PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 2ms

/Sources/ptDcRaw.cpp

https://code.google.com/p/photivo/
C++ | 9640 lines | 8460 code | 595 blank | 585 comment | 3306 complexity | 6bd366b9ee58b4f6fb38567fb6e12d2e MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, LGPL-2.0
  1. /*******************************************************************************
  2. **
  3. ** Photivo
  4. **
  5. ** Copyright (C) 2008,2009 Jos De Laender <jos.de_laender@telenet.be>
  6. ** Copyright (C) 2009-2012 Michael Munzert <mail@mm-log.com>
  7. ** Copyright (C) 2011 Bernd Schoeler <brjohn@brother-john.net>
  8. **
  9. ** This file is part of Photivo.
  10. **
  11. ** Photivo is free software: you can redistribute it and/or modify
  12. ** it under the terms of the GNU General Public License version 3
  13. ** as published by the Free Software Foundation.
  14. **
  15. ** Photivo is distributed in the hope that it will be useful,
  16. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ** GNU General Public License for more details.
  19. **
  20. ** You should have received a copy of the GNU General Public License
  21. ** along with Photivo. If not, see <http://www.gnu.org/licenses/>.
  22. **
  23. *******************************************************************************/
  24. /*
  25. ** This is basically the translation into a more or less C++ object of
  26. ** dcraw.c -- Dave Coffin's raw photo decoder
  27. ** Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net
  28. **
  29. *******************************************************************************/
  30. #include "ptDcRaw.h"
  31. #include "ptDefines.h"
  32. #include "ptError.h"
  33. #include "ptConstants.h"
  34. #include "ptCalloc.h"
  35. #include <cassert>
  36. #define NO_JASPER
  37. #ifndef NO_JASPER
  38. #include <jasper/jasper.h>
  39. #endif
  40. // Macro fix for explicit fread returnvalue check.
  41. #define ptfread(ptr,size,n,stream) \
  42. { \
  43. size_t RV = fread(ptr,size,n,stream); \
  44. if (RV != (size_t) n) assert(!ferror(stream)); \
  45. }
  46. #define ptfwrite(ptr,size,n,stream) \
  47. { \
  48. size_t RV = fwrite(ptr,size,n,stream); \
  49. assert(RV == (size_t) n); \
  50. }
  51. #define ptfscanf(file,format,arg) \
  52. { \
  53. int RV = fscanf(file,format,arg); \
  54. assert (RV == 1); \
  55. }
  56. #define ptfgets(str,num,file) \
  57. { \
  58. char* RV = fgets(str,num,file); \
  59. assert (RV); \
  60. }
  61. inline void VAppend(TImage8RawData &AVector, char* AArray, const int ALength) {
  62. char* hEnd = AArray + ALength * sizeof(char);
  63. AVector.insert(AVector.end(), AArray, hEnd);
  64. }
  65. // The class.
  66. #define CLASS ptDcRaw::
  67. CLASS ptDcRaw() {
  68. //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
  69. // This were the original global variables initialized.
  70. // Now moved into constructor.
  71. // All m_UserSetting* are obviously ,uh, usersettings
  72. // that were done via the command line parameters.
  73. m_UserSetting_ShotSelect=0;
  74. m_UserSetting_MaxMultiplier=0;
  75. m_UserSetting_Multiplier[0]=0;
  76. m_UserSetting_Multiplier[1]=0;
  77. m_UserSetting_Multiplier[2]=0;
  78. m_UserSetting_Multiplier[3]=0;
  79. m_UserSetting_HalfSize=0;
  80. m_UserSetting_HotpixelReduction=0;
  81. m_UserSetting_BayerDenoise=0;
  82. m_UserSetting_CfaLineDn=0;
  83. m_UserSetting_GreenEquil=0;
  84. m_UserSetting_CaCorrect=0;
  85. m_UserSetting_CaRed=0;
  86. m_UserSetting_CaBlue=0;
  87. m_UserSetting_AutoWb=0;
  88. m_UserSetting_CameraWb=0;
  89. m_UserSetting_CameraMatrix=-1;
  90. m_UserSetting_GreyBox[0] = 0;
  91. m_UserSetting_GreyBox[1] = 0;
  92. m_UserSetting_GreyBox[2] = 0xFFFF;
  93. m_UserSetting_GreyBox[3] = 0xFFFF;
  94. m_UserSetting_photivo_ClipMode = ptClipMode_Clip;
  95. m_UserSetting_photivo_ClipParameter = 0;
  96. m_UserSetting_Quality = 3;
  97. m_UserSetting_BlackPoint = -1;
  98. m_UserSetting_Saturation = -1;
  99. m_UserSetting_InputFileName = NULL;
  100. m_UserSetting_DetailView = 0;
  101. m_UserSetting_DetailViewCropX = 0;
  102. m_UserSetting_DetailViewCropY = 0;
  103. m_UserSetting_DetailViewCropW = 0;
  104. m_UserSetting_DetailViewCropH = 0;
  105. m_UserSetting_BadPixelsFileName = NULL;
  106. m_UserSetting_DarkFrameFileName = NULL;
  107. m_UserSetting_AdjustMaximum = 0;
  108. m_UserSetting_DenoiseThreshold = 0;
  109. m_UserSetting_InterpolationPasses = 0;
  110. m_UserSetting_MedianPasses = 0;
  111. m_UserSetting_ESMedianPasses = 0;
  112. // Safety settings to have NULL on uninitialized images.
  113. m_Image = NULL;
  114. m_Image_AfterPhase1 = NULL;
  115. m_Image_AfterPhase2 = NULL;
  116. m_Image_AfterPhase3 = NULL;
  117. m_Image_AfterPhase4 = NULL;
  118. // Some other pointers that are in a dynamic environment better NULL.
  119. m_MetaData = NULL;
  120. m_InputFile = NULL;
  121. m_Thumb.clear();
  122. ResetNonUserSettings();
  123. }
  124. ////////////////////////////////////////////////////////////////////////////////
  125. //
  126. // Destructor
  127. // Deallocate everything dynamic.
  128. //
  129. ////////////////////////////////////////////////////////////////////////////////
  130. CLASS ~ptDcRaw() {
  131. //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
  132. FREE(m_UserSetting_InputFileName);
  133. FREE(m_UserSetting_BadPixelsFileName);
  134. FREE(m_UserSetting_DarkFrameFileName);
  135. FREE(m_Image);
  136. FREE(m_Image_AfterPhase1);
  137. FREE(m_Image_AfterPhase2);
  138. FREE(m_Image_AfterPhase3);
  139. FCLOSE(m_InputFile);
  140. FREE(m_MetaData);
  141. }
  142. ////////////////////////////////////////////////////////////////////////////////
  143. //
  144. // ResetNonUserSettings
  145. // Reset all variables except user settings.
  146. // This is for second entry support.
  147. //
  148. ////////////////////////////////////////////////////////////////////////////////
  149. void CLASS ResetNonUserSettings() {
  150. // Safety settings to have NULL on uninitialized images.
  151. // And freeing the underlying memory (which was long time a leak !)
  152. // FREE(NULL) is safe, so the beginsituation is fine too.
  153. // FREE implies setting of the pointer to NULL
  154. FREE(m_Image);
  155. FREE(m_Image_AfterPhase1);
  156. FREE(m_Image_AfterPhase2);
  157. FREE(m_Image_AfterPhase3);
  158. FREE(m_Image_AfterPhase4);
  159. // Some other pointers that are in a dynamic environment better NULL.
  160. // Same remarks as above.
  161. FREE(m_MetaData);
  162. FCLOSE(m_InputFile);
  163. // This was originally in the identify code, but which is called
  164. // anyway in the beginning. So this is simply global initialization like
  165. // anything else.
  166. m_Tiff_Flip = m_Flip = -1; /* 0 is valid, so -1 is unknown */
  167. m_Filters = (unsigned)(-1); // hack not to change dcraw.
  168. m_RawHeight = m_RawWidth = m_Fuji_Width = m_IsFuji = fuji_layout = cr2_slice[0] = 0;
  169. m_WhiteLevel = m_Height = m_Width = m_TopMargin = m_LeftMargin = 0;
  170. m_ColorDescriptor[0] = m_Description[0] = m_Artist[0] = m_CameraMake[0] = m_CameraModel[0] = m_CameraModelBis[0] = 0;
  171. m_IsoSpeed = m_Shutter = m_Aperture = m_FocalLength = unique_id = 0;
  172. m_Tiff_NrIFDs = 0;
  173. memset (m_Tiff_IFD, 0, sizeof m_Tiff_IFD);
  174. memset (white, 0, sizeof white);
  175. m_ThumbOffset = m_ThumbLength = m_ThumbWidth = m_ThumbHeight = 0;
  176. m_LoadRawFunction = m_ThumbLoadRawFunction = 0;
  177. m_WriteThumb = &CLASS jpeg_thumb;
  178. m_Data_Offset = m_MetaLength = m_Tiff_bps = m_Tiff_Compress = 0;
  179. m_Kodak_cbpp = zero_after_ff = m_DNG_Version = m_Load_Flags = 0;
  180. m_TimeStamp = m_ShotOrder = m_Tiff_Samples = m_BlackLevel = m_IsFoveon = 0;
  181. for (int k=0; k<8; k++) m_CBlackLevel[k] = 0;
  182. m_MixGreen = m_ProfileLength = data_error = m_ZeroIsBad = 0;
  183. m_PixelAspect = m_IsRaw = m_RawColor = 1; m_RawColorPhotivo = 0;
  184. m_TileWidth = m_TileLength = 0;
  185. m_Raw_Image = 0;
  186. memset (m_Mask, 0, sizeof m_Mask);
  187. for (int i=0; i < 4; i++) {
  188. short c;
  189. ASSIGN(m_CameraMultipliers[i], i == 1);
  190. ASSIGN(m_PreMultipliers[i], i < 3);
  191. ASSIGN(m_D65Multipliers[i], i < 3);
  192. for (c=0; c<3; c++) m_cmatrix[c][i] = 0;
  193. for (c=0; c<3; c++) m_MatrixCamRGBToSRGB[c][i] = c == i;
  194. }
  195. m_Colors = 3;
  196. for (int i=0; i < 0x10000; i++) m_Curve[i] = i;
  197. m_Gamma[0] = 0.45;
  198. m_Gamma[1] = 4.50;
  199. m_Gamma[2] = 0;
  200. m_Gamma[3] = 0;
  201. m_Gamma[4] = 0;
  202. m_Gamma[5] = 0;
  203. m_getbithuff_bitbuf=0;
  204. m_getbithuff_reset=0;
  205. m_getbithuff_vbits=0;
  206. m_ph1_bithuffbitbuf=0;
  207. m_ph1_bithuffvbits=0;
  208. for (int i = 0; i < 0x4000; i++) m_pana_bits_buf[i] = 0;
  209. m_pana_bits_vbits = 0;
  210. for (int i = 0; i < 4096; i++) jpeg_buffer[i] = 0;
  211. for (int i = 0; i < 128; i++) m_sony_decrypt_pad[i] = 0;
  212. m_sony_decrypt_p = 0;
  213. for (int i = 0; i < 1024; i++) m_foveon_decoder_huff[i] = 0;
  214. for (int i = 0; i < 4; i++) {
  215. for (int j = 0; j < 3; j++) {
  216. MatrixXYZToCam[i][j] = 0.0;
  217. }
  218. }
  219. ToCamFunctionInited = 0;
  220. for (int i = 0; i < 0x20000; i++) ToLABFunctionTable[i] = 0.0;
  221. ToLABFunctionInited = 0;
  222. for (int i = 0; i < 3; i++) {
  223. for (int j = 0; j < 4; j++) {
  224. MatrixCamToXYZ[i][j] = 0.0;
  225. }
  226. }
  227. }
  228. /*
  229. In order to inline this calculation, I make the risky
  230. assumption that all filter patterns can be described
  231. by a repeating pattern of eight rows and two columns
  232. Do not use the FC or BAYER macros with the Leaf CatchLight,
  233. because its pattern is 16x16, not 2x8.
  234. Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
  235. PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
  236. 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
  237. 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
  238. 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
  239. 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
  240. 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
  241. 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
  242. 4 C Y C Y C Y 4 Y C Y C Y C
  243. PowerShot A5 5 G M G M G M 5 G M G M G M
  244. 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
  245. 7 M G M G M G 7 M G M G M G
  246. 0 1 2 3 4 5
  247. 0 C Y C Y C Y
  248. 1 G M G M G M
  249. 2 C Y C Y C Y
  250. 3 M G M G M G
  251. All RGB cameras use one of these Bayer grids:
  252. 0x16161616: 0x61616161: 0x49494949: 0x94949494:
  253. 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
  254. 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
  255. 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
  256. 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
  257. 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
  258. */
  259. #define RAW(row,col) \
  260. m_Raw_Image[(row)*m_RawWidth+(col)]
  261. #define FC(row,col) \
  262. (m_Filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
  263. #define BAYER(row,col) \
  264. m_Image[(row)*m_Width + (col)][FC(row,col)]
  265. // old: m_Image[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][FC(row,col)]
  266. #define BAYER2(row,col) \
  267. m_Image[(row)*m_Width + (col)][fcol(row,col)]
  268. int CLASS fcol (int row, int col)
  269. {
  270. static const char filter[16][16] =
  271. { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
  272. { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
  273. { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
  274. { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
  275. { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
  276. { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
  277. { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
  278. { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
  279. { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
  280. { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
  281. { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
  282. { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
  283. { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
  284. { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
  285. { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
  286. { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
  287. static const char filter2[6][6] =
  288. { { 1,1,0,1,1,2 },
  289. { 1,1,2,1,1,0 },
  290. { 2,0,1,0,2,1 },
  291. { 1,1,2,1,1,0 },
  292. { 1,1,0,1,1,2 },
  293. { 0,2,1,2,0,1 } };
  294. if (m_Filters == 1) return filter[(row+m_TopMargin)&15][(col+m_LeftMargin)&15];
  295. if (m_Filters == 2) return filter2[(row+6) % 6][(col+6) % 6];
  296. return FC(row,col);
  297. }
  298. #ifndef __GLIBC__
  299. char* CLASS my_memmem (char *haystack, size_t haystacklen,
  300. char *neepte, size_t neeptelen)
  301. {
  302. char *c;
  303. for (c = haystack; c <= haystack + haystacklen - neeptelen; c++)
  304. if (!memcmp (c, neepte, neeptelen))
  305. return c;
  306. return 0;
  307. }
  308. #define memmem my_memmem
  309. #endif
  310. float rgb_cam[3][4];
  311. const double xyz_rgb[3][3] = { /* XYZ from RGB */
  312. { 0.412453, 0.357580, 0.180423 },
  313. { 0.212671, 0.715160, 0.072169 },
  314. { 0.019334, 0.119193, 0.950227 } };
  315. const float d65_white[3] = { 0.950456, 1, 1.088754 };
  316. // Now everything importent is set up, so we can include external demosaicers
  317. #include "dcb/dcb_demosaicing.c"
  318. #include "dcb/dcb_demosaicing_old.c"
  319. #include "vcd/ahd_interpolate_mod.c"
  320. #include "vcd/ahd_partial_interpolate.c"
  321. #include "vcd/refinement.c"
  322. #include "vcd/vcd_interpolate.c"
  323. #include "vcd/es_median_filter.c"
  324. #include "vcd/median_filter_new.c"
  325. #include "perfectraw/lmmse_interpolate.c"
  326. #include "rawtherapee/amaze_interpolate.c"
  327. #include "rawtherapee/cfa_line_dn.c"
  328. #include "rawtherapee/ca_correct.c"
  329. #include "rawtherapee/green_equil.c"
  330. void CLASS merror (void *ptr, const char *where)
  331. {
  332. if (ptr) return;
  333. fprintf (stderr,_("%s: Out of memory in %s\n"), m_UserSetting_InputFileName, where);
  334. longjmp (m_Failure, 1);
  335. }
  336. void CLASS derror()
  337. {
  338. if (!data_error) {
  339. fprintf (stderr, "%s: ", m_UserSetting_InputFileName);
  340. if (feof(m_InputFile))
  341. fprintf (stderr,_("Unexpected end of file\n"));
  342. else
  343. //fprintf (stderr,_("Corrupt data near 0x%lx\n"), (int64_t) ftell(m_InputFile));
  344. fprintf (stderr,_("Corrupt data near 0x%lx\n"), (long unsigned int) ftell(m_InputFile));
  345. }
  346. data_error++;
  347. }
  348. uint16_t CLASS sget2 (uint8_t *s)
  349. {
  350. if (m_ByteOrder == 0x4949) /* "II" means little-endian */
  351. return s[0] | s[1] << 8;
  352. else /* "MM" means big-endian */
  353. return s[0] << 8 | s[1];
  354. }
  355. uint16_t CLASS get2()
  356. {
  357. uint8_t str[2] = { 0xff,0xff };
  358. ptfread (str, 1, 2, m_InputFile);
  359. return sget2(str);
  360. }
  361. unsigned CLASS sget4 (uint8_t *s)
  362. {
  363. if (m_ByteOrder == 0x4949)
  364. return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
  365. else
  366. return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
  367. }
  368. #define sget4(s) sget4((uint8_t *)s)
  369. unsigned CLASS get4()
  370. {
  371. uint8_t str[4] = { 0xff,0xff,0xff,0xff };
  372. ptfread (str, 1, 4, m_InputFile);
  373. return sget4(str);
  374. }
  375. unsigned CLASS getint (int type)
  376. {
  377. return type == 3 ? get2() : get4();
  378. }
  379. float CLASS int_to_float (int i)
  380. {
  381. union { int i; float f; } u;
  382. u.i = i;
  383. return u.f;
  384. }
  385. double CLASS getreal (int type)
  386. {
  387. union { char c[8]; double d; } u;
  388. int i, rev;
  389. switch (type) {
  390. case 3: return (unsigned short) get2();
  391. case 4: return (unsigned int) get4();
  392. case 5: u.d = (unsigned int) get4();
  393. return u.d / (unsigned int) get4();
  394. case 8: return (signed short) get2();
  395. case 9: return (signed int) get4();
  396. case 10: u.d = (signed int) get4();
  397. return u.d / (signed int) get4();
  398. case 11: return int_to_float (get4());
  399. case 12:
  400. rev = 7 * ((m_ByteOrder == 0x4949) == (ntohs(0x1234) == 0x1234));
  401. for (i=0; i < 8; i++)
  402. u.c[i ^ rev] = fgetc(m_InputFile);
  403. return u.d;
  404. default: return fgetc(m_InputFile);
  405. }
  406. }
  407. void CLASS read_shorts (uint16_t *pixel, int count)
  408. {
  409. if (fread (pixel, 2, count, m_InputFile) < (size_t) count) derror();
  410. if ((m_ByteOrder == 0x4949) == (ntohs(0x1234) == 0x1234))
  411. swab ((char *)pixel, (char *)pixel, count*2);
  412. }
  413. /* -> 1438
  414. void CLASS canon_black (double dark[2], int nblack)
  415. {
  416. int c, diff, row, col;
  417. if (!nblack) return;
  418. for (c=0; c<2; c++) dark[c] /= nblack >> 1;
  419. if ((diff = (int)(dark[0] - dark[1])))
  420. for (row=0; row < m_Height; row++)
  421. for (col=1; col < m_Width; col+=2)
  422. BAYER(row,col) += diff;
  423. dark[1] += diff;
  424. m_BlackLevel = (unsigned)((dark[0] + dark[1] + 1) / 2);
  425. }
  426. */
  427. void CLASS canon_600_fixed_wb (int temp)
  428. {
  429. static const short mul[4][5] = {
  430. { 667, 358,397,565,452 },
  431. { 731, 390,367,499,517 },
  432. { 1119, 396,348,448,537 },
  433. { 1399, 485,431,508,688 } };
  434. int lo, hi, i;
  435. float frac=0;
  436. for (lo=4; --lo; )
  437. if (*mul[lo] <= temp) break;
  438. for (hi=0; hi < 3; hi++)
  439. if (*mul[hi] >= temp) break;
  440. if (lo != hi)
  441. frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
  442. for (i=1; i < 5; i++)
  443. ASSIGN(m_D65Multipliers[i-1],1/(frac * mul[hi][i] + (1-frac) * mul[lo][i]));
  444. }
  445. /* Return values: 0 = white 1 = near white 2 = not white */
  446. int CLASS canon_600_color (int ratio[2], int mar)
  447. {
  448. int clipped=0, target, miss;
  449. if (flash_used) {
  450. if (ratio[1] < -104)
  451. { ratio[1] = -104; clipped = 1; }
  452. if (ratio[1] > 12)
  453. { ratio[1] = 12; clipped = 1; }
  454. } else {
  455. if (ratio[1] < -264 || ratio[1] > 461) return 2;
  456. if (ratio[1] < -50)
  457. { ratio[1] = -50; clipped = 1; }
  458. if (ratio[1] > 307)
  459. { ratio[1] = 307; clipped = 1; }
  460. }
  461. target = flash_used || ratio[1] < 197
  462. ? -38 - (398 * ratio[1] >> 10)
  463. : -123 + (48 * ratio[1] >> 10);
  464. if (target - mar <= ratio[0] &&
  465. target + 20 >= ratio[0] && !clipped) return 0;
  466. miss = target - ratio[0];
  467. if (abs(miss) >= mar*4) return 2;
  468. if (miss < -20) miss = -20;
  469. if (miss > mar) miss = mar;
  470. ratio[0] = target - miss;
  471. return 1;
  472. }
  473. void CLASS canon_600_auto_wb()
  474. {
  475. int mar, row, col, i, j, st, count[] = { 0,0 };
  476. int test[8], total[2][8], ratio[2][2], stat[2];
  477. memset (&total, 0, sizeof total);
  478. i = int ( canon_ev + 0.5 );
  479. if (i < 10) mar = 150;
  480. else if (i > 12) mar = 20;
  481. else mar = 280 - 20 * i;
  482. if (flash_used) mar = 80;
  483. for (row=14; row < m_Height-14; row+=4)
  484. for (col=10; col < m_Width; col+=2) {
  485. for (i=0; i < 8; i++)
  486. test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
  487. BAYER(row+(i >> 1),col+(i & 1));
  488. for (i=0; i < 8; i++)
  489. if (test[i] < 150 || test[i] > 1500) goto next;
  490. for (i=0; i < 4; i++)
  491. if (abs(test[i] - test[i+4]) > 50) goto next;
  492. for (i=0; i < 2; i++) {
  493. for (j=0; j < 4; j+=2)
  494. ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
  495. stat[i] = canon_600_color (ratio[i], mar);
  496. }
  497. if ((st = stat[0] | stat[1]) > 1) goto next;
  498. for (i=0; i < 2; i++)
  499. if (stat[i])
  500. for (j=0; j < 2; j++)
  501. test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
  502. for (i=0; i < 8; i++)
  503. total[st][i] += test[i];
  504. count[st]++;
  505. next: ;
  506. }
  507. if (count[0] | count[1]) {
  508. st = count[0]*200 < count[1];
  509. for (i=0; i < 4; i++)
  510. ASSIGN(m_D65Multipliers[i], 1.0 / (total[st][i] + total[st][i+4]));
  511. }
  512. }
  513. void CLASS canon_600_coeff()
  514. {
  515. static const short table[6][12] = {
  516. { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
  517. { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 },
  518. { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 },
  519. { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 },
  520. { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
  521. { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } };
  522. int t=0, i, c;
  523. float mc, yc;
  524. mc = VALUE(m_D65Multipliers[1]) / VALUE(m_D65Multipliers[2]);
  525. yc = VALUE(m_D65Multipliers[3]) / VALUE(m_D65Multipliers[2]);
  526. if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
  527. if (mc > 1.28 && mc <= 2) {
  528. if (yc < 0.8789) t=3;
  529. else if (yc <= 2) t=4;
  530. }
  531. if (flash_used) t=5;
  532. for (m_RawColor = i=0; i < 3; i++)
  533. for (c=0; c < m_Colors; c++)
  534. m_MatrixCamRGBToSRGB[i][c] = table[t][i*4 + c] / 1024.0;
  535. }
  536. void CLASS canon_600_load_raw()
  537. {
  538. uint8_t data[1120], *dp;
  539. uint16_t *pix;
  540. int irow, row;
  541. for (irow=row=0; irow < m_Height; irow++) {
  542. if (fread (data, 1, 1120, m_InputFile) < 1120) derror();
  543. pix = m_Raw_Image + row*m_RawWidth;
  544. for (dp=data; dp < data+1120; dp+=10, pix+=8) {
  545. pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
  546. pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
  547. pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
  548. pix[3] = (dp[4] << 2) + (dp[1] & 3);
  549. pix[4] = (dp[5] << 2) + (dp[9] & 3);
  550. pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
  551. pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
  552. pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
  553. }
  554. if ((row+=2) > m_Height) row = 1;
  555. }
  556. }
  557. void CLASS canon_600_correct()
  558. {
  559. int row, col, val;
  560. static const short mul[4][2] =
  561. { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
  562. for (row=0; row < m_Height; row++)
  563. for (col=0; col < m_Width; col++) {
  564. if ((val = BAYER(row,col) - m_BlackLevel) < 0) val = 0;
  565. val = val * mul[row & 3][col & 1] >> 9;
  566. BAYER(row,col) = val;
  567. }
  568. canon_600_fixed_wb(1311);
  569. canon_600_auto_wb();
  570. canon_600_coeff();
  571. m_WhiteLevel = (0x3ff - m_BlackLevel) * 1109 >> 9;
  572. m_BlackLevel = 0;
  573. }
  574. int CLASS canon_s2is()
  575. {
  576. unsigned row;
  577. for (row=0; row < 100; row++) {
  578. fseek (m_InputFile, row*3340 + 3284, SEEK_SET);
  579. if (getc(m_InputFile) > 15) return 1;
  580. }
  581. return 0;
  582. }
  583. /*
  584. getbits(-1) initializes the buffer
  585. getbits(n) where 0 <= n <= 25 returns an n-bit integer
  586. */
  587. unsigned CLASS getbithuff(int nbits,uint16_t *huff)
  588. {
  589. // unsigned c;
  590. int c;
  591. if (nbits == -1)
  592. return m_getbithuff_bitbuf = m_getbithuff_vbits = m_getbithuff_reset = 0;
  593. if (nbits == 0 || m_getbithuff_vbits < 0) return 0;
  594. while (!m_getbithuff_reset && m_getbithuff_vbits < nbits && (c = fgetc(m_InputFile)) != EOF &&
  595. !(m_getbithuff_reset = zero_after_ff && c == 0xff && fgetc(m_InputFile))) {
  596. m_getbithuff_bitbuf = (m_getbithuff_bitbuf << 8) + (uint8_t) c;
  597. m_getbithuff_vbits += 8;
  598. }
  599. c = m_getbithuff_bitbuf << (32-m_getbithuff_vbits) >> (32-nbits);
  600. if (huff) {
  601. m_getbithuff_vbits -= huff[c] >> 8;
  602. c = (uint8_t) huff[c];
  603. } else
  604. m_getbithuff_vbits -= nbits;
  605. if (m_getbithuff_vbits < 0) derror();
  606. return c;
  607. }
  608. #define getbits(n) getbithuff(n,0)
  609. #define gethuff(h) getbithuff(*h,h+1)
  610. /*
  611. Construct a decode tree according the specification in *source.
  612. The first 16 bytes specify how many codes should be 1-bit, 2-bit
  613. 3-bit, etc. Bytes after that are the leaf values.
  614. For example, if the source is
  615. { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
  616. 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
  617. then the code is
  618. 00 0x04
  619. 010 0x03
  620. 011 0x05
  621. 100 0x06
  622. 101 0x02
  623. 1100 0x07
  624. 1101 0x01
  625. 11100 0x08
  626. 11101 0x09
  627. 11110 0x00
  628. 111110 0x0a
  629. 1111110 0x0b
  630. 1111111 0xff
  631. */
  632. uint16_t * CLASS make_decoder_ref (const uint8_t **source)
  633. {
  634. int max, len, h, i, j;
  635. const uint8_t *count;
  636. uint16_t *huff;
  637. count = (*source += 16) - 17;
  638. for (max=16; max && !count[max]; max--) {} ;
  639. huff = (uint16_t *) CALLOC (1 + (1 << max), sizeof *huff);
  640. merror (huff, "make_decoder()");
  641. huff[0] = max;
  642. for (h=len=1; len <= max; len++)
  643. for (i=0; i < count[len]; i++, ++*source)
  644. for (j=0; j < 1 << (max-len); j++)
  645. if (h <= 1 << max)
  646. huff[h++] = len << 8 | **source;
  647. return huff;
  648. }
  649. uint16_t * CLASS make_decoder (const uint8_t *source)
  650. {
  651. return make_decoder_ref (&source);
  652. }
  653. void CLASS crw_init_tables (unsigned table, uint16_t *huff[2])
  654. {
  655. static const uint8_t first_tree[3][29] = {
  656. { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
  657. 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
  658. { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
  659. 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
  660. { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
  661. 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
  662. };
  663. static const uint8_t second_tree[3][180] = {
  664. { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
  665. 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
  666. 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
  667. 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
  668. 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
  669. 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
  670. 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
  671. 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
  672. 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
  673. 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
  674. 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
  675. 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
  676. 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
  677. 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
  678. 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
  679. { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
  680. 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
  681. 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
  682. 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
  683. 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
  684. 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
  685. 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
  686. 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
  687. 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
  688. 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
  689. 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
  690. 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
  691. 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
  692. 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
  693. 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
  694. { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
  695. 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
  696. 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
  697. 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
  698. 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
  699. 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
  700. 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
  701. 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
  702. 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
  703. 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
  704. 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
  705. 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
  706. 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
  707. 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
  708. 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
  709. };
  710. if (table > 2) table = 2;
  711. huff[0] = make_decoder ( first_tree[table]);
  712. huff[1] = make_decoder (second_tree[table]);
  713. }
  714. /*
  715. Return 0 if the image starts with compressed data,
  716. 1 if it starts with uncompressed low-order bits.
  717. In Canon compressed data, 0xff is always followed by 0x00.
  718. */
  719. int CLASS canon_has_lowbits()
  720. {
  721. uint8_t test[0x4000];
  722. int ret=1, i;
  723. fseek (m_InputFile, 0, SEEK_SET);
  724. ptfread (test, 1, sizeof test, m_InputFile);
  725. for (i=540; i < (int)(sizeof test) - 1; i++)
  726. if (test[i] == 0xff) {
  727. if (test[i+1]) return 1;
  728. ret=0;
  729. }
  730. return ret;
  731. }
  732. void CLASS canon_load_raw()
  733. {
  734. uint16_t *pixel, *prow, *huff[2];
  735. int nblocks, lowbits, i, c, row, r, save, val;
  736. int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
  737. crw_init_tables (m_Tiff_Compress,huff);
  738. lowbits = canon_has_lowbits();
  739. if (!lowbits) m_WhiteLevel = 0x3ff;
  740. fseek (m_InputFile, 540 + lowbits*m_RawHeight*m_RawWidth/4, SEEK_SET);
  741. zero_after_ff = 1;
  742. getbits(-1);
  743. for (row=0; row < m_RawHeight; row+=8) {
  744. pixel = m_Raw_Image + row*m_RawWidth;
  745. nblocks = MIN (8, m_RawHeight-row) * m_RawWidth >> 6;
  746. for (block=0; block < nblocks; block++) {
  747. memset (diffbuf, 0, sizeof diffbuf);
  748. for (i=0; i < 64; i++ ) {
  749. leaf = gethuff(huff[i>0]);
  750. if (leaf == 0 && i) break;
  751. if (leaf == 0xff) continue;
  752. i += leaf >> 4;
  753. len = leaf & 15;
  754. if (len == 0) continue;
  755. diff = getbits(len);
  756. if ((diff & (1 << (len-1))) == 0)
  757. diff -= (1 << len) - 1;
  758. if (i < 64) diffbuf[i] = diff;
  759. }
  760. diffbuf[0] += carry;
  761. carry = diffbuf[0];
  762. for (i=0; i < 64; i++ ) {
  763. if (pnum++ % m_RawWidth == 0)
  764. base[0] = base[1] = 512;
  765. if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
  766. derror();
  767. }
  768. }
  769. if (lowbits) {
  770. save = ftell(m_InputFile);
  771. fseek (m_InputFile, 26 + row*m_RawWidth/4, SEEK_SET);
  772. for (prow=pixel, i=0; i < m_RawWidth*2; i++) {
  773. c = fgetc(m_InputFile);
  774. for (r=0; r < 8; r+=2, prow++) {
  775. val = (*prow << 2) + ((c >> r) & 3);
  776. if (m_RawWidth == 2672 && val < 512) val += 2;
  777. *prow = val;
  778. }
  779. }
  780. fseek (m_InputFile, save, SEEK_SET);
  781. }
  782. }
  783. FREE(huff[0]);
  784. FREE(huff[1]);
  785. }
  786. /*
  787. Not a full implementation of Lossless JPEG, just
  788. enough to decode Canon, Kodak and Adobe DNG images.
  789. */
  790. struct jhead {
  791. int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
  792. uint16_t *huff[6], *free[4], *row;
  793. };
  794. int CLASS ljpeg_start (struct jhead *jh, int info_only)
  795. {
  796. int c, tag, len;
  797. uint8_t data[0x10000];
  798. const uint8_t *dp;
  799. memset (jh, 0, sizeof *jh);
  800. jh->restart = INT_MAX;
  801. ptfread (data, 2, 1, m_InputFile);
  802. if (data[1] != 0xd8) return 0;
  803. do {
  804. ptfread (data, 2, 2, m_InputFile);
  805. tag = data[0] << 8 | data[1];
  806. len = (data[2] << 8 | data[3]) - 2;
  807. if (tag <= 0xff00) return 0;
  808. ptfread (data, 1, len, m_InputFile);
  809. switch (tag) {
  810. case 0xffc3:
  811. jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
  812. case 0xffc0:
  813. jh->bits = data[0];
  814. jh->high = data[1] << 8 | data[2];
  815. jh->wide = data[3] << 8 | data[4];
  816. jh->clrs = data[5] + jh->sraw;
  817. if (len == 9 && !m_DNG_Version) getc(m_InputFile);
  818. break;
  819. case 0xffc4:
  820. if (info_only) break;
  821. for (dp = data; dp < data+len && (c = *dp++) < 4; )
  822. jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
  823. break;
  824. case 0xffda:
  825. jh->psv = data[1+data[0]*2];
  826. jh->bits -= data[3+data[0]*2] & 15;
  827. break;
  828. case 0xffdd:
  829. jh->restart = data[0] << 8 | data[1];
  830. }
  831. } while (tag != 0xffda);
  832. if (info_only) return 1;
  833. for (c=0;c<5;c++) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
  834. if (jh->sraw) {
  835. for (c=0;c<4;c++) jh->huff[2+c] = jh->huff[1];
  836. for (c=0;c<(jh->sraw);c++) jh->huff[1+c] = jh->huff[0];
  837. }
  838. jh->row = (uint16_t *) CALLOC (jh->wide*jh->clrs, 4);
  839. merror (jh->row, "ljpeg_start()");
  840. return zero_after_ff = 1;
  841. }
  842. void CLASS ljpeg_end (struct jhead *jh)
  843. {
  844. int c;
  845. for(c=0;c<4;c++) if (jh->free[c]) FREE (jh->free[c]);
  846. FREE (jh->row);
  847. }
  848. int CLASS ljpeg_diff (uint16_t *huff)
  849. {
  850. int len, diff;
  851. len = gethuff(huff);
  852. if (len == 16 && (!m_DNG_Version || m_DNG_Version >= 0x1010000))
  853. return -32768;
  854. diff = getbits(len);
  855. if ((diff & (1 << (len-1))) == 0)
  856. diff -= (1 << len) - 1;
  857. return diff;
  858. }
  859. uint16_t * CLASS ljpeg_row (int jrow, struct jhead *jh)
  860. {
  861. int col, c, diff, pred, spred=0;
  862. uint16_t mark=0, *row[3];
  863. if (jrow * jh->wide % jh->restart == 0) {
  864. for (c=0;c<6;c++) jh->vpred[c] = 1 << (jh->bits-1);
  865. if (jrow) {
  866. fseek(m_InputFile,-2,SEEK_CUR);
  867. do mark = (mark << 8) + (c = fgetc(m_InputFile));
  868. while (c != EOF && mark >> 4 != 0xffd);
  869. }
  870. getbits(-1);
  871. }
  872. for (c=0; c<3; c++) row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
  873. for (col=0; col < jh->wide; col++)
  874. for (c=0; c < jh->clrs; c++) {
  875. diff = ljpeg_diff (jh->huff[c]);
  876. if (jh->sraw && c <= jh->sraw && (col | c))
  877. pred = spred;
  878. else if (col) pred = row[0][-jh->clrs];
  879. else pred = (jh->vpred[c] += diff) - diff;
  880. if (jrow && col) switch (jh->psv) {
  881. case 1: break;
  882. case 2: pred = row[1][0]; break;
  883. case 3: pred = row[1][-jh->clrs]; break;
  884. case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break;
  885. case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break;
  886. case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break;
  887. case 7: pred = (pred + row[1][0]) >> 1; break;
  888. default: pred = 0;
  889. }
  890. if ((**row = pred + diff) >> jh->bits) derror();
  891. if (c <= jh->sraw) spred = **row;
  892. row[0]++; row[1]++;
  893. }
  894. return row[2];
  895. }
  896. void CLASS lossless_jpeg_load_raw()
  897. {
  898. int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
  899. struct jhead jh;
  900. uint16_t *rp;
  901. if (!ljpeg_start (&jh, 0)) return;
  902. jwide = jh.wide * jh.clrs;
  903. TRACEKEYVALS("jh.high","%d",jh.high);
  904. TRACEKEYVALS("jwide","%d",jwide);
  905. for (jrow=0; jrow < jh.high; jrow++) {
  906. rp = ljpeg_row (jrow, &jh);
  907. if (m_Load_Flags & 1)
  908. row = jrow & 1 ? m_Height-1-jrow/2 : jrow/2;
  909. for (jcol=0; jcol < jwide; jcol++) {
  910. val = m_Curve[*rp++];
  911. if (cr2_slice[0]) {
  912. jidx = jrow*jwide + jcol;
  913. i = jidx / (cr2_slice[1]*jh.high);
  914. if ((j = i >= cr2_slice[0]))
  915. i = cr2_slice[0];
  916. jidx -= i * (cr2_slice[1]*jh.high);
  917. row = jidx / cr2_slice[1+j];
  918. col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
  919. }
  920. if (m_RawWidth == 3984 && (col -= 2) < 0)
  921. col += (row--,m_RawWidth);
  922. if (row >= 0) RAW(row,col) = val;
  923. if (++col >= m_RawWidth)
  924. col = (row++,0);
  925. }
  926. }
  927. ljpeg_end(&jh);
  928. // printf("TIEDELIE dark[0]:%f dark[1]:%f nblack:%d\n",dark[0],dark[1],nblack);
  929. }
  930. void CLASS canon_sraw_load_raw()
  931. {
  932. struct jhead jh;
  933. short *rp=0, (*ip)[4];
  934. int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
  935. int v[3]={0,0,0}, ver, hue;
  936. char *cp;
  937. if (!ljpeg_start (&jh, 0)) return;
  938. jwide = (jh.wide >>= 1) * jh.clrs;
  939. for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
  940. scol = ecol;
  941. ecol += cr2_slice[1] * 2 / jh.clrs;
  942. if (!cr2_slice[0] || ecol > m_RawWidth-1) ecol = m_RawWidth & -2;
  943. for (row=0; row < m_Height; row += (jh.clrs >> 1) - 1) {
  944. ip = (short (*)[4]) m_Image + row*m_Width;
  945. for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
  946. if ((jcol %= jwide) == 0)
  947. rp = (short *) ljpeg_row (jrow++, &jh);
  948. if (col >= m_Width) continue;
  949. for (c=0; c< (jh.clrs-2); c++)
  950. ip[col + (c >> 1)*m_Width + (c & 1)][0] = rp[jcol+c];
  951. ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
  952. ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
  953. }
  954. }
  955. }
  956. for (cp=m_CameraModelBis; *cp && !isdigit(*cp); cp++) {};
  957. sscanf (cp, "%d.%d.%d", v, v+1, v+2);
  958. ver = (v[0]*1000 + v[1])*1000 + v[2];
  959. hue = (jh.sraw+1) << 2;
  960. if (unique_id >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
  961. hue = jh.sraw << 1;
  962. ip = (short (*)[4]) m_Image;
  963. rp = ip[0];
  964. for (row=0; row < m_Height; row++, ip+=m_Width) {
  965. if (row & (jh.sraw >> 1))
  966. for (col=0; col < m_Width; col+=2)
  967. for (c=1; c < 3; c++)
  968. if (row == m_Height-1) {
  969. ip[col][c] = ip[col-m_Width][c];
  970. } else {
  971. ip[col][c] = (ip[col-m_Width][c] + ip[col+m_Width][c] + 1) >> 1;
  972. }
  973. for (col=1; col < m_Width; col+=2)
  974. for (c=1; c < 3; c++)
  975. if (col == m_Width-1)
  976. ip[col][c] = ip[col-1][c];
  977. else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
  978. }
  979. for ( ; rp < ip[0]; rp+=4) {
  980. if (unique_id == 0x80000218 ||
  981. unique_id == 0x80000250 ||
  982. unique_id == 0x80000261 ||
  983. unique_id == 0x80000281 ||
  984. unique_id == 0x80000287) {
  985. rp[1] = (rp[1] << 2) + hue;
  986. rp[2] = (rp[2] << 2) + hue;
  987. pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14);
  988. pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
  989. pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
  990. } else {
  991. if (unique_id < 0x80000218) rp[0] -= 512;
  992. pix[0] = rp[0] + rp[2];
  993. pix[2] = rp[0] + rp[1];
  994. pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
  995. }
  996. for (c=0;c<3;c++) rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
  997. }
  998. ljpeg_end(&jh);
  999. m_WhiteLevel = 0x3fff;
  1000. }
  1001. void CLASS adobe_copy_pixel (unsigned row, unsigned col, uint16_t **rp)
  1002. {
  1003. int c;
  1004. if (m_IsRaw == 2 && m_UserSetting_ShotSelect) (*rp)++;
  1005. if (m_Raw_Image) {
  1006. if (row < m_RawHeight && col < m_RawWidth)
  1007. RAW(row,col) = m_Curve[**rp];
  1008. *rp += m_IsRaw;
  1009. } else {
  1010. if (row < m_Height && col < m_Width)
  1011. for (c=0; c < (int32_t)m_Tiff_Samples; c++)
  1012. m_Image[row*m_Width+col][c] = m_Curve[(*rp)[c]];
  1013. *rp += m_Tiff_Samples;
  1014. }
  1015. if (m_IsRaw == 2 && m_UserSetting_ShotSelect) (*rp)--;
  1016. }
  1017. void CLASS lossless_dng_load_raw()
  1018. {
  1019. unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
  1020. struct jhead jh;
  1021. uint16_t *rp;
  1022. while (trow < m_RawHeight) {
  1023. save = ftell(m_InputFile);
  1024. if (m_TileLength < INT_MAX)
  1025. fseek (m_InputFile, get4(), SEEK_SET);
  1026. if (!ljpeg_start (&jh, 0)) break;
  1027. jwide = jh.wide;
  1028. if (m_Filters) jwide *= jh.clrs;
  1029. jwide /= m_IsRaw;
  1030. for (row=col=jrow=0; jrow < (unsigned) jh.high; jrow++) {
  1031. rp = ljpeg_row (jrow, &jh);
  1032. for (jcol=0; jcol < jwide; jcol++) {
  1033. adobe_copy_pixel (trow+row, tcol+col, &rp);
  1034. if (++col >= m_TileWidth || col >= m_RawWidth)
  1035. row += 1 + (col = 0);
  1036. }
  1037. }
  1038. fseek (m_InputFile, save+4, SEEK_SET);
  1039. if ((tcol += m_TileWidth) >= m_RawWidth)
  1040. trow += m_TileLength + (tcol = 0);
  1041. ljpeg_end(&jh);
  1042. }
  1043. }
  1044. void CLASS packed_dng_load_raw()
  1045. {
  1046. uint16_t *pixel, *rp;
  1047. // int row, col;
  1048. unsigned row, col;
  1049. pixel = (uint16_t *) CALLOC (m_RawWidth * m_Tiff_Samples, sizeof *pixel);
  1050. merror (pixel, "packed_dng_load_raw()");
  1051. for (row=0; row < m_RawHeight; row++) {
  1052. if (m_Tiff_bps == 16)
  1053. read_shorts (pixel, m_RawWidth * m_Tiff_Samples);
  1054. else {
  1055. getbits(-1);
  1056. for (col=0; col < m_RawWidth * m_Tiff_Samples; col++)
  1057. pixel[col] = getbits(m_Tiff_bps);
  1058. }
  1059. for (rp=pixel, col=0; col < m_RawWidth; col++)
  1060. adobe_copy_pixel (row, col, &rp);
  1061. }
  1062. FREE (pixel);
  1063. }
  1064. void CLASS pentax_load_raw()
  1065. {
  1066. uint16_t bit[2][15], huff[4097];
  1067. int dep, row, col, diff, c, i;
  1068. uint16_t vpred[2][2] = {{0,0},{0,0}}, hpred[2];
  1069. fseek (m_InputFile, meta_offset, SEEK_SET);
  1070. dep = (get2() + 12) & 15;
  1071. fseek (m_InputFile, 12, SEEK_CUR);
  1072. for(c=0;c<dep;c++) bit[0][c] = get2();
  1073. for(c=0;c<dep;c++) bit[1][c] = fgetc(m_InputFile);
  1074. for(c=0;c<dep;c++)
  1075. for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
  1076. huff[++i] = bit[1][c] << 8 | c;
  1077. huff[0] = 12;
  1078. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  1079. getbits(-1);
  1080. for (row=0; row < m_RawHeight; row++)
  1081. for (col=0; col < m_RawWidth; col++) {
  1082. diff = ljpeg_diff (huff);
  1083. if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  1084. else hpred[col & 1] += diff;
  1085. RAW(row,col) = hpred[col & 1];
  1086. if (hpred[col & 1] >> m_Tiff_bps) derror();
  1087. }
  1088. }
  1089. void CLASS nikon_load_raw()
  1090. {
  1091. static const uint8_t nikon_tree[][32] = {
  1092. { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
  1093. 5,4,3,6,2,7,1,0,8,9,11,10,12 },
  1094. { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */
  1095. 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
  1096. { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */
  1097. 5,4,6,3,7,2,8,1,9,0,10,11,12 },
  1098. { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */
  1099. 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
  1100. { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */
  1101. 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
  1102. { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
  1103. 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
  1104. uint16_t *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
  1105. int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff;
  1106. fseek (m_InputFile, meta_offset, SEEK_SET);
  1107. ver0 = fgetc(m_InputFile);
  1108. ver1 = fgetc(m_InputFile);
  1109. if (ver0 == 0x49 || ver1 == 0x58)
  1110. fseek (m_InputFile, 2110, SEEK_CUR);
  1111. if (ver0 == 0x46) tree = 2;
  1112. if (m_Tiff_bps == 14) tree += 3;
  1113. read_shorts (vpred[0], 4);
  1114. max = 1 << m_Tiff_bps & 0x7fff;
  1115. if ((csize = get2()) > 1)
  1116. step = max / (csize-1);
  1117. if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
  1118. for (i=0; i < csize; i++)
  1119. m_Curve[i*step] = get2();
  1120. for (i=0; i < max; i++)
  1121. m_Curve[i] = ( m_Curve[i-i%step]*(step-i%step) +
  1122. m_Curve[i-i%step+step]*(i%step) ) / step;
  1123. fseek (m_InputFile, meta_offset+562, SEEK_SET);
  1124. split = get2();
  1125. } else if (ver0 != 0x46 && csize <= 0x4001)
  1126. read_shorts (m_Curve, max=csize);
  1127. while (m_Curve[max-2] == m_Curve[max-1]) max--;
  1128. huff = make_decoder(nikon_tree[tree]);
  1129. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  1130. getbits(-1);
  1131. for (min=row=0; row < m_Height; row++) {
  1132. if (split && row == split) {
  1133. FREE(huff);
  1134. huff = make_decoder(nikon_tree[tree+1]);
  1135. max += (min = 16) << 1;
  1136. }
  1137. for (col=0; col < m_RawWidth; col++) {
  1138. i = gethuff(huff);
  1139. len = i & 15;
  1140. shl = i >> 4;
  1141. diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
  1142. if ((diff & (1 << (len-1))) == 0)
  1143. diff -= (1 << len) - !shl;
  1144. if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  1145. else hpred[col & 1] += diff;
  1146. if ((uint16_t)(hpred[col & 1] + min) >= max) derror();
  1147. RAW(row,col) = m_Curve[LIM((int16_t)hpred[col & 1],(int16_t)0,(int16_t)0x3fff)];
  1148. }
  1149. }
  1150. FREE(huff);
  1151. }
  1152. /*
  1153. Returns 1 for a Coolpix 995, 0 for anything else.
  1154. */
  1155. int CLASS nikon_e995()
  1156. {
  1157. int i, histo[256];
  1158. const uint8_t often[] = { 0x00, 0x55, 0xaa, 0xff };
  1159. memset (histo, 0, sizeof histo);
  1160. fseek (m_InputFile, -2000, SEEK_END);
  1161. for (i=0; i < 2000; i++)
  1162. histo[fgetc(m_InputFile)]++;
  1163. for (i=0; i < 4; i++)
  1164. if (histo[often[i]] < 200)
  1165. return 0;
  1166. return 1;
  1167. }
  1168. /*
  1169. Returns 1 for a Coolpix 2100, 0 for anything else.
  1170. */
  1171. int CLASS nikon_e2100()
  1172. {
  1173. uint8_t t[12];
  1174. int i;
  1175. fseek (m_InputFile, 0, SEEK_SET);
  1176. for (i=0; i < 1024; i++) {
  1177. ptfread (t, 1, 12, m_InputFile);
  1178. if (((t[2] & t[4] & t[7] & t[9]) >> 4
  1179. & t[1] & t[6] & t[8] & t[11] & 3) != 3)
  1180. return 0;
  1181. }
  1182. return 1;
  1183. }
  1184. void CLASS nikon_3700()
  1185. {
  1186. int bits; // i;
  1187. uint8_t dp[24];
  1188. static const struct {
  1189. int bits;
  1190. char make[12], model[15];
  1191. } table[] = {
  1192. { 0x00, "PENTAX", "Optio 33WR" },
  1193. { 0x03, "NIKON", "E3200" },
  1194. { 0x32, "NIKON", "E3700" },
  1195. { 0x33, "OLYMPUS", "C740UZ" } };
  1196. fseek (m_InputFile, 3072, SEEK_SET);
  1197. ptfread (dp, 1, 24, m_InputFile);
  1198. bits = (dp[8] & 3) << 4 | (dp[20] & 3);
  1199. for (unsigned i=0; i < sizeof table / sizeof *table; i++)
  1200. if (bits == table[i].bits) {
  1201. strcpy (m_CameraMake, table[i].make );
  1202. strcpy (m_CameraModel, table[i].model);
  1203. }
  1204. }
  1205. /*
  1206. Separates a Minolta DiMAGE Z2 from a Nikon E4300.
  1207. */
  1208. int CLASS minolta_z2()
  1209. {
  1210. unsigned i,nz;
  1211. char tail[424];
  1212. fseek (m_InputFile, (long)(-sizeof tail), SEEK_END);
  1213. ptfread (tail, 1, sizeof tail, m_InputFile);
  1214. for (nz=i=0; i < sizeof tail; i++)
  1215. if (tail[i]) nz++;
  1216. return nz > 20;
  1217. }
  1218. //void CLASS jpeg_thumb ();
  1219. void CLASS ppm_thumb ()
  1220. /* Remember: This function is modified to write the rawÂ’s thumbnail to the
  1221. m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
  1222. */
  1223. {
  1224. char *thumb;
  1225. m_ThumbLength = m_ThumbWidth*m_ThumbHeight*3;
  1226. thumb = (char *) MALLOC (m_ThumbLength);
  1227. merror (thumb, "ppm_thumb()");
  1228. //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
  1229. QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
  1230. VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
  1231. ptfread (thumb, 1, m_ThumbLength, m_InputFile);
  1232. VAppend(m_Thumb, thumb, m_ThumbLength);
  1233. FREE (thumb);
  1234. }
  1235. void CLASS ppm16_thumb()
  1236. {
  1237. int i;
  1238. char *thumb;
  1239. m_ThumbLength = m_ThumbWidth*m_ThumbHeight*3;
  1240. thumb = (char *) CALLOC (m_ThumbLength,2);
  1241. merror (thumb, "ppm16_thumb()");
  1242. read_shorts ((uint16_t *) thumb, m_ThumbLength);
  1243. for (i=0; i < (int32_t)m_ThumbLength; i++)
  1244. thumb[i] = ((uint16_t *) thumb)[i] >> 8;
  1245. QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
  1246. VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
  1247. //fprintf (ofp, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
  1248. //fwrite (thumb, 1, m_ThumbLength, ofp);
  1249. VAppend(m_Thumb, thumb, m_ThumbLength);
  1250. FREE (thumb);
  1251. }
  1252. void CLASS layer_thumb ()
  1253. /* Remember: This function is modified to write the rawÂ’s thumbnail to the
  1254. m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
  1255. */
  1256. // TODO: Tests needed: What format is this? Can it be read by QPixmap?
  1257. {
  1258. // int i, c;
  1259. int c;
  1260. char *thumb, map[][4] = { "012","102" };
  1261. m_Colors = m_ThumbMisc >> 5 & 7;
  1262. m_ThumbLength = m_ThumbWidth*m_ThumbHeight;
  1263. thumb = (char *) CALLOC (m_Colors, m_ThumbLength);
  1264. merror (thumb, "layer_thumb()");
  1265. //fprintf (m_OutputFile, "P%d\n%d %d\n255\n", 5 + (m_Colors >> 1), m_ThumbWidth, m_ThumbHeight);
  1266. QString dummy = QString("P%1\n%2 %3\n255\n")
  1267. .arg(5 + (m_Colors >> 1)).arg(m_ThumbWidth).arg(m_ThumbHeight);
  1268. VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
  1269. ptfread (thumb, m_ThumbLength, m_Colors, m_InputFile);
  1270. for (unsigned i=0; i < m_ThumbLength; i++) {
  1271. for (c=0; c < m_Colors; c++) {
  1272. //putc (thumb[i+m_ThumbLength*(map[m_ThumbMisc >> 8][c]-'0')], m_OutputFile);
  1273. #pragma GCC diagnostic push
  1274. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  1275. m_Thumb.push_back(thumb[i+m_ThumbLength*(map[m_ThumbMisc >> 8][c]-'0')]);
  1276. #pragma GCC diagnostic pop
  1277. }
  1278. }
  1279. FREE (thumb);
  1280. }
  1281. void CLASS rollei_thumb ()
  1282. /* Remember: This function is modified to write the rawÂ’s thumbnail to the
  1283. m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
  1284. */
  1285. // TODO: Tests needed: What format is this? Can it be read by QPixmap?
  1286. {
  1287. unsigned i;
  1288. uint16_t *thumb;
  1289. m_ThumbLength = m_ThumbWidth * m_ThumbHeight;
  1290. thumb = (uint16_t *) CALLOC (m_ThumbLength, 2);
  1291. merror (thumb, "rollei_thumb()");
  1292. //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
  1293. QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
  1294. VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
  1295. read_shorts (thumb, m_ThumbLength);
  1296. for (i=0; i < m_ThumbLength; i++) {
  1297. //putc (thumb[i] << 3, m_OutputFile);
  1298. //putc (thumb[i] >> 5 << 2, m_OutputFile);
  1299. //putc (thumb[i] >> 11 << 3, m_OutputFile);
  1300. #pragma GCC diagnostic push
  1301. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  1302. m_Thumb.push_back(thumb[i] << 3);
  1303. m_Thumb.push_back(thumb[i] >> 5 << 2);
  1304. m_Thumb.push_back(thumb[i] >> 11 << 3);
  1305. #pragma GCC diagnostic pop
  1306. }
  1307. FREE (thumb);
  1308. }
  1309. void CLASS rollei_load_raw()
  1310. {
  1311. uint8_t pixel[10];
  1312. unsigned iten=0, isix, i, buffer=0, todo[16];
  1313. isix = m_RawWidth * m_RawHeight * 5 / 8;
  1314. while (fread (pixel, 1, 10, m_InputFile) == 10) {
  1315. for (i=0; i < 10; i+=2) {
  1316. todo[i] = iten++;
  1317. todo[i+1] = pixel[i] << 8 | pixel[i+1];
  1318. buffer = pixel[i] >> 2 | buffer << 6;
  1319. }
  1320. for ( ; i < 16; i+=2) {
  1321. todo[i] = isix++;
  1322. todo[i+1] = buffer >> (14-i)*5;
  1323. }
  1324. for (i=0; i < 16; i+=2)
  1325. m_Raw_Image[todo[i]] = (todo[i+1] & 0x3ff);
  1326. }
  1327. m_WhiteLevel = 0x3ff;
  1328. }
  1329. int CLASS raw (unsigned row, unsigned col)
  1330. {
  1331. return (row < m_RawHeight && col < m_RawWidth) ? RAW(row,col) : 0;
  1332. }
  1333. void CLASS phase_one_flat_field (int is_float, int nc)
  1334. {
  1335. uint16_t head[8];
  1336. unsigned wide, y, x, c, rend, cend, row, col;
  1337. float *mrow, num, mult[4];
  1338. read_shorts (head, 8);
  1339. wide = head[2] / head[4];
  1340. mrow = (float *) CALLOC (nc*wide, sizeof *mrow);
  1341. merror (mrow, "phase_one_flat_field()");
  1342. for (y=0; y < (unsigned) (head[3] / head[5]); y++) {
  1343. for (x=0; x < wide; x++)
  1344. for (c=0; c < (unsigned) nc; c+=2) {
  1345. num = is_float ? getreal(11) : get2()/32768.0;
  1346. if (y==0) mrow[c*wide+x] = num;
  1347. else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
  1348. }
  1349. if (y==0) continue;
  1350. rend = head[1] + y*head[5];
  1351. for (row = rend-head[5]; row < m_RawHeight && row < rend; row++) {
  1352. for (x=1; x < wide; x++) {
  1353. for (c=0; c < (unsigned) nc; c+=2) {
  1354. mult[c] = mrow[c*wide+x-1];
  1355. mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
  1356. }
  1357. cend = head[0] + x*head[4];
  1358. for (col = cend-head[4]; col < m_RawWidth && col < cend; col++) {
  1359. c = nc > 2 ? FC(row-m_TopMargin,col-m_LeftMargin) : 0;
  1360. if (!(c & 1)) {
  1361. c = unsigned(RAW(row,col) * mult[c]);
  1362. RAW(row,col) = MIN((int32_t)c,65535);
  1363. }
  1364. for (c=0; c < (unsigned) nc; c+=2)
  1365. mult[c] += mult[c+1];
  1366. }
  1367. }
  1368. for (x=0; x < wide; x++)
  1369. for (c=0; c < (unsigned) nc; c+=2)
  1370. mrow[c*wide+x] += mrow[(c+1)*wide+x];
  1371. }
  1372. }
  1373. FREE (mrow);
  1374. }
  1375. void CLASS phase_one_correct()
  1376. {
  1377. unsigned entries, tag, data, save, col, row, type;
  1378. int len, i, j, k, cip, val[4], dev[4], sum, max;
  1379. int head[9], diff, mindiff=INT_MAX, off_412=0;
  1380. static const signed char dir[12][2] =
  1381. { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
  1382. {-2,-2}, {-2,2}, {2,-2}, {2,2} };
  1383. float poly[8], num, cfrac, frac, mult[2], *yval[2];
  1384. uint16_t *xval[2];
  1385. if (m_UserSetting_HalfSize || !m_MetaLength) return;
  1386. TRACEKEYVALS("Phase One correction","%s","");
  1387. fseek (m_InputFile, meta_offset, SEEK_SET);
  1388. m_ByteOrder = get2();
  1389. fseek (m_InputFile, 6, SEEK_CUR);
  1390. fseek (m_InputFile, meta_offset+get4(), SEEK_SET);
  1391. entries = get4(); get4();
  1392. while (entries--) {
  1393. tag = get4();
  1394. len = get4();
  1395. data = get4();
  1396. save = ftell(m_InputFile);
  1397. fseek (m_InputFile, meta_offset+data, SEEK_SET);
  1398. if (tag == 0x419) { /* Polynomial curve */
  1399. for (get4(), i=0; i < 8; i++)
  1400. poly[i] = getreal(11);
  1401. poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
  1402. for (i=0; i < 0x10000; i++) {
  1403. num = (poly[5]*i + poly[3])*i + poly[1];
  1404. m_Curve[i] = (uint16_t) LIM((int32_t)num,0,65535);
  1405. } goto apply; /* apply to right half */
  1406. } else if (tag == 0x41a) { /* Polynomial curve */
  1407. for (i=0; i < 4; i++)
  1408. poly[i] = getreal(11);
  1409. for (i=0; i < 0x10000; i++) {
  1410. for (num=0, j=4; j--; )
  1411. num = num * i + poly[j];
  1412. m_Curve[i] = (uint16_t) LIM((int32_t)(num+i),0,65535);
  1413. } apply: /* apply to whole image */
  1414. for (row=0; row < m_RawHeight; row++)
  1415. for (col = (tag & 1)*ph1.split_col; col < m_RawWidth; col++)
  1416. RAW(row,col) = m_Curve[RAW(row,col)];
  1417. } else if (tag == 0x400) { /* Sensor defects */
  1418. while ((len -= 8) >= 0) {
  1419. col = get2();
  1420. row = get2();
  1421. type = get2(); get2();
  1422. if (col >= m_RawWidth) continue;
  1423. if (type == 131) /* Bad column */
  1424. for (row=0; row < m_RawHeight; row++)
  1425. if (FC(row-m_TopMargin,col-m_LeftMargin) == 1) {
  1426. for (sum=i=0; i < 4; i++)
  1427. sum += val[i] = raw (row+dir[i][0], col+dir[i][1]);
  1428. for (max=i=0; i < 4; i++) {
  1429. dev[i] = abs((val[i] << 2) - sum);
  1430. if (dev[max] < dev[i]) max = i;
  1431. }
  1432. RAW(row,col) = (uint16_t) ((sum - val[max])/3.0 + 0.5);
  1433. } else {
  1434. for (sum=0, i=8; i < 12; i++)
  1435. sum += raw (row+dir[i][0], col+dir[i][1]);
  1436. RAW(row,col) = (uint16_t) (0.5 + sum * 0.0732233 +
  1437. (raw(row,col-2) + raw(row,col+2)) * 0.3535534);
  1438. }
  1439. else if (type == 129) { /* Bad pixel */
  1440. if (row >= m_RawHeight) continue;
  1441. j = (FC(row-m_TopMargin,col-m_LeftMargin) != 1) * 4;
  1442. for (sum=0, i=j; i < j+8; i++)
  1443. sum += raw (row+dir[i][0], col+dir[i][1]);
  1444. RAW(row,col) = (sum + 4) >> 3;
  1445. }
  1446. }
  1447. } else if (tag == 0x401) { /* All-color flat fields */
  1448. phase_one_flat_field (1, 2);
  1449. } else if (tag == 0x416 || tag == 0x410) {
  1450. phase_one_flat_field (0, 2);
  1451. } else if (tag == 0x40b) { /* Red+blue flat field */
  1452. phase_one_flat_field (0, 4);
  1453. } else if (tag == 0x412) {
  1454. fseek (m_InputFile, 36, SEEK_CUR);
  1455. diff = abs (get2() - ph1.tag_21a);
  1456. if (mindiff > diff) {
  1457. mindiff = diff;
  1458. off_412 = ftell(m_InputFile) - 38;
  1459. }
  1460. }
  1461. fseek (m_InputFile, save, SEEK_SET);
  1462. }
  1463. if (off_412) {
  1464. fseek (m_InputFile, off_412, SEEK_SET);
  1465. for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
  1466. yval[0] = (float *) CALLOC (head[1]*head[3] + head[2]*head[4], 6);
  1467. merror (yval[0], "phase_one_correct()");
  1468. yval[1] = (float *) (yval[0] + head[1]*head[3]);
  1469. xval[0] = (uint16_t *) (yval[1] + head[2]*head[4]);
  1470. xval[1] = (uint16_t *) (xval[0] + head[1]*head[3]);
  1471. get2();
  1472. for (i=0; i < 2; i++)
  1473. for (j=0; j < head[i+1]*head[i+3]; j++)
  1474. yval[i][j] = getreal(11);
  1475. for (i=0; i < 2; i++)
  1476. for (j=0; j < head[i+1]*head[i+3]; j++)
  1477. xval[i][j] = get2();
  1478. for (row=0; row < m_RawHeight; row++)
  1479. for (col=0; col < m_RawWidth; col++) {
  1480. cfrac = (float) col * head[3] / m_RawWidth;
  1481. cfrac -= (cip = (int) cfrac);
  1482. num = RAW(row,col) * 0.5;
  1483. for (i=cip; i < cip+2; i++) {
  1484. for (k=j=0; j < head[1]; j++)
  1485. if (num < xval[0][k = head[1]*i+j]) break;
  1486. frac = (j == 0 || j == head[1]) ? 0 :
  1487. (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
  1488. mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
  1489. }
  1490. i = (int) (((mult[0] * (1-cfrac) + mult[1] * cfrac) * row + num) * 2);
  1491. RAW(row,col) = LIM(i,0,65535);
  1492. }
  1493. FREE (yval[0]);
  1494. }
  1495. }
  1496. void CLASS phase_one_load_raw()
  1497. {
  1498. int a, b, i;
  1499. uint16_t akey, bkey, m_Mask;
  1500. fseek (m_InputFile, ph1.key_off, SEEK_SET);
  1501. akey = get2();
  1502. bkey = get2();
  1503. m_Mask = ph1.format == 1 ? 0x5555:0x1354;
  1504. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  1505. read_shorts (m_Raw_Image, m_RawWidth*m_RawHeight);
  1506. if (ph1.format)
  1507. for (i=0; i < m_RawWidth*m_RawHeight; i+=2) {
  1508. a = m_Raw_Image[i+0] ^ akey;
  1509. b = m_Raw_Image[i+1] ^ bkey;
  1510. m_Raw_Image[i+0] = (a & m_Mask) | (b & ~m_Mask);
  1511. m_Raw_Image[i+1] = (b & m_Mask) | (a & ~m_Mask);
  1512. }
  1513. }
  1514. unsigned CLASS ph1_bithuff (int nbits, uint16_t *huff)
  1515. {
  1516. unsigned c;
  1517. if (nbits == -1)
  1518. return m_ph1_bithuffbitbuf = m_ph1_bithuffvbits = 0;
  1519. if (nbits == 0) return 0;
  1520. if (m_ph1_bithuffvbits < nbits) {
  1521. m_ph1_bithuffbitbuf = m_ph1_bithuffbitbuf << 32 | get4();
  1522. m_ph1_bithuffvbits += 32;
  1523. }
  1524. c = m_ph1_bithuffbitbuf << (64-m_ph1_bithuffvbits) >> (64-nbits);
  1525. if (huff) {
  1526. m_ph1_bithuffvbits -= huff[c] >> 8;
  1527. return (unsigned char) huff[c];
  1528. }
  1529. m_ph1_bithuffvbits -= nbits;
  1530. return c;
  1531. }
  1532. #define ph1_bits(n) ph1_bithuff(n,0)
  1533. #define ph1_huff(h) ph1_bithuff(*h,h+1)
  1534. void CLASS phase_one_load_raw_c()
  1535. {
  1536. static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
  1537. int *offset, len[2], pred[2], row, col, i, j;
  1538. uint16_t *pixel;
  1539. short (*black)[2];
  1540. pixel = (uint16_t *) CALLOC (m_RawWidth + m_RawHeight*4, 2);
  1541. merror (pixel, "phase_one_load_raw_c()");
  1542. offset = (int *) (pixel + m_RawWidth);
  1543. fseek (m_InputFile, strip_offset, SEEK_SET);
  1544. for (row=0; row < m_RawHeight; row++)
  1545. offset[row] = get4();
  1546. black = (short (*)[2]) offset + m_RawHeight;
  1547. fseek (m_InputFile, ph1.black_off, SEEK_SET);
  1548. if (ph1.black_off)
  1549. read_shorts ((uint16_t *) black[0], m_RawHeight*2);
  1550. for (i=0; i < 256; i++)
  1551. m_Curve[i] = (uint16_t) (i*i / 3.969 + 0.5);
  1552. for (row=0; row < m_RawHeight; row++) {
  1553. fseek (m_InputFile, m_Data_Offset + offset[row], SEEK_SET);
  1554. ph1_bits(-1);
  1555. pred[0] = pred[1] = 0;
  1556. for (col=0; col < m_RawWidth; col++) {
  1557. if (col >= (m_RawWidth & -8))
  1558. len[0] = len[1] = 14;
  1559. else if ((col & 7) == 0)
  1560. for (i=0; i < 2; i++) {
  1561. for (j=0; j < 5 && !ph1_bits(1); j++) {};
  1562. if (j--) len[i] = length[j*2 + ph1_bits(1)];
  1563. }
  1564. if ((i = len[col & 1]) == 14)
  1565. pixel[col] = pred[col & 1] = ph1_bits(16);
  1566. else
  1567. pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
  1568. if (pred[col & 1] >> 16) derror();
  1569. if (ph1.format == 5 && pixel[col] < 256)
  1570. pixel[col] = m_Curve[pixel[col]];
  1571. }
  1572. for (col=0; col < m_RawWidth; col++) {
  1573. i = (pixel[col] << 2) - ph1.black + black[row][col >= ph1.split_col];
  1574. if (i > 0) RAW(row,col) = i;
  1575. }
  1576. }
  1577. FREE (pixel);
  1578. m_WhiteLevel = 0xfffc - ph1.black;
  1579. }
  1580. void CLASS hasselblad_load_raw()
  1581. {
  1582. struct jhead jh;
  1583. int row, col, pred[2], len[2], diff, c;
  1584. if (!ljpeg_start (&jh, 0)) return;
  1585. m_ByteOrder = 0x4949;
  1586. ph1_bits(-1);
  1587. for (row=0; row < m_RawHeight; row++) {
  1588. pred[0] = pred[1] = 0x8000 + m_Load_Flags;
  1589. for (col=0; col < m_RawWidth; col+=2) {
  1590. for(c=0;c<2;c++) len[c] = ph1_huff(jh.huff[0]);
  1591. for(c=0;c<2;c++) {
  1592. diff = ph1_bits(len[c]);
  1593. if ((diff & (1 << (len[c]-1))) == 0)
  1594. diff -= (1 << len[c]) - 1;
  1595. if (diff == 65535) diff = -32768;
  1596. RAW(row,col+c) = pred[c] += diff;
  1597. }
  1598. }
  1599. }
  1600. ljpeg_end (&jh);
  1601. m_WhiteLevel = 0xffff;
  1602. }
  1603. void CLASS leaf_hdr_load_raw()
  1604. {
  1605. uint16_t *pixel=0;
  1606. unsigned tile=0, r, c, row, col;
  1607. if (!m_Filters) {
  1608. pixel = (uint16_t *) CALLOC (m_RawWidth, sizeof *pixel);
  1609. merror (pixel, "leaf_hdr_load_raw()");
  1610. }
  1611. for (c=0; c < m_Tiff_Samples; c++) {
  1612. for (r=0; r < m_RawHeight; r++) {
  1613. if (r % m_TileLength == 0) {
  1614. fseek (m_InputFile, m_Data_Offset + 4*tile++, SEEK_SET);
  1615. fseek (m_InputFile, get4(), SEEK_SET);
  1616. }
  1617. if (m_Filters && c != m_UserSetting_ShotSelect) continue;
  1618. if (m_Filters) pixel = m_Raw_Image + r*m_RawWidth;
  1619. read_shorts (pixel, m_RawWidth);
  1620. if (!m_Filters && (row = r - m_TopMargin) < m_Height)
  1621. for (col=0; col < m_Width; col++)
  1622. m_Image[row*m_Width+col][c] = pixel[col+m_LeftMargin];
  1623. }
  1624. }
  1625. if (!m_Filters) {
  1626. m_WhiteLevel = 0xffff;
  1627. m_RawColor = 1;
  1628. FREE (pixel);
  1629. }
  1630. }
  1631. void CLASS unpacked_load_raw()
  1632. {
  1633. int row, col, bits=0;
  1634. while ((1 << ++bits) < (int32_t)m_WhiteLevel);
  1635. read_shorts (m_Raw_Image, m_RawWidth*m_RawHeight);
  1636. for (row=0; row < m_RawHeight; row++)
  1637. for (col=0; col < m_RawWidth; col++)
  1638. if ((RAW(row,col) >>= m_Load_Flags) >> bits
  1639. && (unsigned) (row-m_TopMargin) < m_Height
  1640. && (unsigned) (col-m_LeftMargin) < m_Width) derror();
  1641. }
  1642. void CLASS sinar_4shot_load_raw()
  1643. {
  1644. uint16_t *pixel;
  1645. unsigned shot, row, col, r, c;
  1646. if ((shot = m_UserSetting_ShotSelect) || m_UserSetting_HalfSize) {
  1647. if (shot) shot--;
  1648. if (shot > 3) shot = 3;
  1649. fseek (m_InputFile, m_Data_Offset + shot*4, SEEK_SET);
  1650. fseek (m_InputFile, get4(), SEEK_SET);
  1651. unpacked_load_raw();
  1652. return;
  1653. }
  1654. FREE (m_Raw_Image);
  1655. m_Raw_Image = 0;
  1656. m_Image = (uint16_t (*)[4])
  1657. CALLOC ((m_OutHeight=m_Height)*(m_OutWidth=m_Width), sizeof *m_Image);
  1658. merror (m_Image, "sinar_4shot_load_raw()");
  1659. pixel = (uint16_t *) CALLOC (m_RawWidth, sizeof *pixel);
  1660. merror (pixel, "sinar_4shot_load_raw()");
  1661. for (shot=0; shot < 4; shot++) {
  1662. fseek (m_InputFile, m_Data_Offset + shot*4, SEEK_SET);
  1663. fseek (m_InputFile, get4(), SEEK_SET);
  1664. for (row=0; row < m_RawHeight; row++) {
  1665. read_shorts (pixel, m_RawWidth);
  1666. if ((r = row-m_TopMargin - (shot >> 1 & 1)) >= m_Height) continue;
  1667. for (col=0; col < m_RawWidth; col++) {
  1668. if ((c = col-m_LeftMargin - (shot & 1)) >= m_Width) continue;
  1669. m_Image[r*m_Width+c][FC(row,col)] = pixel[col];
  1670. }
  1671. }
  1672. }
  1673. FREE (pixel);
  1674. m_Shrink = m_Filters = 0;
  1675. }
  1676. void CLASS imacon_full_load_raw()
  1677. {
  1678. int row, col;
  1679. for (row=0; row < m_Height; row++)
  1680. for (col=0; col < m_Width; col++)
  1681. read_shorts (m_Image[row*m_Width+col], 3);
  1682. }
  1683. void CLASS packed_load_raw()
  1684. {
  1685. int vbits=0, bwide, pwide, rbits, bite, half, irow, row, col, val, i;
  1686. uint64_t bitbuf=0;
  1687. if (m_RawWidth * 8U >= m_Width * m_Tiff_bps) /* Is m_RawWidth in bytes? */
  1688. pwide = (bwide = m_RawWidth) * 8 / m_Tiff_bps;
  1689. else bwide = (pwide = m_RawWidth) * m_Tiff_bps / 8;
  1690. rbits = bwide * 8 - pwide * m_Tiff_bps;
  1691. if (m_Load_Flags & 1) bwide = bwide * 16 / 15;
  1692. bite = 8 + (m_Load_Flags & 24);
  1693. half = (m_RawHeight+1) >> 1;
  1694. for (irow=0; irow < m_RawHeight; irow++) {
  1695. row = irow;
  1696. if (m_Load_Flags & 2 &&
  1697. (row = irow % half * 2 + irow / half) == 1 &&
  1698. m_Load_Flags & 4) {
  1699. if (vbits=0, m_Tiff_Compress)
  1700. fseek (m_InputFile, m_Data_Offset - (-half*bwide & -2048), SEEK_SET);
  1701. else {
  1702. fseek (m_InputFile, 0, SEEK_END);
  1703. fseek (m_InputFile, ftell(m_InputFile) >> 3 << 2, SEEK_SET);
  1704. }
  1705. }
  1706. for (col=0; col < pwide; col++) {
  1707. for (vbits -= m_Tiff_bps; vbits < 0; vbits += bite) {
  1708. bitbuf <<= bite;
  1709. for (i=0; i < bite; i+=8)
  1710. bitbuf |= (unsigned) (fgetc(m_InputFile) << i);
  1711. }
  1712. val = bitbuf << (64-m_Tiff_bps-vbits) >> (64-m_Tiff_bps);
  1713. RAW(row,col ^ (m_Load_Flags >> 6)) = val;
  1714. if (m_Load_Flags & 1 && (col % 10) == 9 &&
  1715. fgetc(m_InputFile) && col < m_Width+m_LeftMargin) derror();
  1716. }
  1717. vbits -= rbits;
  1718. }
  1719. }
  1720. void CLASS nokia_load_raw()
  1721. {
  1722. uint8_t *data, *dp;
  1723. int rev, dwide, row, col, c;
  1724. rev = 3 * (m_ByteOrder == 0x4949);
  1725. dwide = m_RawWidth * 5 / 4;
  1726. data = (uint8_t *) MALLOC (dwide*2);
  1727. merror (data, "nokia_load_raw()");
  1728. for (row=0; row < m_RawHeight; row++) {
  1729. if (fread (data+dwide, 1, dwide, m_InputFile) < (size_t) dwide) derror();
  1730. for(c=0;c<dwide;c++) data[c] = data[dwide+(c ^ rev)];
  1731. for (dp=data, col=0; col < m_RawWidth; dp+=5, col+=4)
  1732. for (c=0; c<4; c++) RAW(row,col+c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
  1733. }
  1734. FREE (data);
  1735. m_WhiteLevel = 0x3ff;
  1736. }
  1737. unsigned CLASS pana_bits (int nbits)
  1738. {
  1739. int byte;
  1740. if (!nbits) return m_pana_bits_vbits=0;
  1741. if (!m_pana_bits_vbits) {
  1742. ptfread (m_pana_bits_buf+m_Load_Flags, 1, 0x4000-m_Load_Flags, m_InputFile);
  1743. ptfread (m_pana_bits_buf, 1, m_Load_Flags, m_InputFile);
  1744. }
  1745. m_pana_bits_vbits = (m_pana_bits_vbits - nbits) & 0x1ffff;
  1746. byte = m_pana_bits_vbits >> 3 ^ 0x3ff0;
  1747. return (m_pana_bits_buf[byte] | m_pana_bits_buf[byte+1] << 8) >> (m_pana_bits_vbits & 7) & ~(-1 << nbits);
  1748. }
  1749. void CLASS panasonic_load_raw()
  1750. {
  1751. int row, col, i, j, sh=0, pred[2], nonz[2];
  1752. pana_bits(0);
  1753. for (row=0; row < m_Height; row++)
  1754. for (col=0; col < m_RawWidth; col++) {
  1755. if ((i = col % 14) == 0)
  1756. pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
  1757. if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
  1758. if (nonz[i & 1]) {
  1759. if ((j = pana_bits(8))) {
  1760. if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
  1761. pred[i & 1] &= ~(-1 << sh);
  1762. pred[i & 1] += j << sh;
  1763. }
  1764. } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
  1765. pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
  1766. if ((RAW(row,col) = pred[col & 1]) > 4098 && col < m_Width) derror();
  1767. }
  1768. }
  1769. void CLASS olympus_load_raw()
  1770. {
  1771. uint16_t huff[4096];
  1772. int row, col, nbits, sign, low, high, i, c, w, n, nw;
  1773. int acarry[2][3], *carry, pred, diff;
  1774. huff[n=0] = 0xc0c;
  1775. for (i=12; i--; )
  1776. for (c=0;c<(2048>>i);c++) huff[++n] = (i+1) << 8 | i;
  1777. fseek (m_InputFile, 7, SEEK_CUR);
  1778. getbits(-1);
  1779. for (row=0; row < m_Height; row++) {
  1780. memset (acarry, 0, sizeof acarry);
  1781. for (col=0; col < m_RawWidth; col++) {
  1782. carry = acarry[col & 1];
  1783. i = 2 * (carry[2] < 3);
  1784. for (nbits=2+i; (uint16_t) carry[0] >> (nbits+i); nbits++){} ;
  1785. low = (sign = getbits(3)) & 3;
  1786. sign = sign << 29 >> 31;
  1787. if ((high = getbithuff(12,huff)) == 12)
  1788. high = getbits(16-nbits) >> 1;
  1789. carry[0] = (high << nbits) | getbits(nbits);
  1790. diff = (carry[0] ^ sign) + carry[1];
  1791. carry[1] = (diff*3 + carry[1]) >> 5;
  1792. carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
  1793. if (col >= m_Width) continue;
  1794. if (row < 2 && col < 2) pred = 0;
  1795. else if (row < 2) pred = RAW(row,col-2);
  1796. else if (col < 2) pred = RAW(row-2,col);
  1797. else {
  1798. w = RAW(row,col-2);
  1799. n = RAW(row-2,col);
  1800. nw = RAW(row-2,col-2);
  1801. if ((w < nw && nw < n) || (n < nw && nw < w)) {
  1802. if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
  1803. pred = w + n - nw;
  1804. else pred = (w + n) >> 1;
  1805. } else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
  1806. }
  1807. if ((RAW(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
  1808. }
  1809. }
  1810. }
  1811. void CLASS olympus_cseries_load_raw()
  1812. {
  1813. int irow, row, col;
  1814. for (irow=0; irow < m_Height; irow++) {
  1815. row = irow * 2 % m_Height + irow / (m_Height/2);
  1816. if (row < 2) {
  1817. fseek (m_InputFile, m_Data_Offset - row*(-m_Width*m_Height*3/4 & -2048), SEEK_SET);
  1818. getbits(-1);
  1819. }
  1820. for (col=0; col < m_Width; col++)
  1821. BAYER(row,col) = getbits(12);
  1822. }
  1823. m_BlackLevel >>= 4;
  1824. }
  1825. void CLASS minolta_rd175_load_raw()
  1826. {
  1827. uint8_t pixel[768];
  1828. unsigned irow, box, row, col;
  1829. for (irow=0; irow < 1481; irow++) {
  1830. if (fread (pixel, 1, 768, m_InputFile) < 768) derror();
  1831. box = irow / 82;
  1832. row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
  1833. switch (irow) {
  1834. case 1477: case 1479: continue;
  1835. case 1476: row = 984; break;
  1836. case 1480: row = 985; break;
  1837. case 1478: row = 985; box = 1;
  1838. }
  1839. if ((box < 12) && (box & 1)) {
  1840. for (col=0; col < 1533; col++, row ^= 1)
  1841. if (col != 1) RAW(row,col) = (col+1) & 2 ?
  1842. pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
  1843. RAW(row,1) = pixel[1] << 1;
  1844. RAW(row,1533) = pixel[765] << 1;
  1845. } else
  1846. for (col=row & 1; col < 1534; col+=2)
  1847. RAW(row,col) = pixel[col/2] << 1;
  1848. }
  1849. m_WhiteLevel = 0xff << 1;
  1850. }
  1851. void CLASS quicktake_100_load_raw()
  1852. {
  1853. uint8_t pixel[484][644];
  1854. static const short gstep[16] =
  1855. { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
  1856. static const short rstep[6][4] =
  1857. { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 },
  1858. { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
  1859. int rb, row, col, sharp, val=0;
  1860. getbits(-1);
  1861. memset (pixel, 0x80, sizeof pixel);
  1862. for (row=2; row < m_Height+2; row++) {
  1863. for (col=2+(row & 1); col < m_Width+2; col+=2) {
  1864. val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
  1865. pixel[row][col-2]) >> 2) + gstep[getbits(4)];
  1866. pixel[row][col] = val = LIM(val,0,255);
  1867. if (col < 4)
  1868. pixel[row][col-2] = pixel[row+1][~row & 1] = val;
  1869. if (row == 2)
  1870. pixel[row-1][col+1] = pixel[row-1][col+3] = val;
  1871. }
  1872. pixel[row][col] = val;
  1873. }
  1874. for (rb=0; rb < 2; rb++)
  1875. for (row=2+rb; row < m_Height+2; row+=2)
  1876. for (col=3-(row & 1); col < m_Width+2; col+=2) {
  1877. if (row < 4 || col < 4) sharp = 2;
  1878. else {
  1879. val = ABS(pixel[row-2][col] - pixel[row][col-2])
  1880. + ABS(pixel[row-2][col] - pixel[row-2][col-2])
  1881. + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
  1882. sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 :
  1883. val < 32 ? 3 : val < 48 ? 4 : 5;
  1884. }
  1885. val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
  1886. + rstep[sharp][getbits(2)];
  1887. pixel[row][col] = val = LIM(val,0,255);
  1888. if (row < 4) pixel[row-2][col+2] = val;
  1889. if (col < 4) pixel[row+2][col-2] = val;
  1890. }
  1891. for (row=2; row < m_Height+2; row++)
  1892. for (col=3-(row & 1); col < m_Width+2; col+=2) {
  1893. val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
  1894. pixel[row][col+1]) >> 1) - 0x100;
  1895. pixel[row][col] = LIM(val,0,255);
  1896. }
  1897. for (row=0; row < m_Height; row++)
  1898. for (col=0; col < m_Width; col++)
  1899. RAW(row,col) = m_Curve[pixel[row+2][col+2]];
  1900. m_WhiteLevel = 0x3ff;
  1901. }
  1902. #define radc_token(tree) ((signed char) getbithuff(8,huff[tree]))
  1903. #define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
  1904. #define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
  1905. : (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
  1906. void CLASS kodak_radc_load_raw()
  1907. {
  1908. static const char src[] = {
  1909. 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
  1910. 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
  1911. 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
  1912. 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
  1913. 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
  1914. 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
  1915. 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
  1916. 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
  1917. 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
  1918. 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
  1919. 1,0, 2,2, 2,-2,
  1920. 1,-3, 1,3,
  1921. 2,-17, 2,-5, 2,5, 2,17,
  1922. 2,-7, 2,2, 2,9, 2,18,
  1923. 2,-18, 2,-9, 2,-2, 2,7,
  1924. 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
  1925. 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
  1926. 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
  1927. };
  1928. uint16_t huff[19][256];
  1929. int row, col, tree, nreps, rep, step, /* i,*/ c, s, r, x, y, val;
  1930. constexpr unsigned int bufi1 = 3;
  1931. constexpr unsigned int bufi2 = 386;
  1932. short last[3] = { 16,16,16 }, mul[3], buf[3][bufi1][bufi2];
  1933. static const uint16_t pt[] =
  1934. { 0,0, 1280,1344, 2320,3616, 3328,8000, 4095,16383, 65535,16383 };
  1935. int i;
  1936. for (i=2; i < 12; i+=2)
  1937. for (c=pt[i-2]; c <= pt[i]; c++)
  1938. m_Curve[c] = (float)
  1939. (c-pt[i-2]) / (pt[i]-pt[i-2]) * (pt[i+1]-pt[i-1]) + pt[i-1] + 0.5;
  1940. for (s=i=0; i < (int)(sizeof(src)); i+=2)
  1941. for(c=0;c<(256>>src[i]);c++)
  1942. huff[0][s++] = src[i] << 8 | (unsigned char) src[i+1];
  1943. s = m_Kodak_cbpp == 243 ? 2 : 3;
  1944. for(c=0;c<256;c++) huff[18][c] = (8-s) << 8 | c >> s << s | 1 << (s-1);
  1945. getbits(-1);
  1946. memset(buf, 2048, sizeof(buf)/sizeof(short));
  1947. // for (unsigned i=0; i < sizeof(buf)/sizeof(short); i++)
  1948. // buf[0][0][i] = 2048;
  1949. for (row=0; row < m_Height; row+=4) {
  1950. for (c=0; c<3; c++) mul[c] = getbits(6);
  1951. for (c=0; c<3; c++) {
  1952. val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
  1953. s = val > 65564 ? 10:12;
  1954. x = ~(-1 << (s-1));
  1955. val <<= 12-s;
  1956. for (unsigned i=0; i < bufi1; i++)
  1957. for (unsigned j=0; j < bufi2; j++)
  1958. buf[c][i][j] = (buf[c][i][j] * val + x) >> s;
  1959. // for (unsigned i=0; i < sizeof(buf[0])/sizeof(short); i++)
  1960. // buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
  1961. last[c] = mul[c];
  1962. for (r=0; r <= !c; r++) {
  1963. buf[c][1][m_Width/2] = buf[c][2][m_Width/2] = mul[c] << 7;
  1964. for (tree=1, col=m_Width/2; col > 0; ) {
  1965. if ((tree = radc_token(tree))) {
  1966. col -= 2;
  1967. if (tree == 8)
  1968. FORYX buf[c][y][x] = (uint8_t) radc_token(18) * mul[c];
  1969. else
  1970. FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
  1971. } else
  1972. do {
  1973. nreps = (col > 2) ? radc_token(9) + 1 : 1;
  1974. for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
  1975. col -= 2;
  1976. FORYX buf[c][y][x] = PREDICTOR;
  1977. if (rep & 1) {
  1978. step = radc_token(10) << 4;
  1979. FORYX buf[c][y][x] += step;
  1980. }
  1981. }
  1982. } while (nreps == 9);
  1983. }
  1984. for (y=0; y < 2; y++)
  1985. for (x=0; x < m_Width/2; x++) {
  1986. val = (buf[c][y+1][x] << 4) / mul[c];
  1987. if (val < 0) val = 0;
  1988. if (c) RAW(row+y*2+c-1,x*2+2-c) = val;
  1989. else RAW(row+r*2+y,x*2+y) = val;
  1990. }
  1991. memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
  1992. }
  1993. }
  1994. for (y=row; y < row+4; y++)
  1995. for (x=0; x < m_Width; x++)
  1996. if ((x+y) & 1) {
  1997. r = x ? x-1 : x+1;
  1998. s = x+1 < m_Width ? x+1 : x-1;
  1999. val = (RAW(y,x)-2048)*2 + (RAW(y,r)+RAW(y,s))/2;
  2000. if (val < 0) val = 0;
  2001. RAW(y,x) = val;
  2002. }
  2003. }
  2004. for (i=0; i < m_Height*m_Width; i++)
  2005. m_Raw_Image[i] = m_Curve[m_Raw_Image[i]];
  2006. m_WhiteLevel = 0xfff;
  2007. }
  2008. #undef FORYX
  2009. #undef PREDICTOR
  2010. #ifdef NO_JPEG
  2011. void CLASS kodak_jpeg_load_raw() {}
  2012. void CLASS lossy_dng_load_raw() {}
  2013. #else
  2014. METHODDEF(boolean)
  2015. fill_input_buffer (j_decompress_ptr cinfo)
  2016. {
  2017. static uint8_t jpeg_buffer[4096];
  2018. size_t nbytes;
  2019. ptDcRaw *data = (ptDcRaw*) cinfo->client_data;
  2020. nbytes = fread (jpeg_buffer, 1, 4096, data->m_InputFile);
  2021. swab ((char *)jpeg_buffer, (char *)jpeg_buffer, nbytes);
  2022. cinfo->src->next_input_byte = jpeg_buffer;
  2023. cinfo->src->bytes_in_buffer = nbytes;
  2024. return TRUE;
  2025. }
  2026. void CLASS kodak_jpeg_load_raw()
  2027. {
  2028. struct jpeg_decompress_struct cinfo;
  2029. struct jpeg_error_mgr jerr;
  2030. JSAMPARRAY buf;
  2031. JSAMPLE (*pixel)[3];
  2032. int row, col;
  2033. cinfo.client_data = this;
  2034. cinfo.err = jpeg_std_error (&jerr);
  2035. jpeg_create_decompress (&cinfo);
  2036. jpeg_stdio_src (&cinfo, m_InputFile);
  2037. cinfo.src->fill_input_buffer = fill_input_buffer;
  2038. jpeg_read_header (&cinfo, TRUE);
  2039. jpeg_start_decompress (&cinfo);
  2040. if ((cinfo.output_width != m_Width ) ||
  2041. (cinfo.output_height*2 != m_Height ) ||
  2042. (cinfo.output_components != 3 )) {
  2043. fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), m_UserSetting_InputFileName);
  2044. jpeg_destroy_decompress (&cinfo);
  2045. longjmp (m_Failure, 3);
  2046. }
  2047. buf = (*cinfo.mem->alloc_sarray)
  2048. ((j_common_ptr) &cinfo, JPOOL_IMAGE, m_Width*3, 1);
  2049. while (cinfo.output_scanline < cinfo.output_height) {
  2050. row = cinfo.output_scanline * 2;
  2051. jpeg_read_scanlines (&cinfo, buf, 1);
  2052. pixel = (JSAMPLE (*)[3]) buf[0];
  2053. for (col=0; col < m_Width; col+=2) {
  2054. RAW(row+0,col+0) = pixel[col+0][1] << 1;
  2055. RAW(row+1,col+1) = pixel[col+1][1] << 1;
  2056. RAW(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
  2057. RAW(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
  2058. }
  2059. }
  2060. jpeg_finish_decompress (&cinfo);
  2061. jpeg_destroy_decompress (&cinfo);
  2062. m_WhiteLevel = 0xff << 1;
  2063. }
  2064. void CLASS lossy_dng_load_raw()
  2065. {
  2066. struct jpeg_decompress_struct cinfo;
  2067. struct jpeg_error_mgr jerr;
  2068. JSAMPARRAY buf;
  2069. JSAMPLE (*pixel)[3];
  2070. unsigned sm_ByteOrder=m_ByteOrder, ntags, opcode, deg, i, j, c;
  2071. unsigned save=m_Data_Offset-4, trow=0, tcol=0, row, col;
  2072. ushort curve[3][256];
  2073. double coeff[9], tot;
  2074. fseek (m_InputFile, meta_offset, SEEK_SET);
  2075. m_ByteOrder = 0x4d4d;
  2076. ntags = get4();
  2077. while (ntags--) {
  2078. opcode = get4(); get4(); get4();
  2079. if (opcode != 8)
  2080. { fseek (m_InputFile, get4(), SEEK_CUR); continue; }
  2081. fseek (m_InputFile, 20, SEEK_CUR);
  2082. if ((c = get4()) > 2) break;
  2083. fseek (m_InputFile, 12, SEEK_CUR);
  2084. if ((deg = get4()) > 8) break;
  2085. for (i=0; i <= deg && i < 9; i++)
  2086. coeff[i] = getreal(12);
  2087. for (i=0; i < 256; i++) {
  2088. for (tot=j=0; j <= deg; j++)
  2089. tot += coeff[j] * pow(i/255.0, j);
  2090. curve[c][i] = tot*0xffff;
  2091. }
  2092. }
  2093. m_ByteOrder = sm_ByteOrder;
  2094. cinfo.err = jpeg_std_error (&jerr);
  2095. jpeg_create_decompress (&cinfo);
  2096. while (trow < m_RawHeight) {
  2097. fseek (m_InputFile, save+=4, SEEK_SET);
  2098. if (m_TileLength < INT_MAX)
  2099. fseek (m_InputFile, get4(), SEEK_SET);
  2100. jpeg_stdio_src (&cinfo, m_InputFile);
  2101. jpeg_read_header (&cinfo, TRUE);
  2102. jpeg_start_decompress (&cinfo);
  2103. buf = (*cinfo.mem->alloc_sarray)
  2104. ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width*3, 1);
  2105. while (cinfo.output_scanline < cinfo.output_height &&
  2106. (row = trow + cinfo.output_scanline) < m_Height) {
  2107. jpeg_read_scanlines (&cinfo, buf, 1);
  2108. pixel = (JSAMPLE (*)[3]) buf[0];
  2109. for (col=0; col < cinfo.output_width && tcol+col < m_Width; col++) {
  2110. for (c=0; c<3; c++) m_Image[row*m_Width+tcol+col][c] = curve[c][pixel[col][c]];
  2111. }
  2112. }
  2113. jpeg_abort_decompress (&cinfo);
  2114. if ((tcol += m_TileWidth) >= m_RawWidth)
  2115. trow += m_TileLength + (tcol = 0);
  2116. }
  2117. jpeg_destroy_decompress (&cinfo);
  2118. m_WhiteLevel = 0xffff;
  2119. }
  2120. #endif
  2121. void CLASS kodak_dc120_load_raw()
  2122. {
  2123. static const int mul[4] = { 162, 192, 187, 92 };
  2124. static const int add[4] = { 0, 636, 424, 212 };
  2125. uint8_t pixel[848];
  2126. int row, shift, col;
  2127. for (row=0; row < m_Height; row++) {
  2128. if (fread (pixel, 1, 848, m_InputFile) < 848) derror();
  2129. shift = row * mul[row & 3] + add[row & 3];
  2130. for (col=0; col < m_Width; col++)
  2131. RAW(row,col) = (uint16_t) pixel[(col + shift) % 848];
  2132. }
  2133. m_WhiteLevel = 0xff;
  2134. }
  2135. void CLASS eight_bit_load_raw()
  2136. {
  2137. uint8_t *pixel;
  2138. unsigned row, col;
  2139. pixel = (uint8_t *) CALLOC (m_RawWidth, sizeof *pixel);
  2140. merror (pixel, "eight_bit_load_raw()");
  2141. for (row=0; row < m_RawHeight; row++) {
  2142. if (fread (pixel, 1, m_RawWidth, m_InputFile) < m_RawWidth) derror();
  2143. for (col=0; col < m_RawWidth; col++)
  2144. RAW(row,col) = m_Curve[pixel[col]];
  2145. }
  2146. FREE (pixel);
  2147. m_WhiteLevel = m_Curve[0xff];
  2148. }
  2149. void CLASS kodak_yrgb_load_raw()
  2150. {
  2151. uint8_t *pixel;
  2152. int row, col, y, cb, cr, rgb[3], c;
  2153. pixel = (uint8_t *) CALLOC (m_RawWidth, 3*sizeof *pixel);
  2154. merror (pixel, "kodak_yrgb_load_raw()");
  2155. for (row=0; row < m_Height; row++) {
  2156. if (~row & 1)
  2157. if (fread (pixel, m_RawWidth, 3, m_InputFile) < 3) derror();
  2158. for (col=0; col < m_RawWidth; col++) {
  2159. y = pixel[m_Width*2*(row & 1) + col];
  2160. cb = pixel[m_Width + (col & -2)] - 128;
  2161. cr = pixel[m_Width + (col & -2)+1] - 128;
  2162. rgb[1] = y-((cb + cr + 2) >> 2);
  2163. rgb[2] = rgb[1] + cb;
  2164. rgb[0] = rgb[1] + cr;
  2165. for (c=0;c<3;c++) m_Image[row*m_Width+col][c] = m_Curve[LIM(rgb[c],0,255)];
  2166. }
  2167. }
  2168. FREE (pixel);
  2169. m_WhiteLevel = m_Curve[0xff];
  2170. }
  2171. void CLASS kodak_262_load_raw()
  2172. {
  2173. static const uint8_t kodak_tree[2][26] =
  2174. { { 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 },
  2175. { 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 } };
  2176. uint16_t *huff[2];
  2177. uint8_t *pixel;
  2178. int *strip, ns, c, row, col, chess, pi=0, pi1, pi2, pred, val;
  2179. huff[0] = make_decoder (kodak_tree[0]);
  2180. huff[1] = make_decoder (kodak_tree[1]);
  2181. ns = (m_RawHeight+63) >> 5;
  2182. pixel = (uint8_t *) MALLOC (m_RawWidth*32 + ns*4);
  2183. merror (pixel, "kodak_262_load_raw()");
  2184. strip = (int *) (pixel + m_RawWidth*32);
  2185. m_ByteOrder = 0x4d4d;
  2186. for(c=0;c<ns;c++) strip[c] = get4();
  2187. for (row=0; row < m_RawHeight; row++) {
  2188. if ((row & 31) == 0) {
  2189. fseek (m_InputFile, strip[row >> 5], SEEK_SET);
  2190. getbits(-1);
  2191. pi = 0;
  2192. }
  2193. for (col=0; col < m_RawWidth; col++) {
  2194. chess = (row + col) & 1;
  2195. pi1 = chess ? pi-2 : pi-m_RawWidth-1;
  2196. pi2 = chess ? pi-2*m_RawWidth : pi-m_RawWidth+1;
  2197. if (col <= chess) pi1 = -1;
  2198. if (pi1 < 0) pi1 = pi2;
  2199. if (pi2 < 0) pi2 = pi1;
  2200. if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
  2201. pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
  2202. pixel[pi] = val = pred + ljpeg_diff (huff[chess]);
  2203. if (val >> 8) derror();
  2204. val = m_Curve[pixel[pi++]];
  2205. RAW(row,col) = val;
  2206. }
  2207. }
  2208. FREE (pixel);
  2209. FREE (huff[0]);
  2210. FREE (huff[1]);
  2211. }
  2212. int CLASS kodak_65000_decode (short *out, int bsize)
  2213. {
  2214. uint8_t c, blen[768];
  2215. uint16_t raw[6];
  2216. int64_t bitbuf=0;
  2217. int save, bits=0, i, j, len, diff;
  2218. save = ftell(m_InputFile);
  2219. bsize = (bsize + 3) & -4;
  2220. for (i=0; i < bsize; i+=2) {
  2221. c = fgetc(m_InputFile);
  2222. if ((blen[i ] = c & 15) > 12 ||
  2223. (blen[i+1] = c >> 4) > 12 ) {
  2224. fseek (m_InputFile, save, SEEK_SET);
  2225. for (i=0; i < bsize; i+=8) {
  2226. read_shorts (raw, 6);
  2227. out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
  2228. out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
  2229. for (j=0; j < 6; j++)
  2230. out[i+2+j] = raw[j] & 0xfff;
  2231. }
  2232. return 1;
  2233. }
  2234. }
  2235. if ((bsize & 7) == 4) {
  2236. bitbuf = fgetc(m_InputFile) << 8;
  2237. bitbuf += fgetc(m_InputFile);
  2238. bits = 16;
  2239. }
  2240. for (i=0; i < bsize; i++) {
  2241. len = blen[i];
  2242. if (bits < len) {
  2243. for (j=0; j < 32; j+=8)
  2244. bitbuf += (int64_t) fgetc(m_InputFile) << (bits+(j^8));
  2245. bits += 32;
  2246. }
  2247. diff = bitbuf & (0xffff >> (16-len));
  2248. bitbuf >>= len;
  2249. bits -= len;
  2250. if ((diff & (1 << (len-1))) == 0)
  2251. diff -= (1 << len) - 1;
  2252. out[i] = diff;
  2253. }
  2254. return 0;
  2255. }
  2256. void CLASS kodak_65000_load_raw()
  2257. {
  2258. short buf[256];
  2259. int row, col, len, pred[2], ret, i;
  2260. for (row=0; row < m_Height; row++)
  2261. for (col=0; col < m_Width; col+=256) {
  2262. pred[0] = pred[1] = 0;
  2263. len = MIN (256, m_Width-col);
  2264. ret = kodak_65000_decode (buf, len);
  2265. for (i=0; i < len; i++)
  2266. if ((RAW(row,col+i) = m_Curve[ret ? buf[i] :
  2267. (pred[i & 1] += buf[i])]) >> 12) derror();
  2268. }
  2269. }
  2270. void CLASS kodak_ycbcr_load_raw()
  2271. {
  2272. short buf[384], *bp;
  2273. int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
  2274. uint16_t *ip;
  2275. for (row=0; row < m_Height; row+=2)
  2276. for (col=0; col < m_Width; col+=128) {
  2277. len = MIN (128, m_Width-col);
  2278. kodak_65000_decode (buf, len*3);
  2279. y[0][1] = y[1][1] = cb = cr = 0;
  2280. for (bp=buf, i=0; i < len; i+=2, bp+=2) {
  2281. cb += bp[4];
  2282. cr += bp[5];
  2283. rgb[1] = -((cb + cr + 2) >> 2);
  2284. rgb[2] = rgb[1] + cb;
  2285. rgb[0] = rgb[1] + cr;
  2286. for (j=0; j < 2; j++)
  2287. for (k=0; k < 2; k++) {
  2288. if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
  2289. ip = m_Image[(row+j)*m_Width + col+i+k];
  2290. for (c=0; c<3; c++) ip[c] = m_Curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
  2291. }
  2292. }
  2293. }
  2294. }
  2295. void CLASS kodak_rgb_load_raw()
  2296. {
  2297. short buf[768], *bp;
  2298. int row, col, len, c, i, rgb[3];
  2299. uint16_t *ip=m_Image[0];
  2300. if (m_Raw_Image) FREE (m_Raw_Image);
  2301. m_Raw_Image = 0;
  2302. for (row=0; row < m_Height; row++)
  2303. for (col=0; col < m_Width; col+=256) {
  2304. len = MIN (256, m_Width-col);
  2305. kodak_65000_decode (buf, len*3);
  2306. memset (rgb, 0, sizeof rgb);
  2307. for (bp=buf, i=0; i < len; i++, ip+=4)
  2308. for (c=0; c<3; c++) if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
  2309. }
  2310. }
  2311. void CLASS kodak_thumb_load_raw()
  2312. {
  2313. int row, col;
  2314. m_Colors = m_ThumbMisc >> 5;
  2315. for (row=0; row < m_Height; row++)
  2316. for (col=0; col < m_Width; col++)
  2317. read_shorts (m_Image[row*m_Width+col], m_Colors);
  2318. m_WhiteLevel = (1 << (m_ThumbMisc & 31)) - 1;
  2319. }
  2320. void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
  2321. {
  2322. if (start) {
  2323. for (m_sony_decrypt_p=0; m_sony_decrypt_p < 4; m_sony_decrypt_p++)
  2324. m_sony_decrypt_pad[m_sony_decrypt_p] = key = key * 48828125 + 1;
  2325. m_sony_decrypt_pad[3] = m_sony_decrypt_pad[3] << 1 | (m_sony_decrypt_pad[0]^m_sony_decrypt_pad[2]) >> 31;
  2326. for (m_sony_decrypt_p=4; m_sony_decrypt_p < 127; m_sony_decrypt_p++)
  2327. m_sony_decrypt_pad[m_sony_decrypt_p] = (m_sony_decrypt_pad[m_sony_decrypt_p-4]^m_sony_decrypt_pad[m_sony_decrypt_p-2]) << 1 | (m_sony_decrypt_pad[m_sony_decrypt_p-3]^m_sony_decrypt_pad[m_sony_decrypt_p-1]) >> 31;
  2328. for (m_sony_decrypt_p=0; m_sony_decrypt_p < 127; m_sony_decrypt_p++)
  2329. m_sony_decrypt_pad[m_sony_decrypt_p] = htonl(m_sony_decrypt_pad[m_sony_decrypt_p]);
  2330. }
  2331. while (len--)
  2332. *data++ ^= m_sony_decrypt_pad[m_sony_decrypt_p++ & 127] = m_sony_decrypt_pad[(m_sony_decrypt_p+1) & 127] ^ m_sony_decrypt_pad[(m_sony_decrypt_p+65) & 127];
  2333. }
  2334. void CLASS sony_load_raw()
  2335. {
  2336. uint8_t head[40];
  2337. uint16_t *pixel;
  2338. unsigned i, key; // row, col;
  2339. uint16_t row,col;
  2340. fseek (m_InputFile, 200896, SEEK_SET);
  2341. fseek (m_InputFile, (unsigned) fgetc(m_InputFile)*4 - 1, SEEK_CUR);
  2342. m_ByteOrder = 0x4d4d;
  2343. key = get4();
  2344. fseek (m_InputFile, 164600, SEEK_SET);
  2345. ptfread (head, 1, 40, m_InputFile);
  2346. sony_decrypt ((unsigned int *) head, 10, 1, key);
  2347. for (i=26; i-- > 22; )
  2348. key = key << 8 | head[i];
  2349. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  2350. for (row=0; row < m_RawHeight; row++) {
  2351. pixel = m_Raw_Image + row*m_RawWidth;
  2352. if (fread (pixel, 2, m_RawWidth, m_InputFile) < m_RawWidth) derror();
  2353. sony_decrypt ((unsigned int *) pixel, m_RawWidth/2, !row, key);
  2354. for (col=0; col < m_RawWidth; col++)
  2355. if ((pixel[col] = ntohs(pixel[col])) >> 14) derror();
  2356. }
  2357. m_WhiteLevel = 0x3ff0;
  2358. }
  2359. void CLASS sony_arw_load_raw()
  2360. {
  2361. uint16_t huff[32768];
  2362. static const uint16_t tab[18] =
  2363. { 0xf11,0xf10,0xe0f,0xd0e,0xc0d,0xb0c,0xa0b,0x90a,0x809,
  2364. 0x708,0x607,0x506,0x405,0x304,0x303,0x300,0x202,0x201 };
  2365. int i, c, n, col, row, len, diff, sum=0;
  2366. for (n=i=0; i < 18; i++)
  2367. for (c=0;c<(32768 >> (tab[i] >> 8));c++) huff[n++] = tab[i];
  2368. getbits(-1);
  2369. for (col = m_RawWidth; col--; )
  2370. for (row=0; row < m_RawHeight+1; row+=2) {
  2371. if (row == m_RawHeight) row = 1;
  2372. len = getbithuff(15,huff);
  2373. diff = getbits(len);
  2374. if ((diff & (1 << (len-1))) == 0)
  2375. diff -= (1 << len) - 1;
  2376. if ((sum += diff) >> 12) derror();
  2377. if (row < m_Height) RAW(row,col) = sum;
  2378. }
  2379. }
  2380. void CLASS sony_arw2_load_raw()
  2381. {
  2382. uint8_t *data, *dp;
  2383. uint16_t pix[16];
  2384. int row, col, val, max, min, imax, imin, sh, bit, i;
  2385. data = (uint8_t *) MALLOC (m_RawWidth);
  2386. merror (data, "sony_arw2_load_raw()");
  2387. for (row=0; row < m_Height; row++) {
  2388. ptfread (data, 1, m_RawWidth, m_InputFile);
  2389. for (dp=data, col=0; col < m_RawWidth-30; dp+=16) {
  2390. max = 0x7ff & (val = sget4(dp));
  2391. min = 0x7ff & val >> 11;
  2392. imax = 0x0f & val >> 22;
  2393. imin = 0x0f & val >> 26;
  2394. for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++) {};
  2395. for (bit=30, i=0; i < 16; i++)
  2396. if (i == imax) pix[i] = max;
  2397. else if (i == imin) pix[i] = min;
  2398. else {
  2399. pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
  2400. if (pix[i] > 0x7ff) pix[i] = 0x7ff;
  2401. bit += 7;
  2402. }
  2403. for (i=0; i < 16; i++, col+=2)
  2404. RAW(row,col) = m_Curve[pix[i] << 1] >> 2;
  2405. col -= col & 1 ? 1:31;
  2406. }
  2407. }
  2408. FREE (data);
  2409. }
  2410. #define HOLE(row) ((holes >> (((row) - m_RawHeight) & 7)) & 1)
  2411. /* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
  2412. void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
  2413. {
  2414. uint8_t hist[3][13] = {
  2415. { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
  2416. { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
  2417. { 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
  2418. int low, high=0xff, carry=0, nbits=8;
  2419. int pix, s, count, bin, next, i, sym[3];
  2420. uint8_t diff, pred[]={0,0};
  2421. uint16_t data=0, range=0;
  2422. fseek (m_InputFile, seg[0][1]+1, SEEK_SET);
  2423. getbits(-1);
  2424. for (pix=seg[0][0]; pix < (int32_t)seg[1][0]; pix++) {
  2425. for (s=0; s < 3; s++) {
  2426. data = data << nbits | getbits(nbits);
  2427. if (carry < 0)
  2428. carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
  2429. while (--nbits >= 0)
  2430. if ((data >> nbits & 0xff) == 0xff) break;
  2431. if (nbits > 0)
  2432. data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
  2433. ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
  2434. if (nbits >= 0) {
  2435. data += getbits(1);
  2436. carry = nbits - 8;
  2437. }
  2438. count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
  2439. for (bin=0; hist[s][bin+5] > count; bin++) {} ;
  2440. low = hist[s][bin+5] * (high >> 4) >> 2;
  2441. if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
  2442. high -= low;
  2443. for (nbits=0; high << nbits < 128; nbits++) {} ;
  2444. range = (range+low) << nbits;
  2445. high <<= nbits;
  2446. next = hist[s][1];
  2447. if (++hist[s][2] > hist[s][3]) {
  2448. next = (next+1) & hist[s][0];
  2449. hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
  2450. hist[s][2] = 1;
  2451. }
  2452. if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
  2453. if (bin < hist[s][1]) {
  2454. #pragma GCC diagnostic push
  2455. #pragma GCC diagnostic ignored "-Warray-bounds"
  2456. for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
  2457. #pragma GCC diagnostic pop
  2458. } else if (next <= bin)
  2459. for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
  2460. }
  2461. hist[s][1] = next;
  2462. sym[s] = bin;
  2463. }
  2464. diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
  2465. if (sym[0] & 4)
  2466. diff = diff ? -diff : 0x80;
  2467. if (unsigned(ftell(m_InputFile) + 12) >= seg[1][1])
  2468. diff = 0;
  2469. m_Raw_Image[pix] = pred[pix & 1] += diff;
  2470. if (!(pix & 1) && HOLE(pix / m_RawWidth)) pix += 2;
  2471. }
  2472. m_WhiteLevel = 0xff;
  2473. }
  2474. void CLASS smal_v6_load_raw()
  2475. {
  2476. unsigned seg[2][2];
  2477. fseek (m_InputFile, 16, SEEK_SET);
  2478. seg[0][0] = 0;
  2479. seg[0][1] = get2();
  2480. seg[1][0] = m_RawWidth * m_RawHeight;
  2481. seg[1][1] = INT_MAX;
  2482. smal_decode_segment (seg, 0);
  2483. }
  2484. int CLASS median4 (int *p)
  2485. {
  2486. int min, max, sum, i;
  2487. min = max = sum = p[0];
  2488. for (i=1; i < 4; i++) {
  2489. sum += p[i];
  2490. if (min > p[i]) min = p[i];
  2491. if (max < p[i]) max = p[i];
  2492. }
  2493. return (sum - min - max) >> 1;
  2494. }
  2495. void CLASS fill_holes (int holes)
  2496. {
  2497. int row, col, val[4];
  2498. for (row=2; row < m_Height-2; row++) {
  2499. if (!HOLE(row)) continue;
  2500. for (col=1; col < m_Width-1; col+=4) {
  2501. val[0] = RAW(row-1,col-1);
  2502. val[1] = RAW(row-1,col+1);
  2503. val[2] = RAW(row+1,col-1);
  2504. val[3] = RAW(row+1,col+1);
  2505. RAW(row,col) = median4(val);
  2506. }
  2507. for (col=2; col < m_Width-2; col+=4)
  2508. if (HOLE(row-2) || HOLE(row+2))
  2509. RAW(row,col) = (RAW(row,col-2) + RAW(row,col+2)) >> 1;
  2510. else {
  2511. val[0] = RAW(row,col-2);
  2512. val[1] = RAW(row,col+2);
  2513. val[2] = RAW(row-2,col);
  2514. val[3] = RAW(row+2,col);
  2515. RAW(row,col) = median4(val);
  2516. }
  2517. }
  2518. }
  2519. void CLASS smal_v9_load_raw()
  2520. {
  2521. unsigned seg[256][2], offset, nseg, holes, i;
  2522. fseek (m_InputFile, 67, SEEK_SET);
  2523. offset = get4();
  2524. nseg = fgetc(m_InputFile);
  2525. fseek (m_InputFile, offset, SEEK_SET);
  2526. for (i=0; i < nseg*2; i++)
  2527. seg[0][i] = get4() + m_Data_Offset*(i & 1);
  2528. fseek (m_InputFile, 78, SEEK_SET);
  2529. holes = fgetc(m_InputFile);
  2530. fseek (m_InputFile, 88, SEEK_SET);
  2531. seg[nseg][0] = m_RawHeight * m_RawWidth;
  2532. seg[nseg][1] = get4() + m_Data_Offset;
  2533. for (i=0; i < nseg; i++)
  2534. smal_decode_segment (seg+i, holes);
  2535. if (holes) fill_holes (holes);
  2536. }
  2537. void CLASS redcine_load_raw()
  2538. {
  2539. #ifndef NO_JASPER
  2540. int c, row, col;
  2541. jas_stream_t *in;
  2542. jas_m_Image_t *jimg;
  2543. jas_matrix_t *jmat;
  2544. jas_seqent_t *data;
  2545. uint16_t *img, *pix;
  2546. jas_init();
  2547. in = jas_stream_fopen (ifname, "rb");
  2548. jas_stream_seek (in, m_Data_Offset+20, SEEK_SET);
  2549. jimg = jas_m_Image_decode (in, -1, 0);
  2550. if (!jimg) longjmp (failure, 3);
  2551. jmat = jas_matrix_create (m_Height/2, m_Width/2);
  2552. merror (jmat, "redcine_m_load_raw()");
  2553. img = (uint16_t *) calloc ((m_Height+2)*(m_Width+2), 2);
  2554. merror (img, "redcine_m_load_raw()");
  2555. for (c=0; c<4; c++) {
  2556. jas_m_Image_readcmpt (jimg, c, 0, 0, m_Width/2, m_Height/2, jmat);
  2557. data = jas_matrix_getref (jmat, 0, 0);
  2558. for (row = c >> 1; row < m_Height; row+=2)
  2559. for (col = c & 1; col < m_Width; col+=2)
  2560. img[(row+1)*(m_Width+2)+col+1] = data[(row/2)*(m_Width/2)+col/2];
  2561. }
  2562. for (col=1; col <= m_Width; col++) {
  2563. img[col] = img[2*(m_Width+2)+col];
  2564. img[(m_Height+1)*(m_Width+2)+col] = img[(m_Height-1)*(m_Width+2)+col];
  2565. }
  2566. for (row=0; row < m_Height+2; row++) {
  2567. img[row*(m_Width+2)] = img[row*(m_Width+2)+2];
  2568. img[(row+1)*(m_Width+2)-1] = img[(row+1)*(m_Width+2)-3];
  2569. }
  2570. for (row=1; row <= m_Height; row++) {
  2571. pix = img + row*(m_Width+2) + (col = 1 + (FC(row,1) & 1));
  2572. for ( ; col <= m_Width; col+=2, pix+=2) {
  2573. c = (((pix[0] - 0x800) << 3) +
  2574. pix[-(m_Width+2)] + pix[m_Width+2] + pix[-1] + pix[1]) >> 2;
  2575. pix[0] = LIM(c,0,4095);
  2576. }
  2577. }
  2578. for (row=0; row < m_Height; row++)
  2579. for (col=0; col < m_Width; col++)
  2580. RAW(row,col) = m_Curve[img[(row+1)*(m_Width+2)+col+1]];
  2581. free (img);
  2582. jas_matrix_destroy (jmat);
  2583. jas_m_Image_destroy (jimg);
  2584. jas_stream_close (in);
  2585. #endif
  2586. }
  2587. /* RESTRICTED code starts here */
  2588. void CLASS foveon_decoder (unsigned size, unsigned code)
  2589. {
  2590. struct decode *cur;
  2591. // int i, len;
  2592. unsigned i,len;
  2593. if (!code) {
  2594. for (unsigned i=0; i < size; i++)
  2595. m_foveon_decoder_huff[i] = get4();
  2596. memset (first_decode, 0, sizeof first_decode);
  2597. free_decode = first_decode;
  2598. }
  2599. cur = free_decode++;
  2600. if (free_decode > first_decode+2048) {
  2601. fprintf (stderr,_("%s: decoder table overflow\n"), m_UserSetting_InputFileName);
  2602. longjmp (m_Failure, 2);
  2603. }
  2604. if (code)
  2605. for (i=0; i < size; i++)
  2606. if (m_foveon_decoder_huff[i] == code) {
  2607. cur->leaf = i;
  2608. return;
  2609. }
  2610. if ((len = code >> 27) > 26) return;
  2611. code = (len+1) << 27 | (code & 0x3ffffff) << 1;
  2612. cur->branch[0] = free_decode;
  2613. foveon_decoder (size, code);
  2614. cur->branch[1] = free_decode;
  2615. foveon_decoder (size, code+1);
  2616. }
  2617. void CLASS foveon_thumb ()
  2618. /* Remember: This function is modified to write the rawÂ’s thumbnail to the
  2619. m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
  2620. */
  2621. // TODO: Tests needed: What format is this? Can it be read by QPixmap?
  2622. {
  2623. unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
  2624. char *buf;
  2625. struct decode *dindex;
  2626. short pred[3];
  2627. bwide = get4();
  2628. //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
  2629. QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
  2630. VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
  2631. if (bwide > 0) {
  2632. if (bwide < (unsigned)(m_ThumbWidth*3)) return;
  2633. buf = (char *) MALLOC (bwide);
  2634. merror (buf, "foveon_thumb()");
  2635. for (row=0; row < m_ThumbHeight; row++) {
  2636. ptfread (buf, 1, bwide, m_InputFile);
  2637. //ptfwrite (buf, 3, m_ThumbWidth, m_OutputFile);
  2638. VAppend(m_Thumb, buf, 3 * m_ThumbWidth);
  2639. }
  2640. FREE (buf);
  2641. return;
  2642. }
  2643. foveon_decoder (256, 0);
  2644. for (row=0; row < m_ThumbHeight; row++) {
  2645. memset (pred, 0, sizeof pred);
  2646. if (!bit) get4();
  2647. for (bit=col=0; col < m_ThumbWidth; col++)
  2648. for (c=0; c<3; c++) {
  2649. for (dindex=first_decode; dindex->branch[0]; ) {
  2650. if ((bit = (bit-1) & 31) == 31)
  2651. for (i=0; i < 4; i++)
  2652. bitbuf = (bitbuf << 8) + fgetc(m_InputFile);
  2653. dindex = dindex->branch[bitbuf >> bit & 1];
  2654. }
  2655. pred[c] += dindex->leaf;
  2656. //fputc (pred[c], m_OutputFile);
  2657. #pragma GCC diagnostic push
  2658. #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
  2659. m_Thumb.push_back(pred[c]);
  2660. #pragma GCC diagnostic pop
  2661. }
  2662. }
  2663. }
  2664. void CLASS foveon_sd_load_raw()
  2665. {
  2666. struct decode *dindex;
  2667. short diff[1024];
  2668. unsigned bitbuf=0;
  2669. int pred[3], row, col, bit=-1, c, i;
  2670. read_shorts ((uint16_t *) diff, 1024);
  2671. if (!m_Load_Flags) foveon_decoder (1024, 0);
  2672. for (row=0; row < m_Height; row++) {
  2673. memset (pred, 0, sizeof pred);
  2674. if (!bit && !m_Load_Flags && atoi(m_CameraModel+2) < 14) get4();
  2675. for (col=bit=0; col < m_Width; col++) {
  2676. if (m_Load_Flags) {
  2677. bitbuf = get4();
  2678. for (c=0; c<3; c++) pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
  2679. }
  2680. else for (c=0; c<3; c++) {
  2681. for (dindex=first_decode; dindex->branch[0]; ) {
  2682. if ((bit = (bit-1) & 31) == 31)
  2683. for (i=0; i < 4; i++)
  2684. bitbuf = (bitbuf << 8) + fgetc(m_InputFile);
  2685. dindex = dindex->branch[bitbuf >> bit & 1];
  2686. }
  2687. pred[c] += diff[dindex->leaf];
  2688. if (pred[c] >> 16 && ~pred[c] >> 16) derror();
  2689. }
  2690. for (c=0; c<3; c++) m_Image[row*m_Width+col][c] = pred[c];
  2691. }
  2692. }
  2693. }
  2694. void CLASS foveon_huff (uint16_t *huff)
  2695. {
  2696. int i, j, clen, code;
  2697. huff[0] = 8;
  2698. for (i=0; i < 13; i++) {
  2699. clen = getc(m_InputFile);
  2700. code = getc(m_InputFile);
  2701. for (j=0; j < 256 >> clen; )
  2702. huff[code+ ++j] = clen << 8 | i;
  2703. }
  2704. get2();
  2705. }
  2706. void CLASS foveon_dp_load_raw()
  2707. {
  2708. unsigned c, roff[4], row, col, diff;
  2709. uint16_t huff[258], vpred[2][2], hpred[2];
  2710. fseek (m_InputFile, 8, SEEK_CUR);
  2711. foveon_huff (huff);
  2712. roff[0] = 48;
  2713. for (c=0; c<3; c++) roff[c+1] = -(-(roff[c] + get4()) & -16);
  2714. for (c=0; c<3; c++) {
  2715. fseek (m_InputFile, m_Data_Offset+roff[c], SEEK_SET);
  2716. getbits(-1);
  2717. vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
  2718. for (row=0; row < m_Height; row++) {
  2719. for (col=0; col < m_Width; col++) {
  2720. diff = ljpeg_diff(huff);
  2721. if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  2722. else hpred[col & 1] += diff;
  2723. m_Image[row*m_Width+col][c] = hpred[col & 1];
  2724. }
  2725. }
  2726. }
  2727. }
  2728. void CLASS foveon_load_camf()
  2729. {
  2730. unsigned type, wide, high, i, j, row, col, diff;
  2731. uint16_t huff[258], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
  2732. fseek (m_InputFile, meta_offset, SEEK_SET);
  2733. type = get4(); get4(); get4();
  2734. wide = get4();
  2735. high = get4();
  2736. if (type == 2) {
  2737. ptfread (m_MetaData, 1, m_MetaLength, m_InputFile);
  2738. for (i=0; i < m_MetaLength; i++) {
  2739. high = (high * 1597 + 51749) % 244944;
  2740. wide = high * (INT64) 301593171 >> 24;
  2741. m_MetaData[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
  2742. }
  2743. } else if (type == 4) {
  2744. FREE (m_MetaData);
  2745. m_MetaData = (char *) MALLOC (m_MetaLength = wide*high*3/2);
  2746. merror (m_MetaData, "foveon_load_camf()");
  2747. foveon_huff (huff);
  2748. get4();
  2749. getbits(-1);
  2750. for (j=row=0; row < high; row++) {
  2751. for (col=0; col < wide; col++) {
  2752. diff = ljpeg_diff(huff);
  2753. if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
  2754. else hpred[col & 1] += diff;
  2755. if (col & 1) {
  2756. m_MetaData[j++] = hpred[0] >> 4;
  2757. m_MetaData[j++] = hpred[0] << 4 | hpred[1] >> 8;
  2758. m_MetaData[j++] = hpred[1];
  2759. }
  2760. }
  2761. }
  2762. } else
  2763. fprintf (stderr,_("%s has unknown CAMF type %d.\n"), m_UserSetting_InputFileName, type);
  2764. }
  2765. const char * CLASS foveon_camf_param (const char *block, const char *param)
  2766. {
  2767. unsigned idx, num;
  2768. char *pos, *cp, *dp;
  2769. for (idx=0; idx < m_MetaLength; idx += sget4(pos+8)) {
  2770. pos = m_MetaData + idx;
  2771. if (strncmp (pos, "CMb", 3)) break;
  2772. if (pos[3] != 'P') continue;
  2773. if (strcmp (block, pos+sget4(pos+12))) continue;
  2774. cp = pos + sget4(pos+16);
  2775. num = sget4(cp);
  2776. dp = pos + sget4(cp+4);
  2777. while (num--) {
  2778. cp += 8;
  2779. if (!strcmp (param, dp+sget4(cp)))
  2780. return dp+sget4(cp+4);
  2781. }
  2782. }
  2783. return 0;
  2784. }
  2785. void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
  2786. {
  2787. unsigned i, idx, type, ndim, size, *mat;
  2788. char *pos, *cp, *dp;
  2789. double dsize;
  2790. for (idx=0; idx < m_MetaLength; idx += sget4(pos+8)) {
  2791. pos = m_MetaData + idx;
  2792. if (strncmp (pos, "CMb", 3)) break;
  2793. if (pos[3] != 'M') continue;
  2794. if (strcmp (name, pos+sget4(pos+12))) continue;
  2795. dim[0] = dim[1] = dim[2] = 1;
  2796. cp = pos + sget4(pos+16);
  2797. type = sget4(cp);
  2798. if ((ndim = sget4(cp+4)) > 3) break;
  2799. dp = pos + sget4(cp+8);
  2800. for (i=ndim; i--; ) {
  2801. cp += 12;
  2802. dim[i] = sget4(cp);
  2803. }
  2804. if ((dsize = (double) dim[0]*dim[1]*dim[2]) > m_MetaLength/4) break;
  2805. mat = (unsigned *) MALLOC ((size = (unsigned) dsize) * 4);
  2806. merror (mat, "foveon_camf_matrix()");
  2807. for (i=0; i < size; i++)
  2808. if (type && type != 6)
  2809. mat[i] = sget4(dp + i*4);
  2810. else
  2811. mat[i] = sget4(dp + i*2) & 0xffff;
  2812. return mat;
  2813. }
  2814. fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), m_UserSetting_InputFileName, name);
  2815. return 0;
  2816. }
  2817. int CLASS foveon_fixed (void *ptr, int size, const char *name)
  2818. {
  2819. void *dp;
  2820. unsigned dim[3];
  2821. if (!name) return 0;
  2822. dp = foveon_camf_matrix (dim, name);
  2823. if (!dp) return 0;
  2824. memcpy (ptr, dp, size*4);
  2825. FREE (dp);
  2826. return 1;
  2827. }
  2828. float CLASS foveon_avg (short *pix, int range[2], float cfilt)
  2829. {
  2830. int i;
  2831. float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
  2832. for (i=range[0]; i <= range[1]; i++) {
  2833. sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
  2834. if (min > val) min = val;
  2835. if (max < val) max = val;
  2836. }
  2837. if (range[1] - range[0] == 1) return sum/2;
  2838. return (sum - min - max) / (range[1] - range[0] - 1);
  2839. }
  2840. short * CLASS foveon_make_curve (double max, double mul, double filt)
  2841. {
  2842. short *curve;
  2843. unsigned i, size;
  2844. double x;
  2845. if (!filt) filt = 0.8;
  2846. size = (unsigned) (4*ptPI*max / filt);
  2847. if (size == UINT_MAX) size--;
  2848. curve = (short *) CALLOC (size+1, sizeof *curve);
  2849. merror (curve, "foveon_make_curve()");
  2850. curve[0] = size;
  2851. for (i=0; i < size; i++) {
  2852. x = i*filt/max/4;
  2853. curve[i+1] = (short) ((cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5);
  2854. }
  2855. return curve;
  2856. }
  2857. void CLASS foveon_make_curves
  2858. (short **curvep, float dq[3], float div[3], float filt)
  2859. {
  2860. double mul[3], max=0;
  2861. int c;
  2862. for (c=0; c<3; c++) mul[c] = dq[c]/div[c];
  2863. for (c=0; c<3; c++) if (max < mul[c]) max = mul[c];
  2864. for (c=0; c<3; c++) curvep[c] = foveon_make_curve (max, mul[c], filt);
  2865. }
  2866. int CLASS foveon_apply_curve (short *l_Curve, int i)
  2867. {
  2868. if (abs(i) >= l_Curve[0]) return 0;
  2869. return i < 0 ? -l_Curve[1-i] : l_Curve[1+i];
  2870. }
  2871. #define m_Image ((short (*)[4]) m_Image)
  2872. void CLASS foveon_interpolate()
  2873. {
  2874. #pragma GCC diagnostic push
  2875. #pragma GCC diagnostic ignored "-Warray-bounds"
  2876. static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
  2877. short *pix, prev[3], *l_curve[8], (*shrink)[3];
  2878. float cfilt=0, ddft[3][3][2], ppm[3][3][3];
  2879. float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
  2880. float chroma_dq[3], color_dq[3], diag[3][3], div[3];
  2881. float (*black)[3], (*sgain)[3], (*sgrow)[3];
  2882. float fsum[3], val, frow, num;
  2883. int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
  2884. int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
  2885. int work[3][3], smlast, smred, smred_p=0, dev[3];
  2886. int satlev[3], keep[4], active[4];
  2887. unsigned dim[3], *badpix;
  2888. double dsum=0, trsum[3];
  2889. char str[128];
  2890. const char* cp;
  2891. memset(cam_xyz, 0, sizeof(cam_xyz));
  2892. memset(dscr, 0, sizeof(dscr));
  2893. memset(dstb, 0, sizeof(dstb));
  2894. memset(active, 0, sizeof(active));
  2895. memset(keep, 0, sizeof(keep));
  2896. TRACEKEYVALS("Foveon interpolation","%s","");
  2897. foveon_load_camf();
  2898. foveon_fixed (dscr, 4, "DarkShieldColRange");
  2899. foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
  2900. foveon_fixed (satlev, 3, "SaturationLevel");
  2901. foveon_fixed (keep, 4, "KeepImageArea");
  2902. foveon_fixed (active, 4, "ActiveImageArea");
  2903. foveon_fixed (chroma_dq, 3, "ChromaDQ");
  2904. foveon_fixed (color_dq, 3,
  2905. foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
  2906. "ColorDQ" : "ColorDQCamRGB");
  2907. if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
  2908. foveon_fixed (&cfilt, 1, "ColumnFilter");
  2909. memset (ddft, 0, sizeof ddft);
  2910. if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
  2911. || !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
  2912. for (i=0; i < 2; i++) {
  2913. foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
  2914. for (row = dstb[1]; row <= dstb[3]; row++)
  2915. for (col = dstb[0]; col <= dstb[2]; col++)
  2916. for (c=0; c<3; c++) ddft[i+1][c][1] += (short) m_Image[row*m_Width+col][c];
  2917. for (c=0; c<3; c++) ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
  2918. }
  2919. if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", m_CameraModelBis)))
  2920. { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), m_UserSetting_InputFileName, m_CameraModelBis);
  2921. return; }
  2922. foveon_fixed (cam_xyz, 9, cp);
  2923. foveon_fixed (correct, 9,
  2924. foveon_camf_param ("WhiteBalanceCorrections", m_CameraModelBis));
  2925. memset (last, 0, sizeof last);
  2926. for (i=0; i < 3; i++)
  2927. for (j=0; j < 3; j++)
  2928. for (c=0; c<3; c++) last[i][j] += correct[i][c] * cam_xyz[c][j];
  2929. #define LAST(x,y) last[(i+x)%3][(c+y)%3]
  2930. for (i=0; i < 3; i++)
  2931. for (c=0; c<3; c++) diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
  2932. #undef LAST
  2933. for (c=0; c<3; c++) div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
  2934. sprintf (str, "%sRGBNeutral", m_CameraModelBis);
  2935. if (foveon_camf_param ("IncludeBlocks", str))
  2936. foveon_fixed (div, 3, str);
  2937. num = 0;
  2938. for (c=0; c<3; c++) if (num < div[c]) num = div[c];
  2939. for (c=0; c<3; c++) div[c] /= num;
  2940. memset (trans, 0, sizeof trans);
  2941. for (i=0; i < 3; i++)
  2942. for (j=0; j < 3; j++)
  2943. for (c=0; c<3; c++) trans[i][j] += m_MatrixCamRGBToSRGB[i][c] * last[c][j] * div[j];
  2944. for (c=0; c<3; c++) trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
  2945. dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
  2946. for (i=0; i < 3; i++)
  2947. for (c=0; c<3; c++) last[i][c] = trans[i][c] * dsum / trsum[i];
  2948. memset (trans, 0, sizeof trans);
  2949. for (i=0; i < 3; i++)
  2950. for (j=0; j < 3; j++)
  2951. for (c=0; c<3; c++) trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
  2952. foveon_make_curves (l_curve, color_dq, div, cfilt);
  2953. for (c=0; c<3; c++) chroma_dq[c] /= 3;
  2954. foveon_make_curves (l_curve+3, chroma_dq, div, cfilt);
  2955. for (c=0; c<3; c++) dsum += chroma_dq[c] / div[c];
  2956. l_curve[6] = foveon_make_curve (dsum, dsum, cfilt);
  2957. l_curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
  2958. sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
  2959. if (!sgain) return;
  2960. sgrow = (float (*)[3]) CALLOC (dim[1], sizeof *sgrow);
  2961. sgx = (m_Width + dim[1]-2) / (dim[1]-1);
  2962. black = (float (*)[3]) CALLOC (m_Height, sizeof *black);
  2963. for (row=0; row < m_Height; row++) {
  2964. for (i=0; i < 6; i++)
  2965. ddft[0][0][i] = ddft[1][0][i] +
  2966. row / (m_Height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
  2967. for (c=0; c<3; c++) black[row][c] =
  2968. ( foveon_avg (m_Image[row*m_Width]+c, dscr[0], cfilt) +
  2969. foveon_avg (m_Image[row*m_Width]+c, dscr[1], cfilt) * 3
  2970. - ddft[0][c][0] ) / 4 - ddft[0][c][1];
  2971. }
  2972. memcpy (black, black+8, sizeof *black*8);
  2973. memcpy (black+m_Height-11, black+m_Height-22, 11*sizeof *black);
  2974. memcpy (last, black, sizeof last);
  2975. for (row=1; row < m_Height-1; row++) {
  2976. for (c=0; c<3; c++) if (last[1][c] > last[0][c]) {
  2977. if (last[1][c] > last[2][c])
  2978. black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
  2979. } else
  2980. if (last[1][c] < last[2][c])
  2981. black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
  2982. memmove (last, last+1, 2*sizeof last[0]);
  2983. memcpy (last[2], black[row+1], sizeof last[2]);
  2984. }
  2985. for (c=0; c<3; c++) black[row][c] = (last[0][c] + last[1][c])/2;
  2986. for (c=0; c<3; c++) black[0][c] = (black[1][c] + black[3][c])/2;
  2987. val = 1 - exp(-1/24.0);
  2988. memcpy (fsum, black, sizeof fsum);
  2989. for (row=1; row < m_Height; row++)
  2990. for (c=0; c<3; c++) fsum[c] += black[row][c] =
  2991. (black[row][c] - black[row-1][c])*val + black[row-1][c];
  2992. memcpy (last[0], black[m_Height-1], sizeof last[0]);
  2993. for (c=0; c<3; c++) fsum[c] /= m_Height;
  2994. for (row = m_Height; row--; )
  2995. for (c=0; c<3; c++) last[0][c] = black[row][c] =
  2996. (black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
  2997. memset (total, 0, sizeof total);
  2998. for (row=2; row < m_Height; row+=4)
  2999. for (col=2; col < m_Width; col+=4) {
  3000. for (c=0; c<3; c++) total[c] += (short) m_Image[row*m_Width+col][c];
  3001. total[3]++;
  3002. }
  3003. for (row=0; row < m_Height; row++)
  3004. for (c=0; c<3; c++) black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
  3005. for (row=0; row < m_Height; row++) {
  3006. for (i=0; i < 6; i++)
  3007. ddft[0][0][i] = ddft[1][0][i] +
  3008. row / (m_Height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
  3009. pix = m_Image[row*m_Width];
  3010. memcpy (prev, pix, sizeof prev);
  3011. frow = row / (m_Height-1.0) * (dim[2]-1);
  3012. if ((unsigned)(irow = (int)(frow)) == dim[2]-1) irow--;
  3013. frow -= irow;
  3014. for (i=0; (unsigned) i < dim[1]; i++)
  3015. for (c=0; c<3; c++) sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) +
  3016. sgain[(irow+1)*dim[1]+i][c] * frow;
  3017. for (col=0; col < m_Width; col++) {
  3018. for (c=0; c<3; c++) {
  3019. diff = pix[c] - prev[c];
  3020. prev[c] = pix[c];
  3021. ipix[c] = (int)(pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
  3022. - ddft[0][c][1] - ddft[0][c][0] * ((float) col/m_Width - 0.5)
  3023. - black[row][c] ));
  3024. }
  3025. for (c=0; c<3; c++) {
  3026. work[0][c] = ipix[c] * ipix[c] >> 14;
  3027. work[2][c] = ipix[c] * work[0][c] >> 14;
  3028. work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
  3029. }
  3030. for (c=0; c<3; c++) {
  3031. for (val=i=0; i < 3; i++)
  3032. for ( j=0; j < 3; j++)
  3033. val += ppm[c][i][j] * work[i][j];
  3034. ipix[c] = (int) (floor ((ipix[c] + floor(val)) *
  3035. ( sgrow[col/sgx ][c] * (sgx - col%sgx) +
  3036. sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]));
  3037. if (ipix[c] > 32000) ipix[c] = 32000;
  3038. pix[c] = ipix[c];
  3039. }
  3040. pix += 4;
  3041. }
  3042. }
  3043. FREE (black);
  3044. FREE (sgrow);
  3045. FREE (sgain);
  3046. if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
  3047. for (i=0; (unsigned) i < dim[0]; i++) {
  3048. col = (badpix[i] >> 8 & 0xfff) - keep[0];
  3049. row = (badpix[i] >> 20 ) - keep[1];
  3050. if ((unsigned)(row-1) > (unsigned)(m_Height-3) || (unsigned)(col-1) > (unsigned)(m_Width-3))
  3051. continue;
  3052. memset (fsum, 0, sizeof fsum);
  3053. for (sum=j=0; j < 8; j++)
  3054. if (badpix[i] & (1 << j)) {
  3055. for (c=0; c<3; c++) fsum[c] += (short)
  3056. m_Image[(row+hood[j*2])*m_Width+col+hood[j*2+1]][c];
  3057. sum++;
  3058. }
  3059. if (sum) for (c=0; c<3; c++) m_Image[row*m_Width+col][c] = (short) (fsum[c]/sum);
  3060. }
  3061. FREE (badpix);
  3062. }
  3063. /* Array for 5x5 Gaussian averaging of red values */
  3064. smrow[6] = (int (*)[3]) CALLOC (m_Width*5, sizeof **smrow);
  3065. merror (smrow[6], "foveon_interpolate()");
  3066. for (i=0; i < 5; i++)
  3067. smrow[i] = smrow[6] + i*m_Width;
  3068. /* Sharpen the reds against these Gaussian averages */
  3069. for (smlast=-1, row=2; row < m_Height-2; row++) {
  3070. while (smlast < row+2) {
  3071. for (i=0; i < 6; i++)
  3072. smrow[(i+5) % 6] = smrow[i];
  3073. pix = m_Image[++smlast*m_Width+2];
  3074. for (col=2; col < m_Width-2; col++) {
  3075. smrow[4][col][0] =
  3076. (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
  3077. pix += 4;
  3078. }
  3079. }
  3080. pix = m_Image[row*m_Width+2];
  3081. for (col=2; col < m_Width-2; col++) {
  3082. smred = ( 6 * smrow[2][col][0]
  3083. + 4 * (smrow[1][col][0] + smrow[3][col][0])
  3084. + smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
  3085. if (col == 2)
  3086. smred_p = smred;
  3087. i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
  3088. if (i > 32000) i = 32000;
  3089. pix[0] = i;
  3090. smred_p = smred;
  3091. pix += 4;
  3092. }
  3093. }
  3094. /* Adjust the brighter pixels for better linearity */
  3095. min = 0xffff;
  3096. for (c=0; c<3; c++) {
  3097. i = (int)(satlev[c] / div[c]);
  3098. if (min > i) min = i;
  3099. }
  3100. limit = min * 9 >> 4;
  3101. for (pix=m_Image[0]; pix < m_Image[m_Height*m_Width]; pix+=4) {
  3102. if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
  3103. continue;
  3104. min = max = pix[0];
  3105. for (c=1; c < 3; c++) {
  3106. if (min > pix[c]) min = pix[c];
  3107. if (max < pix[c]) max = pix[c];
  3108. }
  3109. if (min >= limit*2) {
  3110. pix[0] = pix[1] = pix[2] = max;
  3111. } else {
  3112. i = 0x4000 - ((min - limit) << 14) / limit;
  3113. i = 0x4000 - (i*i >> 14);
  3114. i = i*i >> 14;
  3115. for (c=0; c<3; c++) pix[c] += (max - pix[c]) * i >> 14;
  3116. }
  3117. }
  3118. /*
  3119. Because photons that miss one detector often hit another,
  3120. the sum R+G+B is much less noisy than the individual colors.
  3121. So smooth the hues without smoothing the total.
  3122. */
  3123. for (smlast=-1, row=2; row < m_Height-2; row++) {
  3124. while (smlast < row+2) {
  3125. for (i=0; i < 6; i++)
  3126. smrow[(i+5) % 6] = smrow[i];
  3127. pix = m_Image[++smlast*m_Width+2];
  3128. for (col=2; col < m_Width-2; col++) {
  3129. for (c=0; c<3; c++) smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
  3130. pix += 4;
  3131. }
  3132. }
  3133. pix = m_Image[row*m_Width+2];
  3134. for (col=2; col < m_Width-2; col++) {
  3135. for (c=0; c<3; c++) dev[c] = -foveon_apply_curve (l_curve[7], pix[c] -
  3136. ((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
  3137. sum = (dev[0] + dev[1] + dev[2]) >> 3;
  3138. for (c=0; c<3; c++) pix[c] += dev[c] - sum;
  3139. pix += 4;
  3140. }
  3141. }
  3142. for (smlast=-1, row=2; row < m_Height-2; row++) {
  3143. while (smlast < row+2) {
  3144. for (i=0; i < 6; i++)
  3145. smrow[(i+5) % 6] = smrow[i];
  3146. pix = m_Image[++smlast*m_Width+2];
  3147. for (col=2; col < m_Width-2; col++) {
  3148. for (c=0; c<3; c++) smrow[4][col][c] =
  3149. (pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
  3150. pix += 4;
  3151. }
  3152. }
  3153. pix = m_Image[row*m_Width+2];
  3154. for (col=2; col < m_Width-2; col++) {
  3155. for (total[3]=375, sum=60, c=0; c < 3; c++) {
  3156. for (total[c]=i=0; i < 5; i++)
  3157. total[c] += smrow[i][col][c];
  3158. total[3] += total[c];
  3159. sum += pix[c];
  3160. }
  3161. if (sum < 0) sum = 0;
  3162. j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
  3163. for (c=0; c<3; c++) pix[c] += foveon_apply_curve (l_curve[6],
  3164. ((j*total[c] + 0x8000) >> 16) - pix[c]);
  3165. pix += 4;
  3166. }
  3167. }
  3168. /* Transform the image to a different colorspace */
  3169. for (pix=m_Image[0]; pix < m_Image[m_Height*m_Width]; pix+=4) {
  3170. for (c=0; c<3; c++) pix[c] -= foveon_apply_curve (l_curve[c], pix[c]);
  3171. sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
  3172. for (c=0; c<3; c++) pix[c] -= foveon_apply_curve (l_curve[c], pix[c]-sum);
  3173. for (c=0; c<3; c++) {
  3174. for (dsum=i=0; i < 3; i++)
  3175. dsum += trans[c][i] * pix[i];
  3176. if (dsum < 0) dsum = 0;
  3177. if (dsum > 24000) dsum = 24000;
  3178. ipix[c] = (int)(dsum + 0.5);
  3179. }
  3180. for (c=0; c<3; c++) pix[c] = ipix[c];
  3181. }
  3182. /* Smooth the image bottom-to-top and save at 1/4 scale */
  3183. shrink = (short (*)[3]) CALLOC ((m_Width/4) * (m_Height/4), sizeof *shrink);
  3184. merror (shrink, "foveon_interpolate()");
  3185. for (row = m_Height/4; row--; )
  3186. for (col=0; col < m_Width/4; col++) {
  3187. ipix[0] = ipix[1] = ipix[2] = 0;
  3188. for (i=0; i < 4; i++)
  3189. for (j=0; j < 4; j++)
  3190. for (c=0; c<3; c++) ipix[c] += m_Image[(row*4+i)*m_Width+col*4+j][c];
  3191. for (c=0; c<3; c++)
  3192. if (row+2 > m_Height/4)
  3193. shrink[row*(m_Width/4)+col][c] = ipix[c] >> 4;
  3194. else
  3195. shrink[row*(m_Width/4)+col][c] =
  3196. (shrink[(row+1)*(m_Width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
  3197. }
  3198. /* From the 1/4-scale image, smooth right-to-left */
  3199. for (row=0; row < (m_Height & ~3); row++) {
  3200. ipix[0] = ipix[1] = ipix[2] = 0;
  3201. if ((row & 3) == 0)
  3202. for (col = m_Width & ~3 ; col--; )
  3203. for (c=0; c<3; c++) smrow[0][col][c] = ipix[c] =
  3204. (shrink[(row/4)*(m_Width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
  3205. /* Then smooth left-to-right */
  3206. ipix[0] = ipix[1] = ipix[2] = 0;
  3207. for (col=0; col < (m_Width & ~3); col++)
  3208. for (c=0; c<3; c++) smrow[1][col][c] = ipix[c] =
  3209. (smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
  3210. /* Smooth top-to-bottom */
  3211. if (row == 0)
  3212. memcpy (smrow[2], smrow[1], sizeof **smrow * m_Width);
  3213. else
  3214. for (col=0; col < (m_Width & ~3); col++)
  3215. for (c=0; c<3; c++) smrow[2][col][c] =
  3216. (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
  3217. /* Adjust the chroma toward the smooth values */
  3218. for (col=0; col < (m_Width & ~3); col++) {
  3219. for (i=j=30, c=0; c < 3; c++) {
  3220. i += smrow[2][col][c];
  3221. j += m_Image[row*m_Width+col][c];
  3222. }
  3223. j = (j << 16) / i;
  3224. for (sum=c=0; c < 3; c++) {
  3225. ipix[c] = foveon_apply_curve (l_curve[c+3],
  3226. ((smrow[2][col][c] * j + 0x8000) >> 16) - m_Image[row*m_Width+col][c]);
  3227. sum += ipix[c];
  3228. }
  3229. sum >>= 3;
  3230. for (c=0; c<3; c++) {
  3231. i = m_Image[row*m_Width+col][c] + ipix[c] - sum;
  3232. if (i < 0) i = 0;
  3233. m_Image[row*m_Width+col][c] = i;
  3234. }
  3235. }
  3236. }
  3237. FREE (shrink);
  3238. FREE (smrow[6]);
  3239. for (i=0; i < 8; i++)
  3240. FREE (l_curve[i]);
  3241. /* Trim off the black border */
  3242. active[1] -= keep[1];
  3243. active[3] -= 2;
  3244. i = active[2] - active[0];
  3245. for (row=0; row < active[3]-active[1]; row++)
  3246. memcpy (m_Image[row*i], m_Image[(row+active[1])*m_Width+active[0]],
  3247. i * sizeof *m_Image);
  3248. m_Width = i;
  3249. m_Height = row;
  3250. #pragma GCC diagnostic pop
  3251. }
  3252. #undef m_Image
  3253. /* RESTRICTED code ends here */
  3254. void CLASS crop_masked_pixels()
  3255. {
  3256. int row, col;
  3257. unsigned r, c, m, mm_BlackLevel[8], zero, val;
  3258. if (m_LoadRawFunction == &CLASS phase_one_load_raw ||
  3259. m_LoadRawFunction == &CLASS phase_one_load_raw_c)
  3260. phase_one_correct();
  3261. if (m_Fuji_Width) {
  3262. for (row=0; row < m_RawHeight-m_TopMargin*2; row++) {
  3263. for (col=0; col < m_Fuji_Width << !fuji_layout; col++) {
  3264. if (fuji_layout) {
  3265. r = m_Fuji_Width - 1 - col + (row >> 1);
  3266. c = col + ((row+1) >> 1);
  3267. } else {
  3268. r = m_Fuji_Width - 1 + row - (col >> 1);
  3269. c = row + ((col+1) >> 1);
  3270. }
  3271. if (r < m_Height && c < m_Width)
  3272. BAYER(r,c) = RAW(row+m_TopMargin,col+m_LeftMargin);
  3273. }
  3274. }
  3275. } else {
  3276. for (row=0; row < m_Height; row++)
  3277. for (col=0; col < m_Width; col++)
  3278. BAYER2(row,col) = RAW(row+m_TopMargin,col+m_LeftMargin);
  3279. }
  3280. if (m_Mask[0][3]) goto mask_set;
  3281. if (m_LoadRawFunction == &CLASS canon_load_raw ||
  3282. m_LoadRawFunction == &CLASS lossless_jpeg_load_raw) {
  3283. m_Mask[0][1] = m_Mask[1][1] = 2;
  3284. m_Mask[0][3] = -2;
  3285. goto sides;
  3286. }
  3287. if (m_LoadRawFunction == &CLASS canon_600_load_raw ||
  3288. m_LoadRawFunction == &CLASS sony_load_raw ||
  3289. (m_LoadRawFunction == &CLASS eight_bit_load_raw && strncmp(m_CameraModel,"DC2",3)) ||
  3290. m_LoadRawFunction == &CLASS kodak_262_load_raw ||
  3291. (m_LoadRawFunction == &CLASS packed_load_raw && (m_Load_Flags & 32))) {
  3292. sides:
  3293. m_Mask[0][0] = m_Mask[1][0] = m_TopMargin;
  3294. m_Mask[0][2] = m_Mask[1][2] = m_TopMargin+m_Height;
  3295. m_Mask[0][3] += m_LeftMargin;
  3296. m_Mask[1][1] += m_LeftMargin+m_Width;
  3297. m_Mask[1][3] += m_RawWidth;
  3298. }
  3299. if (m_LoadRawFunction == &CLASS nokia_load_raw) {
  3300. m_Mask[0][2] = m_TopMargin;
  3301. m_Mask[0][3] = m_Width;
  3302. }
  3303. mask_set:
  3304. memset (mm_BlackLevel, 0, sizeof mm_BlackLevel);
  3305. for (zero=m=0; m < 8; m++)
  3306. for (row=m_Mask[m][0]; row < m_Mask[m][2]; row++)
  3307. for (col=m_Mask[m][1]; col < m_Mask[m][3]; col++) {
  3308. c = FC(row-m_TopMargin,col-m_LeftMargin);
  3309. mm_BlackLevel[c] += val = RAW(row,col);
  3310. mm_BlackLevel[4+c]++;
  3311. zero += !val;
  3312. }
  3313. if (m_LoadRawFunction == &CLASS canon_600_load_raw && m_Width < m_RawWidth) {
  3314. m_BlackLevel = (mm_BlackLevel[0]+mm_BlackLevel[1]+mm_BlackLevel[2]+mm_BlackLevel[3]) /
  3315. (mm_BlackLevel[4]+mm_BlackLevel[5]+mm_BlackLevel[6]+mm_BlackLevel[7]) - 4;
  3316. canon_600_correct();
  3317. } else if (zero < mm_BlackLevel[4] && mm_BlackLevel[5] && mm_BlackLevel[6] && mm_BlackLevel[7])
  3318. for (c=0; c<4; c++) m_CBlackLevel[c] = mm_BlackLevel[c] / mm_BlackLevel[4+c];
  3319. }
  3320. void CLASS remove_zeroes()
  3321. {
  3322. unsigned row, col, tot, n, r, c;
  3323. for (row=0; row < m_Height; row++)
  3324. for (col=0; col < m_Width; col++)
  3325. if (BAYER(row,col) == 0) {
  3326. tot = n = 0;
  3327. for (r = row-2; r <= row+2; r++)
  3328. for (c = col-2; c <= col+2; c++)
  3329. if (r < m_Height && c < m_Width &&
  3330. FC(r,c) == FC(row,col) && BAYER(r,c))
  3331. tot += (n++,BAYER(r,c));
  3332. if (n) BAYER(row,col) = tot/n;
  3333. }
  3334. }
  3335. /*
  3336. Seach from the current directory up to the root looking for
  3337. a ".badpixels" file, and fix those pixels now.
  3338. */
  3339. void CLASS bad_pixels (const char *cfname)
  3340. {
  3341. FILE *fp=0;
  3342. char *cp, line[128];
  3343. int /* len, */ time, row, col, r, c, rad, tot, n;
  3344. if (!m_Filters) return;
  3345. if (cfname)
  3346. fp = fopen (cfname, "r");
  3347. /* MASK AWAY IN dcRaw
  3348. else {
  3349. for (len=32 ; ; len *= 2) {
  3350. fname = (char *) MALLOC (len);
  3351. if (!fname) return;
  3352. if (getcwd (fname, len-16)) break;
  3353. FREE (fname);
  3354. if (errno != ERANGE) return;
  3355. }
  3356. #if defined(WIN32) || defined(DJGPP)
  3357. if (fname[1] == ':')
  3358. memmove (fname, fname+2, len-2);
  3359. for (cp=fname; *cp; cp++)
  3360. if (*cp == '\\') *cp = '/';
  3361. #endif
  3362. cp = fname + strlen(fname);
  3363. if (cp[-1] == '/') cp--;
  3364. while (*fname == '/') {
  3365. strcpy (cp, "/.badpixels");
  3366. if ((fp = fopen (fname, "r"))) break;
  3367. if (cp == fname) break;
  3368. while (*--cp != '/');
  3369. }
  3370. FREE (fname);
  3371. }
  3372. */
  3373. if (!fp) return;
  3374. while (fgets (line, 128, fp)) {
  3375. cp = strchr (line, '#');
  3376. if (cp) *cp = 0;
  3377. if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
  3378. if ((unsigned) col >= m_Width || (unsigned) row >= m_Height) continue;
  3379. if (time > m_TimeStamp) continue;
  3380. for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
  3381. for (r = row-rad; r <= row+rad; r++)
  3382. for (c = col-rad; c <= col+rad; c++)
  3383. if ((unsigned) r < m_Height && (unsigned) c < m_Width &&
  3384. (r != row || c != col) && fcol(r,c) == fcol(row,col)) {
  3385. tot += BAYER2(r,c);
  3386. n++;
  3387. }
  3388. BAYER2(row,col) = tot/n;
  3389. TRACEKEYVALS("Fixed dead pixel at column","%d",col);
  3390. TRACEKEYVALS("Fixed dead pixel at row","%d",row);
  3391. }
  3392. FCLOSE (fp);
  3393. }
  3394. void CLASS subtract (const char *fname)
  3395. {
  3396. FILE *fp;
  3397. int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
  3398. uint16_t *pixel;
  3399. if (!(fp = fopen (fname, "rb"))) {
  3400. perror (fname); return;
  3401. }
  3402. if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
  3403. while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
  3404. if (c == '#') comment = 1;
  3405. if (c == '\n') comment = 0;
  3406. if (comment) continue;
  3407. if (isdigit(c)) number = 1;
  3408. if (number) {
  3409. if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
  3410. else if (isspace(c)) {
  3411. number = 0; nd++;
  3412. } else error = 1;
  3413. }
  3414. }
  3415. if (error || nd < 3) {
  3416. fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
  3417. FCLOSE (fp); return;
  3418. } else if (dim[0] != m_Width || dim[1] != m_Height || dim[2] != 65535) {
  3419. fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
  3420. FCLOSE (fp); return;
  3421. }
  3422. pixel = (uint16_t*) CALLOC (m_Width, sizeof *pixel);
  3423. merror (pixel, "subtract()");
  3424. for (row=0; row < m_Height; row++) {
  3425. ptfread (pixel, 2, m_Width, fp);
  3426. for (col=0; col < m_Width; col++)
  3427. BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
  3428. }
  3429. FREE (pixel);
  3430. FCLOSE (fp);
  3431. memset (m_CBlackLevel, 0, sizeof m_CBlackLevel);
  3432. m_BlackLevel = 0;
  3433. }
  3434. void CLASS gamma_curve (double pwr, double ts, int mode, int imax)
  3435. {
  3436. int i;
  3437. double g[6], bnd[2]={0,0}, r;
  3438. g[0] = pwr;
  3439. g[1] = ts;
  3440. g[2] = g[3] = g[4] = 0;
  3441. bnd[g[1] >= 1] = 1;
  3442. if (g[1] && (g[1]-1)*(g[0]-1) <= 0) {
  3443. for (i=0; i < 48; i++) {
  3444. g[2] = (bnd[0] + bnd[1])/2;
  3445. if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2];
  3446. else bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2];
  3447. }
  3448. g[3] = g[2] / g[1];
  3449. if (g[0]) g[4] = g[2] * (1/g[0] - 1);
  3450. }
  3451. if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) +
  3452. (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1;
  3453. else g[5] = 1 / (g[1]*SQR(g[3])/2 + 1
  3454. - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1;
  3455. if (!mode--) {
  3456. memcpy (m_Gamma, g, sizeof m_Gamma);
  3457. return;
  3458. }
  3459. for (i=0; i < 0x10000; i++) {
  3460. m_Curve[i] = 0xffff;
  3461. if ((r = (double) i / imax) < 1)
  3462. m_Curve[i] = 0x10000 * ( mode
  3463. ? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4] : log(r)*g[2]+1))
  3464. : (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2]))));
  3465. }
  3466. }
  3467. void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
  3468. {
  3469. double work[3][6], num;
  3470. int i, j, k;
  3471. for (i=0; i < 3; i++) {
  3472. for (j=0; j < 6; j++)
  3473. work[i][j] = j == i+3;
  3474. for (j=0; j < 3; j++)
  3475. for (k=0; k < size; k++)
  3476. work[i][j] += in[k][i] * in[k][j];
  3477. }
  3478. for (i=0; i < 3; i++) {
  3479. num = work[i][i];
  3480. for (j=0; j < 6; j++)
  3481. work[i][j] /= num;
  3482. for (k=0; k < 3; k++) {
  3483. if (k==i) continue;
  3484. num = work[k][i];
  3485. for (j=0; j < 6; j++)
  3486. work[k][j] -= work[i][j] * num;
  3487. }
  3488. }
  3489. for (i=0; i < size; i++)
  3490. for (j=0; j < 3; j++)
  3491. for (out[i][j]=k=0; k < 3; k++)
  3492. out[i][j] += work[j][k+3] * in[i][k];
  3493. }
  3494. void CLASS cam_xyz_coeff (double MatrixXYZToCamRGB[4][3])
  3495. {
  3496. double MatrixSRGBToCamRGB[4][3], inverse[4][3], num;
  3497. int i, j, k;
  3498. for (i=0; i < m_Colors; i++) /* Multiply out XYZ colorspace */
  3499. for (j=0; j < 3; j++)
  3500. for (MatrixSRGBToCamRGB[i][j] = k=0; k < 3; k++)
  3501. MatrixSRGBToCamRGB[i][j] +=
  3502. MatrixXYZToCamRGB[i][k] * MatrixRGBToXYZ[ptSpace_sRGB_D65][k][j];
  3503. // Normalize MatrixSRGBToCamRGB such that
  3504. // (1,1,1) in SRGB maps onto (1,1,1,1) in CamRGB.
  3505. for (i=0; i < m_Colors; i++) {
  3506. for (num=j=0; j < 3; j++)
  3507. num += MatrixSRGBToCamRGB[i][j];
  3508. for (j=0; j < 3; j++)
  3509. MatrixSRGBToCamRGB[i][j] /= num;
  3510. // TODO More profound explanation.
  3511. // But somehow it is clear that the factors to bring
  3512. // (1,1,1)=>(1,1,1,1) are the multipliers at the reference point D65.
  3513. ASSIGN(m_D65Multipliers[i], 1 / num);
  3514. }
  3515. pseudoinverse (MatrixSRGBToCamRGB, inverse, m_Colors);
  3516. m_RawColorPhotivo = m_RawColor;
  3517. for (m_RawColor = i=0; i < 3; i++)
  3518. for (j=0; j < m_Colors; j++)
  3519. m_MatrixCamRGBToSRGB[i][j] = inverse[j][i];
  3520. }
  3521. void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
  3522. {
  3523. int i;
  3524. for (i=0; i < sc; i++)
  3525. temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
  3526. for (; i+sc < size; i++)
  3527. temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
  3528. for (; i < size; i++)
  3529. temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
  3530. }
  3531. ////////////////////////////////////////////////////////////////////////////////
  3532. //
  3533. // ptAdjustMaximum
  3534. // This is modelled after the adjust_maximum of libraw.
  3535. // It's purpose is false color suppression in the highlights.
  3536. // Typically "Threshold" should be between 0.75 and 1.
  3537. //
  3538. ////////////////////////////////////////////////////////////////////////////////
  3539. void CLASS ptAdjustMaximum(double Threshold) {
  3540. m_WhiteLevel = LIM((int32_t)(Threshold*(double)m_WhiteLevel),0, 4095);
  3541. }
  3542. ////////////////////////////////////////////////////////////////////////////////
  3543. //
  3544. // ptScaleColors
  3545. // Be aware : ptWaveletDenoising has as side effect that
  3546. // m_Blacklevel and m_Whitelevel change.
  3547. //
  3548. ////////////////////////////////////////////////////////////////////////////////
  3549. void CLASS ptScaleColors() {
  3550. unsigned bottom, right, row, col, x, y, c, sum[8];
  3551. int val;
  3552. double dsum[8], dmin, dmax;
  3553. // Use the UserSetting_Multipliers if they are defined.
  3554. // Remark that they will be overwritten if we have a AutoWb on CameraWb on !
  3555. if (m_UserSetting_Multiplier[0]) {
  3556. TRACEKEYVALS("Setting PreMultipliers due to UserSetting","%s","");
  3557. ASSIGN(m_PreMultipliers[0],m_UserSetting_Multiplier[0]);
  3558. ASSIGN(m_PreMultipliers[1],m_UserSetting_Multiplier[1]);
  3559. ASSIGN(m_PreMultipliers[2],m_UserSetting_Multiplier[2]);
  3560. ASSIGN(m_PreMultipliers[3],m_UserSetting_Multiplier[3]);
  3561. }
  3562. // AutoWb calculation, also fallback if no CameraWb found and
  3563. // CameraWb is on.
  3564. // Also the GreyBox whitesetting is done here, so AutoWb should be on for
  3565. // GreyBox calculation !
  3566. if ( m_UserSetting_AutoWb ||
  3567. (m_UserSetting_CameraWb && VALUE(m_CameraMultipliers[0]) == -1)) {
  3568. memset (dsum, 0, sizeof dsum);
  3569. bottom = MIN (m_UserSetting_GreyBox[1]+m_UserSetting_GreyBox[3], (int32_t)m_Height);
  3570. right = MIN (m_UserSetting_GreyBox[0]+m_UserSetting_GreyBox[2], (int32_t)m_Width);
  3571. TRACEKEYVALS("AutoWB GreyBox[0]","%d",m_UserSetting_GreyBox[0]);
  3572. TRACEKEYVALS("AutoWB GreyBox[1]","%d",m_UserSetting_GreyBox[1]);
  3573. TRACEKEYVALS("AutoWB GreyBox[2]","%d",m_UserSetting_GreyBox[2]);
  3574. TRACEKEYVALS("AutoWB GreyBox[3]","%d",m_UserSetting_GreyBox[3]);
  3575. TRACEKEYVALS("AutoWB m_Width","%d",m_Width);
  3576. TRACEKEYVALS("AutoWB m_Height","%d",m_Height);
  3577. TRACEKEYVALS("AutoWB right","%d",right);
  3578. TRACEKEYVALS("AutoWB bottom","%d",bottom);
  3579. // Auto whitebalance done over the greybox but resulting
  3580. // in the whole image if no greybox given.
  3581. for (row=m_UserSetting_GreyBox[1]; row < bottom; row += 8)
  3582. for (col=m_UserSetting_GreyBox[0]; col < right; col += 8) {
  3583. // Apparently the image is scanned in 8*8 pixel blocks.
  3584. memset (sum, 0, sizeof sum);
  3585. for (y=row; y < row+8 && y < bottom; y++)
  3586. for (x=col; x < col+8 && x < right; x++)
  3587. for (c=0; c < 4; c++) {
  3588. if (m_Filters) {
  3589. c = fcol(y,x);
  3590. val = BAYER2(y,x);
  3591. } else
  3592. val = m_Image[y*m_Width+x][c];
  3593. if ((unsigned) val > m_WhiteLevel-25) goto skip_block;
  3594. if ((val -= m_CBlackLevel[c]) < 0) val = 0;
  3595. sum[c] += val;
  3596. sum[c+4]++;
  3597. if (m_Filters) break;
  3598. }
  3599. for (c=0; c < 8; c++) dsum[c] += sum[c];
  3600. skip_block: ;
  3601. }
  3602. // How intenser the blocks , how smaller the multipliers.
  3603. // In terms of ratio's it means they will be close to each other
  3604. // (neutral color balance) if the image has equally distributed RGB
  3605. // (that's grey :))
  3606. for (c=0; c < 4; c++) if (dsum[c]) ASSIGN(m_PreMultipliers[c], dsum[c+4] / dsum[c]);
  3607. TRACEKEYVALS("Setting PreMultipliers due to AutoWB","%s","");
  3608. }
  3609. if (m_UserSetting_CameraWb && VALUE(m_CameraMultipliers[0]) != -1) {
  3610. memset (sum, 0, sizeof sum);
  3611. for (row=0; row < 8; row++)
  3612. for (col=0; col < 8; col++) {
  3613. c = FC(row,col);
  3614. if ((val = white[row][col] - m_CBlackLevel[c]) > 0)
  3615. sum[c] += val;
  3616. sum[c+4]++;
  3617. }
  3618. if (sum[0] && sum[1] && sum[2] && sum[3]) {
  3619. for (c=0; c < 4; c++) ASSIGN(m_PreMultipliers[c], (float) sum[c+4] / sum[c]);
  3620. TRACEKEYVALS("Setting PreMultipliers due to CameraWB","%s","");
  3621. }
  3622. else if (VALUE(m_CameraMultipliers[0]) && VALUE(m_CameraMultipliers[2])) {
  3623. ASSIGN(m_PreMultipliers[0],VALUE(m_CameraMultipliers[0]));
  3624. ASSIGN(m_PreMultipliers[1],VALUE(m_CameraMultipliers[1]));
  3625. ASSIGN(m_PreMultipliers[2],VALUE(m_CameraMultipliers[2]));
  3626. ASSIGN(m_PreMultipliers[3],VALUE(m_CameraMultipliers[3]));
  3627. TRACEKEYVALS("Setting PreMultipliers due to CameraMultipliers","%s","");
  3628. }
  3629. else
  3630. fprintf (stderr,_("%s: Cannot use camera white balance.\n"), m_UserSetting_InputFileName);
  3631. }
  3632. if (VALUE(m_PreMultipliers[3]) == 0) {
  3633. ASSIGN(m_PreMultipliers[3],
  3634. (m_Colors < 4) ? VALUE(m_PreMultipliers[1]) : 1);
  3635. }
  3636. // Denoising before color scaling and interpolation.
  3637. // Remark m_BlackLevel and m_WhiteLevel migth be changed.
  3638. if (m_UserSetting_DenoiseThreshold) ptWaveletDenoise();
  3639. for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
  3640. if (dmin > VALUE(m_PreMultipliers[c]))
  3641. dmin = VALUE(m_PreMultipliers[c]);
  3642. if (dmax < VALUE(m_PreMultipliers[c]))
  3643. dmax = VALUE(m_PreMultipliers[c]);
  3644. }
  3645. TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
  3646. TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
  3647. TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
  3648. TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
  3649. #ifdef TRACE_ORIGIN
  3650. TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
  3651. TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
  3652. #endif
  3653. for (c=0;c<4;c++) {
  3654. if (m_UserSetting_MaxMultiplier==0)
  3655. ASSIGN(m_PreMultipliers[c],VALUE(m_PreMultipliers[c]) / dmax);
  3656. else
  3657. ASSIGN(m_PreMultipliers[c],VALUE(m_PreMultipliers[c]) / dmin);
  3658. ASSIGN(m_Multipliers[c],
  3659. VALUE(m_PreMultipliers[c])*0xffff/(m_WhiteLevel-m_CBlackLevel[c]));
  3660. }
  3661. if (m_UserSetting_MaxMultiplier==0)
  3662. m_MinPreMulti = dmin/dmax; // And the maximum is per construction 1.0
  3663. else
  3664. m_MinPreMulti = 1.0; // TODO Mike: max is not 1.0 anymore...
  3665. TRACEKEYVALS("dmax","%f",dmax);
  3666. TRACEKEYVALS("dmin","%f",dmin);
  3667. TRACEKEYVALS("m_MinPreMulti","%f",m_MinPreMulti);
  3668. TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
  3669. TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
  3670. TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
  3671. TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
  3672. #ifdef TRACE_ORIGIN
  3673. TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
  3674. TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
  3675. #endif
  3676. TRACEKEYVALS("Mult[0]","%f",VALUE(m_Multipliers[0]));
  3677. TRACEKEYVALS("Mult[1]","%f",VALUE(m_Multipliers[1]));
  3678. TRACEKEYVALS("Mult[2]","%f",VALUE(m_Multipliers[2]));
  3679. TRACEKEYVALS("Mult[3]","%f",VALUE(m_Multipliers[3]));
  3680. #ifdef TRACE_ORIGIN
  3681. TRACEKEYVALS("Mult File","%s",m_Multipliers[0].File);
  3682. TRACEKEYVALS("Mult Line","%d",m_Multipliers[0].Line);
  3683. #endif
  3684. TRACEKEYVALS("Scaling colors","%s","");
  3685. uint16_t LUT[0x10000][4];
  3686. #pragma omp parallel for schedule(static)
  3687. for (uint32_t i = 0; i < 0xffff; i++) {
  3688. for (short c = 0; c < 4; c++) {
  3689. LUT[i][c] = i>m_CBlackLevel[c]?
  3690. MIN((int32_t)((i - m_CBlackLevel[c])*VALUE(m_Multipliers[c])),0xffff):0;
  3691. }
  3692. }
  3693. uint32_t Size = m_OutHeight*m_OutWidth;
  3694. #pragma omp parallel for schedule(static)
  3695. for (uint32_t i = 0; i < Size; i++) {
  3696. for (short Color = 0; Color < 4; Color++) {
  3697. m_Image[i][Color] = LUT[m_Image[i][Color]][Color];
  3698. }
  3699. }
  3700. }
  3701. ////////////////////////////////////////////////////////////////////////////////
  3702. //
  3703. // ptHighlight
  3704. // Clipping is determined by Clip... FIXME
  3705. //
  3706. ////////////////////////////////////////////////////////////////////////////////
  3707. void CLASS ptHighlight(const short ClipMode,
  3708. const short ClipParameter) {
  3709. TRACEKEYVALS("ClipMode","%d",ClipMode);
  3710. TRACEKEYVALS("ClipParameter","%d",ClipParameter);
  3711. TRACEKEYVALS("m_Multi[0]","%f",VALUE(m_Multipliers[0]));
  3712. TRACEKEYVALS("m_Multi[1]","%f",VALUE(m_Multipliers[1]));
  3713. TRACEKEYVALS("m_Multi[2]","%f",VALUE(m_Multipliers[2]));
  3714. TRACEKEYVALS("m_Multi[3]","%f",VALUE(m_Multipliers[3]));
  3715. #ifdef TRACE_ORIGIN
  3716. TRACEKEYVALS("Mult File","%s",m_Multipliers[0].File);
  3717. TRACEKEYVALS("Mult Line","%d",m_Multipliers[0].Line);
  3718. #endif
  3719. TRACEKEYVALS("m_MinPreMulti","%f",m_MinPreMulti);
  3720. short ColorRGB[4]={0,1,2,1};
  3721. #pragma omp parallel for schedule(static) default(shared)
  3722. for (uint16_t Row = 0; Row < m_OutHeight; Row++) {
  3723. for (uint16_t Column = 0; Column < m_OutWidth; Column++) {
  3724. uint32_t Pos = Row*m_OutWidth+Column;
  3725. // Do take into account however that we scaled the image here
  3726. // already !
  3727. // Clip occurs if the sensor reached its max value. Full stop.
  3728. // m_Image[Pos] stands for value after application of the
  3729. // m_Multipliers, which are per construction so that the saturation
  3730. // value of the sensor maps onto 0XFFFF. It is the unclipped pixel.
  3731. short Clipped = 0;
  3732. for (short Color = 0; Color < m_Colors; Color++) {
  3733. if (m_Image[Pos][Color] >=
  3734. (uint16_t)
  3735. ((m_WhiteLevel-m_CBlackLevel[ColorRGB[Color]])*VALUE(m_Multipliers[Color]))) {
  3736. Clipped = 1;
  3737. }
  3738. }
  3739. if (Clipped) {
  3740. // Here it becomes fun. The sensor reached a clipped value.
  3741. // 'ClippedPixel' stands for the pixel which is multiplied
  3742. // by a value that guarantees the saturation value of the
  3743. // least scaled channel maps onto 0XFFFF.
  3744. // That value is obtained by observing that normally the
  3745. // least scaled channel maps on saturation*minimum_multiplier
  3746. // So since maximum_multipliers brings us per definition on 0XFFFF
  3747. // upscaling with maximum_multiplier/minimum_multipier is that
  3748. // value. Via the equivalence with the pre_multipliers where the
  3749. // maximum is per construction 1 , it means that we have to upscale
  3750. // with 1/m_MinPreMulti.
  3751. // That way all saturated pixels are definitely mapped onto 0xFFFF
  3752. uint16_t ClippedPixel[4];
  3753. for (short Color = 0; Color < m_Colors; Color++) {
  3754. // This ensures that the channel with the smallest multiplier
  3755. // is clipped at its saturation level.
  3756. ClippedPixel[Color] =
  3757. MIN(0xFFFF,
  3758. (int32_t)(m_Image[Pos][Color]/m_MinPreMulti));
  3759. // And now we correct it back for the increased exposure.
  3760. // (but clipped stays clipped !)
  3761. ClippedPixel[Color] = (uint16_t)(ClippedPixel[Color]* m_MinPreMulti);
  3762. }
  3763. // From here on there are now different strategies with respect
  3764. // to clipping.
  3765. // Try to remove purple highlights
  3766. if (0)
  3767. if (m_Image[Pos][2]>m_Image[Pos][1] && m_Image[Pos][0]==0xffff) m_Image[Pos][2]=m_Image[Pos][1];
  3768. // Simply use the clipped value.
  3769. if (ptClipMode_Clip == ClipMode) {
  3770. for (short Color = 0; Color < m_Colors; Color++) {
  3771. m_Image[Pos][Color] = ClippedPixel[Color];
  3772. }
  3773. // Or use a value starting from Unclipped->Clipped ,
  3774. // defined by the ClipParameter.
  3775. } else if (ptClipMode_NoClip == ClipMode) {
  3776. for (short Color = 0; Color < m_Colors; Color++) {
  3777. m_Image[Pos][Color] =
  3778. m_Image[Pos][Color] +
  3779. (uint16_t) (ClipParameter/100.0*
  3780. (ClippedPixel[Color]-m_Image[Pos][Color]));
  3781. }
  3782. // Or restore via Lab, which is basically the same as
  3783. // used in ufraw (and a simplification of Cyril Guyots LCH blending.
  3784. } else if (ptClipMode_Lab == ClipMode) {
  3785. double ClippedLab[3];
  3786. double UnclippedLab[3];
  3787. double FinalLab[3];
  3788. CamToLab(ClippedPixel,ClippedLab);
  3789. CamToLab(m_Image[Pos],UnclippedLab);
  3790. // FIXME / TODO : Clarify and explain.
  3791. // This is a bit bizar in fact (but also in ufraw ...)
  3792. // The result seems to be better when taking the clipped
  3793. // alternatives for ab and unclipped for L.
  3794. // Wouldn't we expect it the other way around ?
  3795. FinalLab[0] = UnclippedLab[0] +
  3796. ClipParameter/100.0*
  3797. (ClippedLab[0]-UnclippedLab[0]);
  3798. FinalLab[1] = ClippedLab[1];
  3799. FinalLab[2] = ClippedLab[2];
  3800. LabToCam(FinalLab,m_Image[Pos]);
  3801. // Or restore via HSV, as in ufraw.
  3802. } else if (ptClipMode_HSV == ClipMode) {
  3803. // FIXME / TODO : can this not break in some 4 colour modes ?
  3804. short MaxChannel,MidChannel,MinChannel;
  3805. if (m_Image[Pos][0] > m_Image[Pos][1] &&
  3806. m_Image[Pos][0] > m_Image[Pos][2]) {
  3807. MaxChannel = 0;
  3808. if (m_Image[Pos][1] > m_Image[Pos][2]) {
  3809. MidChannel = 1;
  3810. MinChannel = 2;
  3811. } else {
  3812. MidChannel = 2;
  3813. MinChannel = 1;
  3814. }
  3815. } else if (m_Image[Pos][1] > m_Image[Pos][2]) {
  3816. MaxChannel = 1;
  3817. if (m_Image[Pos][0] > m_Image[Pos][2]) {
  3818. MidChannel = 0;
  3819. MinChannel = 2;
  3820. } else {
  3821. MidChannel = 2;
  3822. MinChannel = 0;
  3823. }
  3824. } else {
  3825. MaxChannel = 2;
  3826. if (m_Image[Pos][0] > m_Image[Pos][1]) {
  3827. MidChannel = 0;
  3828. MinChannel = 1;
  3829. } else {
  3830. MidChannel = 1;
  3831. MinChannel = 0;
  3832. }
  3833. }
  3834. uint16_t UnclippedLuminance = m_Image[Pos][MaxChannel];
  3835. uint16_t ClippedLuminance = ClippedPixel[MaxChannel];
  3836. double ClippedSaturation;
  3837. if ( ClippedPixel[MaxChannel]<ClippedPixel[MinChannel] ||
  3838. ClippedPixel[MaxChannel]==0) {
  3839. ClippedSaturation = 0;
  3840. } else {
  3841. ClippedSaturation =
  3842. 1.0 - (double)ClippedPixel[MinChannel] / ClippedPixel[MaxChannel];
  3843. }
  3844. //warning: variable 'ClippedHue' set but not used [-Wunused-but-set-variable]
  3845. // double ClippedHue;
  3846. // if ( ClippedPixel[MaxChannel]==ClippedPixel[MinChannel] ) {
  3847. // ClippedHue = 0;
  3848. // } else {
  3849. // ClippedHue =
  3850. // ((double)ClippedPixel[MidChannel]-ClippedPixel[MinChannel]) /
  3851. // ((double)ClippedPixel[MaxChannel]-ClippedPixel[MinChannel]);
  3852. // }
  3853. double UnclippedHue;
  3854. if ( m_Image[Pos][MaxChannel]==m_Image[Pos][MinChannel] ) {
  3855. UnclippedHue = 0;
  3856. } else {
  3857. UnclippedHue =
  3858. ((double)m_Image[Pos][MidChannel]-m_Image[Pos][MinChannel]) /
  3859. ((double)m_Image[Pos][MaxChannel]-m_Image[Pos][MinChannel]);
  3860. }
  3861. uint16_t Luminance =
  3862. UnclippedLuminance +
  3863. (uint16_t)(ClipParameter/100.0 *
  3864. (ClippedLuminance-UnclippedLuminance));
  3865. double Saturation = ClippedSaturation;
  3866. double Hue = UnclippedHue;
  3867. m_Image[Pos][MaxChannel] = Luminance;
  3868. m_Image[Pos][MinChannel] = (uint16_t)(Luminance * (1-Saturation));
  3869. m_Image[Pos][MidChannel] =
  3870. (uint16_t)(Luminance * (1-Saturation + Saturation*Hue));
  3871. } else if (ptClipMode_Blend == ClipMode) {
  3872. // Do nothing at this stage, keep the unclipped image.
  3873. ;
  3874. } else if (ptClipMode_Rebuild == ClipMode) {
  3875. // Do nothing at this stage, keep the unclipped image.
  3876. ;
  3877. } else {
  3878. assert(0); // should not occur.
  3879. }
  3880. }
  3881. }
  3882. }
  3883. if (ptClipMode_Rebuild == ClipMode) {
  3884. ptRebuildHighlights(ClipParameter);
  3885. }
  3886. if (ptClipMode_Blend == ClipMode) {
  3887. ptBlendHighlights();
  3888. }
  3889. }
  3890. void CLASS pre_interpolate()
  3891. {
  3892. int row, col;
  3893. TRACEKEYVALS("pre_interpolate","%s","");
  3894. if (m_Shrink) {
  3895. if (m_UserSetting_HalfSize) {
  3896. // No interpolation will be needed as
  3897. // m_Shrink has caused a 2X2 Bayer area mapped onto one pixel.
  3898. m_Height = m_OutHeight;
  3899. m_Width = m_OutWidth;
  3900. } else {
  3901. // in photivo we assume that m_Shrink is only set due
  3902. // to m_UserSetting_HalfSize.
  3903. assert(0);
  3904. }
  3905. }
  3906. if (m_Filters > 1000 && m_Colors == 3) {
  3907. if (m_MixGreen) { // 4 color demosaicer will follow
  3908. m_Colors++;
  3909. // Change from dcraw 1.445 to 1.447 wanted "m_MixGreen = !m_UserSetting_HalfSize;"
  3910. // but this doesn't work in Photivo, since we don't run the full pipe of dcraw,
  3911. // since most of the time we start with phase2
  3912. } else {
  3913. // RG1BG2 -> RGB
  3914. #pragma omp parallel for schedule(static) default(shared) private(row, col)
  3915. for (row = FC(1,0) >> 1; row < m_Height; row+=2)
  3916. for (col = FC(row,1) & 1; col < m_Width; col+=2)
  3917. m_Image[row*m_Width+col][1] = m_Image[row*m_Width+col][3];
  3918. m_Filters &= ~((m_Filters & 0x55555555) << 1);
  3919. }
  3920. }
  3921. // If m_UserSetting_HalfSize is set no interpolation will
  3922. // be needed. This is registered by m_Filters = 0.
  3923. // (no Bayer array anymore, this means)
  3924. if (m_UserSetting_HalfSize && m_Filters != 2) {
  3925. m_Filters = 0;
  3926. }
  3927. }
  3928. void CLASS border_interpolate (int border)
  3929. {
  3930. unsigned row, col, y, x, f, c, sum[8];
  3931. for (row=0; row < m_Height; row++)
  3932. for (col=0; col < m_Width; col++) {
  3933. if (col==(unsigned) border && row >= (unsigned) border && row < (unsigned) (m_Height-border))
  3934. col = m_Width-border;
  3935. memset (sum, 0, sizeof sum);
  3936. for (y=row-1; y != row+2; y++)
  3937. for (x=col-1; x != col+2; x++)
  3938. if (y < m_Height && x < m_Width) {
  3939. f = fcol(y,x);
  3940. sum[f] += m_Image[y*m_Width+x][f];
  3941. sum[f+4]++;
  3942. }
  3943. f = fcol(row,col);
  3944. for (c=0; c < (unsigned) m_Colors; c++) if (c != f && sum[c+4])
  3945. m_Image[row*m_Width+col][c] = sum[c] / sum[c+4];
  3946. }
  3947. }
  3948. void CLASS lin_interpolate()
  3949. {
  3950. int code[16][16][32], size=16, *ip, sum[4];
  3951. int f, c, i, x, y, row, col, shift, color;
  3952. uint16_t *pix;
  3953. TRACEKEYVALS("Bilinear interpolation","%s","");
  3954. if (m_Filters == 2) size = 6;
  3955. border_interpolate(1);
  3956. for (row=0; row < size; row++)
  3957. for (col=0; col < size; col++) {
  3958. ip = code[row][col]+1;
  3959. f = fcol(row,col);
  3960. memset (sum, 0, sizeof sum);
  3961. for (y=-1; y <= 1; y++)
  3962. for (x=-1; x <= 1; x++) {
  3963. shift = (y==0) + (x==0);
  3964. color = fcol(row+y,col+x);
  3965. if (color == f) continue;
  3966. *ip++ = (m_Width*y + x)*4 + color;
  3967. *ip++ = shift;
  3968. *ip++ = color;
  3969. sum[color] += 1 << shift;
  3970. }
  3971. code[row][col][0] = (ip - code[row][col]) / 3;
  3972. for (c=0; c < m_Colors; c++)
  3973. if (c != f) {
  3974. *ip++ = c;
  3975. *ip++ = 256 / sum[c];
  3976. }
  3977. }
  3978. #pragma omp parallel for schedule(static) default(shared) private(row,col,pix,ip,sum,i)
  3979. for (row=1; row < m_Height-1; row++)
  3980. for (col=1; col < m_Width-1; col++) {
  3981. pix = m_Image[row*m_Width+col];
  3982. ip = code[row % size][col % size];
  3983. memset (sum, 0, sizeof sum);
  3984. for (i=*ip++; i--; ip+=3)
  3985. sum[ip[2]] += pix[ip[0]] << ip[1];
  3986. for (i=m_Colors; --i; ip+=2)
  3987. pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
  3988. }
  3989. }
  3990. /*
  3991. This algorithm is officially called:
  3992. "Interpolation using a Threshold-based variable number of gradients"
  3993. described in http://scien.stanford.edu/pages/labsite/1999/psych221/projects/99/tingchen/algodep/vargra.html
  3994. I've extended the basic idea to work with non-Bayer filter arrays.
  3995. Gradients are numbered clockwise from NW=0 to W=7.
  3996. */
  3997. void CLASS vng_interpolate()
  3998. {
  3999. static const int16_t *cp, terms[] = {
  4000. -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
  4001. -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
  4002. -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
  4003. -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
  4004. -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
  4005. -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
  4006. -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
  4007. -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
  4008. -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
  4009. -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
  4010. -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
  4011. -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
  4012. -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
  4013. +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
  4014. +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
  4015. +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
  4016. +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
  4017. +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
  4018. +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
  4019. +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
  4020. +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
  4021. +1,+0,+2,+1,0,0x10
  4022. }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
  4023. uint16_t (*brow[5])[4], *pix;
  4024. int prow=8, pcol=2, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
  4025. int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
  4026. int g, diff, thold, num, c;
  4027. lin_interpolate();
  4028. TRACEKEYVALS("VNG interpolation","%s","");
  4029. if (m_Filters == 1) prow = pcol = 16;
  4030. if (m_Filters == 2) prow = pcol = 6;
  4031. ip = (int *) CALLOC (prow*pcol, 1280);
  4032. merror (ip, "vng_interpolate()");
  4033. for (row=0; row < prow; row++) /* Precalculate for VNG */
  4034. for (col=0; col < pcol; col++) {
  4035. code[row][col] = ip;
  4036. for (cp=terms, t=0; t < 64; t++) {
  4037. y1 = *cp++; x1 = *cp++;
  4038. y2 = *cp++; x2 = *cp++;
  4039. weight = *cp++;
  4040. grads = *cp++;
  4041. color = fcol(row+y1,col+x1);
  4042. if (fcol(row+y2,col+x2) != color) continue;
  4043. diag = (fcol(row,col+1) == color && fcol(row+1,col) == color) ? 2:1;
  4044. if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
  4045. *ip++ = (y1*m_Width + x1)*4 + color;
  4046. *ip++ = (y2*m_Width + x2)*4 + color;
  4047. *ip++ = weight;
  4048. for (g=0; g < 8; g++)
  4049. if (grads & 1<<g) *ip++ = g;
  4050. *ip++ = -1;
  4051. }
  4052. *ip++ = INT_MAX;
  4053. for (cp=chood, g=0; g < 8; g++) {
  4054. y = *cp++; x = *cp++;
  4055. *ip++ = (y*m_Width + x) * 4;
  4056. color = fcol(row,col);
  4057. if (fcol(row+y,col+x) != color && fcol(row+y*2,col+x*2) == color)
  4058. *ip++ = (y*m_Width + x) * 8 + color;
  4059. else
  4060. *ip++ = 0;
  4061. }
  4062. }
  4063. brow[4] = (uint16_t (*)[4]) CALLOC (m_Width*3, sizeof **brow);
  4064. merror (brow[4], "vng_interpolate()");
  4065. for (row=0; row < 3; row++)
  4066. brow[row] = brow[4] + row*m_Width;
  4067. for (row=2; row < m_Height-2; row++) { /* Do VNG interpolation */
  4068. for (col=2; col < m_Width-2; col++) {
  4069. pix = m_Image[row*m_Width+col];
  4070. ip = code[row % prow][col % pcol];
  4071. memset (gval, 0, sizeof gval);
  4072. while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
  4073. diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
  4074. gval[ip[3]] += diff;
  4075. ip += 5;
  4076. if ((g = ip[-1]) == -1) continue;
  4077. gval[g] += diff;
  4078. while ((g = *ip++) != -1)
  4079. gval[g] += diff;
  4080. }
  4081. ip++;
  4082. gmin = gmax = gval[0]; /* Choose a threshold */
  4083. for (g=1; g < 8; g++) {
  4084. if (gmin > gval[g]) gmin = gval[g];
  4085. if (gmax < gval[g]) gmax = gval[g];
  4086. }
  4087. if (gmax == 0) {
  4088. memcpy (brow[2][col], pix, sizeof *m_Image);
  4089. continue;
  4090. }
  4091. thold = gmin + (gmax >> 1);
  4092. memset (sum, 0, sizeof sum);
  4093. color = fcol(row,col);
  4094. for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */
  4095. if (gval[g] <= thold) {
  4096. for (c=0; c < m_Colors; c++)
  4097. if (c == color && ip[1])
  4098. sum[c] += (pix[c] + pix[ip[1]]) >> 1;
  4099. else
  4100. sum[c] += pix[ip[0] + c];
  4101. num++;
  4102. }
  4103. }
  4104. for (c=0; c < m_Colors; c++) { /* Save to buffer */
  4105. t = pix[color];
  4106. if (c != color)
  4107. t += (sum[c] - sum[color]) / num;
  4108. brow[2][col][c] = CLIP(t);
  4109. }
  4110. }
  4111. if (row > 3) /* Write buffer to image */
  4112. memcpy (m_Image[(row-2)*m_Width+2], brow[0]+2, (m_Width-4)*sizeof *m_Image);
  4113. for (g=0; g < 4; g++)
  4114. brow[(g-1) & 3] = brow[g];
  4115. }
  4116. memcpy (m_Image[(row-2)*m_Width+2], brow[0]+2, (m_Width-4)*sizeof *m_Image);
  4117. memcpy (m_Image[(row-1)*m_Width+2], brow[1]+2, (m_Width-4)*sizeof *m_Image);
  4118. FREE (brow[4]);
  4119. FREE (code[0][0]);
  4120. }
  4121. /*
  4122. Patterned Pixel Grouping Interpolation by Alain Desbiolles
  4123. */
  4124. void CLASS ppg_interpolate()
  4125. {
  4126. const int dir[5] = { 1, m_Width, -1, -m_Width, 1 };
  4127. int row, col, diff[2], guess[2], c, d, i;
  4128. uint16_t (*pix)[4];
  4129. border_interpolate(3);
  4130. TRACEKEYVALS("PPG interpolation","%s","");
  4131. #pragma omp parallel private(row,c,col,i,guess,diff,d,pix)
  4132. /* Fill in the green layer with gradients and pattern recognition: */
  4133. #pragma omp for
  4134. for (row=3; row < m_Height-3; row++)
  4135. for (col=3+(FC(row,3) & 1), c=FC(row,col); col < m_Width-3; col+=2) {
  4136. pix = m_Image + row*m_Width+col;
  4137. for (i=0; i<2; i++) {
  4138. d = dir[i];
  4139. guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
  4140. - pix[-2*d][c] - pix[2*d][c];
  4141. diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
  4142. ABS(pix[ 2*d][c] - pix[ 0][c]) +
  4143. ABS(pix[ -d][1] - pix[ d][1]) ) * 3 +
  4144. ( ABS(pix[ 3*d][1] - pix[ d][1]) +
  4145. ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
  4146. }
  4147. d = dir[i = diff[0] > diff[1]];
  4148. pix[0][1] = ULIM(guess[i] >> 2, (int32_t)pix[d][1], (int32_t)pix[-d][1]);
  4149. }
  4150. /* Calculate red and blue for each green pixel: */
  4151. #pragma omp for
  4152. for (row=1; row < m_Height-1; row++)
  4153. for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < m_Width-1; col+=2) {
  4154. pix = m_Image + row*m_Width+col;
  4155. for (i=0; (d=dir[i]) > 0; c=2-c, i++)
  4156. pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
  4157. - pix[-d][1] - pix[d][1]) >> 1);
  4158. }
  4159. /* Calculate blue for red pixels and vice versa: */
  4160. #pragma omp for
  4161. for (row=1; row < m_Height-1; row++)
  4162. for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < m_Width-1; col+=2) {
  4163. pix = m_Image + row*m_Width+col;
  4164. for (i=0; i < 2; i++) {
  4165. d = dir[i]+dir[i+1];
  4166. diff[i] = ABS(pix[-d][c] - pix[d][c]) +
  4167. ABS(pix[-d][1] - pix[0][1]) +
  4168. ABS(pix[ d][1] - pix[0][1]);
  4169. guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
  4170. - pix[-d][1] - pix[d][1];
  4171. }
  4172. if (diff[0] != diff[1])
  4173. pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
  4174. else
  4175. pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
  4176. }
  4177. }
  4178. /*
  4179. Adaptive Homogeneity-Directed interpolation is based on
  4180. the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
  4181. */
  4182. #define TS 256 /* Tile Size */
  4183. void CLASS ahd_interpolate()
  4184. {
  4185. int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
  4186. uint16_t (*pix)[4], (*rix)[3];
  4187. static const int dir[4] = { -1, 1, -TS, TS };
  4188. unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
  4189. float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
  4190. uint16_t (*rgb)[TS][TS][3];
  4191. short (*lab)[TS][TS][3], (*lix)[3];
  4192. char (*homo)[TS][TS], *buffer;
  4193. TRACEKEYVALS("AHD interpolation","%s","");
  4194. for (i=0; i < 0x10000; i++) {
  4195. r = i / 65535.0;
  4196. cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
  4197. }
  4198. for (i=0; i < 3; i++)
  4199. for (j=0; j < m_Colors; j++)
  4200. for (xyz_cam[i][j] = k=0; k < 3; k++)
  4201. xyz_cam[i][j] += MatrixRGBToXYZ[ptSpace_sRGB_D65][i][k] * m_MatrixCamRGBToSRGB[k][j] / D65Reference[i];
  4202. border_interpolate(5);
  4203. #pragma omp parallel private(buffer,rgb,lab,homo,top,left,row,c,col,pix,val,d,rix,xyz,lix,tc,tr,ldiff,abdiff,leps,abeps,hm,i,j) firstprivate(cbrt) shared(xyz_cam)
  4204. {
  4205. buffer = (char *) MALLOC (26*TS*TS); /* 1664 kB */
  4206. merror (buffer, "ahd_interpolate()");
  4207. rgb = (uint16_t(*)[TS][TS][3]) buffer;
  4208. lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
  4209. homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
  4210. #pragma omp for schedule(static)
  4211. for (top=2; top < m_Height-5; top += TS-6)
  4212. for (left=2; left < m_Width-5; left += TS-6) {
  4213. /* Interpolate green horizontally and vertically: */
  4214. for (row = top; row < top+TS && row < m_Height-2; row++) {
  4215. col = left + (FC(row,left) & 1);
  4216. for (c = FC(row,col); col < left+TS && col < m_Width-2; col+=2) {
  4217. pix = m_Image + row*m_Width+col;
  4218. val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
  4219. - pix[-2][c] - pix[2][c]) >> 2;
  4220. rgb[0][row-top][col-left][1] = ULIM(val,(int32_t)pix[-1][1],(int32_t)pix[1][1]);
  4221. val = ((pix[-m_Width][1] + pix[0][c] + pix[m_Width][1]) * 2
  4222. - pix[-2*m_Width][c] - pix[2*m_Width][c]) >> 2;
  4223. rgb[1][row-top][col-left][1] = ULIM(val,(int32_t)pix[-m_Width][1],(int32_t)pix[m_Width][1]);
  4224. }
  4225. }
  4226. /* Interpolate red and blue, and convert to CIELab: */
  4227. for (d=0; d < 2; d++)
  4228. for (row=top+1; row < top+TS-1 && row < m_Height-3; row++)
  4229. for (col=left+1; col < left+TS-1 && col < m_Width-3; col++) {
  4230. pix = m_Image + row*m_Width+col;
  4231. rix = &rgb[d][row-top][col-left];
  4232. lix = &lab[d][row-top][col-left];
  4233. if ((c = 2 - FC(row,col)) == 1) {
  4234. c = FC(row+1,col);
  4235. val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
  4236. - rix[-1][1] - rix[1][1] ) >> 1);
  4237. rix[0][2-c] = CLIP(val);
  4238. val = pix[0][1] + (( pix[-m_Width][c] + pix[m_Width][c]
  4239. - rix[-TS][1] - rix[TS][1] ) >> 1);
  4240. } else
  4241. val = rix[0][1] + (( pix[-m_Width-1][c] + pix[-m_Width+1][c]
  4242. + pix[+m_Width-1][c] + pix[+m_Width+1][c]
  4243. - rix[-TS-1][1] - rix[-TS+1][1]
  4244. - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
  4245. rix[0][c] = CLIP(val);
  4246. c = FC(row,col);
  4247. rix[0][c] = pix[0][c];
  4248. xyz[0] = xyz[1] = xyz[2] = 0.5;
  4249. for (c=0; c < m_Colors; c++) {
  4250. xyz[0] += xyz_cam[0][c] * rix[0][c];
  4251. xyz[1] += xyz_cam[1][c] * rix[0][c];
  4252. xyz[2] += xyz_cam[2][c] * rix[0][c];
  4253. }
  4254. xyz[0] = cbrt[CLIP((int) xyz[0])];
  4255. xyz[1] = cbrt[CLIP((int) xyz[1])];
  4256. xyz[2] = cbrt[CLIP((int) xyz[2])];
  4257. lix[0][0] = (short) (64 * (116 * xyz[1] - 16));
  4258. lix[0][1] = (short) (64 * 500 * (xyz[0] - xyz[1]));
  4259. lix[0][2] = (short) (64 * 200 * (xyz[1] - xyz[2]));
  4260. }
  4261. /* Build homogeneity maps from the CIELab images: */
  4262. memset (homo, 0, 2*TS*TS);
  4263. for (row=top+2; row < top+TS-2 && row < m_Height-4; row++) {
  4264. tr = row-top;
  4265. for (col=left+2; col < left+TS-2 && col < m_Width-4; col++) {
  4266. tc = col-left;
  4267. for (d=0; d < 2; d++) {
  4268. lix = &lab[d][tr][tc];
  4269. for (i=0; i < 4; i++) {
  4270. ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
  4271. abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
  4272. + SQR(lix[0][2]-lix[dir[i]][2]);
  4273. }
  4274. }
  4275. leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
  4276. MAX(ldiff[1][2],ldiff[1][3]));
  4277. abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
  4278. MAX(abdiff[1][2],abdiff[1][3]));
  4279. for (d=0; d < 2; d++)
  4280. for (i=0; i < 4; i++)
  4281. if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
  4282. homo[d][tr][tc]++;
  4283. }
  4284. }
  4285. /* Combine the most homogenous pixels for the final result: */
  4286. for (row=top+3; row < top+TS-3 && row < m_Height-5; row++) {
  4287. tr = row-top;
  4288. for (col=left+3; col < left+TS-3 && col < m_Width-5; col++) {
  4289. tc = col-left;
  4290. for (d=0; d < 2; d++)
  4291. for (hm[d]=0, i=tr-1; i <= tr+1; i++)
  4292. for (j=tc-1; j <= tc+1; j++)
  4293. hm[d] += homo[d][i][j];
  4294. if (hm[0] != hm[1])
  4295. for (c=0; c<3; c++) m_Image[row*m_Width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
  4296. else
  4297. for (c=0; c<3; c++) m_Image[row*m_Width+col][c] =
  4298. (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
  4299. }
  4300. }
  4301. }
  4302. FREE (buffer);
  4303. }
  4304. }
  4305. #undef TS
  4306. void CLASS tiff_get (unsigned base,
  4307. unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
  4308. {
  4309. *tag = get2();
  4310. *type = get2();
  4311. *len = get4();
  4312. *save = ftell(m_InputFile) + 4;
  4313. if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
  4314. fseek (m_InputFile, get4()+base, SEEK_SET);
  4315. }
  4316. void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
  4317. {
  4318. unsigned entries, tag, type, len, save;
  4319. entries = get2();
  4320. while (entries--) {
  4321. tiff_get (base, &tag, &type, &len, &save);
  4322. if (tag == toff) m_ThumbOffset = get4()+base;
  4323. if (tag == tlen) m_ThumbLength = get4();
  4324. fseek (m_InputFile, save, SEEK_SET);
  4325. }
  4326. }
  4327. //int CLASS parse_tiff_ifd (int base);
  4328. void CLASS parse_makernote (int base, int uptag)
  4329. {
  4330. static const uint8_t xlat[2][256] = {
  4331. { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
  4332. 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
  4333. 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
  4334. 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
  4335. 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
  4336. 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
  4337. 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
  4338. 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
  4339. 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
  4340. 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
  4341. 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
  4342. 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
  4343. 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
  4344. 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
  4345. 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
  4346. 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
  4347. { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
  4348. 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
  4349. 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
  4350. 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
  4351. 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
  4352. 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
  4353. 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
  4354. 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
  4355. 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
  4356. 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
  4357. 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
  4358. 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
  4359. 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
  4360. 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
  4361. 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
  4362. 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
  4363. unsigned offset=0, entries, tag, type, len, save, c;
  4364. unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
  4365. uint8_t buf97[324], ci, cj, ck;
  4366. short mm_ByteOrder, sm_ByteOrder=m_ByteOrder;
  4367. char buf[10];
  4368. /*
  4369. The MakerNote might have its own TIFF header (possibly with
  4370. its own byte-order!), or it might just be a table.
  4371. */
  4372. if (!strcmp(m_CameraMake,"Nokia")) return;
  4373. ptfread (buf, 1, 10, m_InputFile);
  4374. if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */
  4375. !strncmp (buf,"VER" ,3) ||
  4376. !strncmp (buf,"IIII",4) ||
  4377. !strncmp (buf,"MMMM",4)) return;
  4378. if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */
  4379. !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */
  4380. m_ByteOrder = 0x4d4d;
  4381. while ((i=ftell(m_InputFile)) < (unsigned) m_Data_Offset && i < (unsigned) 16384) {
  4382. wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3];
  4383. wb[3] = get2();
  4384. if (wb[1] == 256 && wb[3] == 256 &&
  4385. wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
  4386. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c], wb[c]);
  4387. }
  4388. goto quit;
  4389. }
  4390. if (!strcmp (buf,"Nikon")) {
  4391. base = ftell(m_InputFile);
  4392. m_ByteOrder = get2();
  4393. if (get2() != 42) goto quit;
  4394. offset = get4();
  4395. fseek (m_InputFile, offset-8, SEEK_CUR);
  4396. } else if (!strcmp (buf,"OLYMPUS")) {
  4397. base = ftell(m_InputFile)-10;
  4398. fseek (m_InputFile, -2, SEEK_CUR);
  4399. m_ByteOrder = get2(); get2();
  4400. } else if (!strncmp (buf,"SONY",4) ||
  4401. !strcmp (buf,"Panasonic")) {
  4402. goto nf;
  4403. } else if (!strncmp (buf,"FUJIFILM",8)) {
  4404. base = ftell(m_InputFile)-10;
  4405. nf: m_ByteOrder = 0x4949;
  4406. fseek (m_InputFile, 2, SEEK_CUR);
  4407. } else if (!strcmp (buf,"OLYMP") ||
  4408. !strcmp (buf,"LEICA") ||
  4409. !strcmp (buf,"Ricoh") ||
  4410. !strcmp (buf,"EPSON"))
  4411. fseek (m_InputFile, -2, SEEK_CUR);
  4412. else if (!strcmp (buf,"AOC") ||
  4413. !strcmp (buf,"QVC"))
  4414. fseek (m_InputFile, -4, SEEK_CUR);
  4415. else {
  4416. fseek (m_InputFile, -10, SEEK_CUR);
  4417. if (!strncmp(m_CameraMake,"SAMSUNG",7))
  4418. base = ftell(m_InputFile);
  4419. }
  4420. entries = get2();
  4421. if (entries > 1000) return;
  4422. mm_ByteOrder = m_ByteOrder;
  4423. while (entries--) {
  4424. m_ByteOrder = mm_ByteOrder;
  4425. tiff_get (base, &tag, &type, &len, &save);
  4426. tag |= uptag << 16;
  4427. if (tag == 2 && strstr(m_CameraMake,"NIKON") && !m_IsoSpeed)
  4428. m_IsoSpeed = (get2(),get2());
  4429. if (tag == 4 && len > 26 && len < 35) {
  4430. if ((i=(get4(),get2())) != 0x7fff && !m_IsoSpeed)
  4431. m_IsoSpeed = 50 * pow (2, i/32.0 - 4);
  4432. if ((i=(get2(),get2())) != 0x7fff && !m_Aperture)
  4433. m_Aperture = pow (2, i/64.0);
  4434. if ((i=get2()) != 0xffff && !m_Shutter)
  4435. m_Shutter = pow (2, (short) i/-32.0);
  4436. wbi = (get2(),get2());
  4437. m_ShotOrder = (get2(),get2());
  4438. }
  4439. if ((tag == 4 || tag == 0x114) && !strncmp(m_CameraMake,"KONICA",6)) {
  4440. fseek (m_InputFile, tag == 4 ? 140:160, SEEK_CUR);
  4441. switch (get2()) {
  4442. case 72: m_Flip = 0; break;
  4443. case 76: m_Flip = 6; break;
  4444. case 82: m_Flip = 5; break;
  4445. }
  4446. }
  4447. if (tag == 7 && type == 2 && len > 20)
  4448. ptfgets (m_CameraModelBis, 64, m_InputFile);
  4449. if (tag == 8 && type == 4)
  4450. m_ShotOrder = get4();
  4451. if (tag == 9 && !strcmp(m_CameraMake,"Canon"))
  4452. ptfread (m_Artist, 64, 1, m_InputFile);
  4453. if (tag == 0xc && len == 4) {
  4454. ASSIGN(m_CameraMultipliers[0], getreal(type));
  4455. ASSIGN(m_CameraMultipliers[2], getreal(type));
  4456. }
  4457. if (tag == 0xd && type == 7 && get2() == 0xaaaa) {
  4458. for (c=i=2; (uint16_t) c != 0xbbbb && i < len; i++)
  4459. c = c << 8 | fgetc(m_InputFile);
  4460. while ((i+=4) < len-5)
  4461. if (get4() == 257 && (i=len) && (c = (get4(),fgetc(m_InputFile))) < 3)
  4462. m_Flip = "065"[c]-'0';
  4463. }
  4464. if (tag == 0x10 && type == 4)
  4465. unique_id = get4();
  4466. if (tag == 0x11 && m_IsRaw && !strncmp(m_CameraMake,"NIKON",5)) {
  4467. fseek (m_InputFile, get4()+base, SEEK_SET);
  4468. parse_tiff_ifd (base);
  4469. }
  4470. if (tag == 0x14 && type == 7) {
  4471. if (len == 2560) {
  4472. fseek (m_InputFile, 1248, SEEK_CUR);
  4473. goto get2_256;
  4474. }
  4475. ptfread (buf, 1, 10, m_InputFile);
  4476. if (!strncmp(buf,"NRW ",4)) {
  4477. fseek (m_InputFile, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR);
  4478. ASSIGN(m_CameraMultipliers[0], get4() << 2);
  4479. ASSIGN(m_CameraMultipliers[1], get4() + get4());
  4480. ASSIGN(m_CameraMultipliers[2], get4() << 2);
  4481. }
  4482. }
  4483. if (tag == 0x15 && type == 2 && m_IsRaw)
  4484. ptfread (m_CameraModel, 64, 1, m_InputFile);
  4485. if (strstr(m_CameraMake,"PENTAX")) {
  4486. if (tag == 0x1b) tag = 0x1018;
  4487. if (tag == 0x1c) tag = 0x1017;
  4488. }
  4489. if (tag == 0x1d)
  4490. while ((c = fgetc(m_InputFile)) && c != (unsigned) EOF)
  4491. serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
  4492. if (tag == 0x81 && type == 4) {
  4493. m_Data_Offset = get4();
  4494. fseek (m_InputFile, m_Data_Offset + 41, SEEK_SET);
  4495. m_RawHeight = get2() * 2;
  4496. m_RawWidth = get2();
  4497. m_Filters = 0x61616161;
  4498. }
  4499. if (tag == 0x29 && type == 1) {
  4500. c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
  4501. fseek (m_InputFile, 8 + c*32, SEEK_CUR);
  4502. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ 1], get4());
  4503. }
  4504. if ((tag == 0x81 && type == 7) ||
  4505. (tag == 0x100 && type == 7) ||
  4506. (tag == 0x280 && type == 1)) {
  4507. m_ThumbOffset = ftell(m_InputFile);
  4508. m_ThumbLength = len;
  4509. }
  4510. if (tag == 0x88 && type == 4 && (m_ThumbOffset = get4()))
  4511. m_ThumbOffset += base;
  4512. if (tag == 0x89 && type == 4)
  4513. m_ThumbLength = get4();
  4514. if (tag == 0x8c || tag == 0x96)
  4515. meta_offset = ftell(m_InputFile);
  4516. if (tag == 0x97) {
  4517. for (i=0; i < 4; i++)
  4518. ver97 = ver97 * 10 + fgetc(m_InputFile)-'0';
  4519. switch (ver97) {
  4520. case 100:
  4521. fseek (m_InputFile, 68, SEEK_CUR);
  4522. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[(c >> 1) | ((c & 1) << 1)], get2());
  4523. break;
  4524. case 102:
  4525. fseek (m_InputFile, 6, SEEK_CUR);
  4526. goto get2_rggb;
  4527. case 103:
  4528. fseek (m_InputFile, 16, SEEK_CUR);
  4529. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c], get2());
  4530. }
  4531. if (ver97 >= 200) {
  4532. if (ver97 != 205) fseek (m_InputFile, 280, SEEK_CUR);
  4533. ptfread (buf97, 324, 1, m_InputFile);
  4534. }
  4535. }
  4536. if (tag == 0xa1 && type == 7) {
  4537. type = m_ByteOrder;
  4538. m_ByteOrder = 0x4949;
  4539. fseek (m_InputFile, 140, SEEK_CUR);
  4540. for (c=0; c < 3; c++) ASSIGN(m_CameraMultipliers[c], get4());
  4541. m_ByteOrder = type;
  4542. }
  4543. if (tag == 0xa4 && type == 3) {
  4544. fseek (m_InputFile, wbi*48, SEEK_CUR);
  4545. for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], get2());
  4546. }
  4547. if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !VALUE(m_CameraMultipliers[0])) {
  4548. ci = xlat[0][serial & 0xff];
  4549. cj = xlat[1][fgetc(m_InputFile)^fgetc(m_InputFile)^fgetc(m_InputFile)^fgetc(m_InputFile)];
  4550. ck = 0x60;
  4551. for (i=0; i < 324; i++)
  4552. buf97[i] ^= (cj += ci * ck++);
  4553. i = "66666>666;6A;:;55"[ver97-200] - '0';
  4554. for (c=0; c < 4; c++)
  4555. ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ (i &1)],
  4556. sget2 (buf97 + (i & -2) + c*2));
  4557. }
  4558. if (tag == 0x200 && len == 3)
  4559. m_ShotOrder = (get4(),get4());
  4560. if (tag == 0x200 && len == 4)
  4561. for (c=0; c<4; c++) m_CBlackLevel[c ^ c >> 1] = get2();
  4562. if (tag == 0x201 && len == 4)
  4563. goto get2_rggb;
  4564. if (tag == 0x220 && type == 7)
  4565. meta_offset = ftell(m_InputFile);
  4566. if (tag == 0x401 && type == 4 && len == 4) {
  4567. for (c=0; c<4; c++) m_CBlackLevel[c ^ c >> 1] = get4();
  4568. }
  4569. if (tag == 0xe01) { /* Nikon Capture Note */
  4570. type = m_ByteOrder;
  4571. m_ByteOrder = 0x4949;
  4572. fseek (m_InputFile, 22, SEEK_CUR);
  4573. for (offset=22; offset+22 < len; offset += 22+i) {
  4574. tag = get4();
  4575. fseek (m_InputFile, 14, SEEK_CUR);
  4576. i = get4()-4;
  4577. if (tag == 0x76a43207) m_Flip = get2();
  4578. else fseek (m_InputFile, i, SEEK_CUR);
  4579. }
  4580. m_ByteOrder = type;
  4581. }
  4582. if (tag == 0xe80 && len == 256 && type == 7) {
  4583. fseek (m_InputFile, 48, SEEK_CUR);
  4584. ASSIGN(m_CameraMultipliers[0], get2() * 508 * 1.078 / 0x10000);
  4585. ASSIGN(m_CameraMultipliers[2], get2() * 382 * 1.173 / 0x10000);
  4586. }
  4587. if (tag == 0xf00 && type == 7) {
  4588. if (len == 614)
  4589. fseek (m_InputFile, 176, SEEK_CUR);
  4590. else if (len == 734 || len == 1502)
  4591. fseek (m_InputFile, 148, SEEK_CUR);
  4592. else goto next;
  4593. goto get2_256;
  4594. }
  4595. if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
  4596. for (i=0; i < 3; i++)
  4597. for (c=0; c<3; c++) m_cmatrix[i][c] = ((short) get2()) / 256.0;
  4598. if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
  4599. for (c=0; c<4; c++) m_CBlackLevel[c ^ c >> 1] = get2();
  4600. if (tag == 0x1017 || tag == 0x20400100)
  4601. ASSIGN(m_CameraMultipliers[0], get2() / 256.0);
  4602. if (tag == 0x1018 || tag == 0x20400100)
  4603. ASSIGN(m_CameraMultipliers[2], get2() / 256.0);
  4604. if (tag == 0x2011 && len == 2) {
  4605. get2_256:
  4606. m_ByteOrder = 0x4d4d;
  4607. ASSIGN(m_CameraMultipliers[0], get2() / 256.0);
  4608. ASSIGN(m_CameraMultipliers[2], get2() / 256.0);
  4609. }
  4610. if ((tag | 0x70) == 0x2070 && type == 4)
  4611. fseek (m_InputFile, get4()+base, SEEK_SET);
  4612. if (tag == 0x2010 && type != 7)
  4613. m_LoadRawFunction = &CLASS olympus_load_raw;
  4614. if (tag == 0x2020)
  4615. parse_thumb_note (base, 257, 258);
  4616. if (tag == 0x2040)
  4617. parse_makernote (base, 0x2040);
  4618. if (tag == 0xb028) {
  4619. fseek (m_InputFile, get4()+base, SEEK_SET);
  4620. parse_thumb_note (base, 136, 137);
  4621. }
  4622. if (tag == 0x4001 && len > 500) {
  4623. i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
  4624. fseek (m_InputFile, i, SEEK_CUR);
  4625. get2_rggb:
  4626. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get2());
  4627. i = len >> 3 == 164 ? 112:22;
  4628. fseek (m_InputFile, i, SEEK_CUR);
  4629. for (c=0; c < 4; c++) sraw_mul[c ^ (c >> 1)] = get2();
  4630. }
  4631. if (tag == 0xa021)
  4632. for (c=0; c<4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get4());
  4633. if (tag == 0xa028)
  4634. for (c=0; c<4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], m_CameraMultipliers[c ^ (c >> 1)] - get4());
  4635. next:
  4636. fseek (m_InputFile, save, SEEK_SET);
  4637. }
  4638. quit:
  4639. m_ByteOrder = sm_ByteOrder;
  4640. }
  4641. /*
  4642. Since the TIFF DateTime string has no timezone information,
  4643. assume that the camera's clock was set to Universal Time.
  4644. */
  4645. void CLASS get_timestamp (int reversed)
  4646. {
  4647. struct tm t;
  4648. char str[20];
  4649. int i;
  4650. str[19] = 0;
  4651. if (reversed)
  4652. for (i=19; i--; ) str[i] = fgetc(m_InputFile);
  4653. else
  4654. ptfread (str, 19, 1, m_InputFile);
  4655. memset (&t, 0, sizeof t);
  4656. if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
  4657. &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
  4658. return;
  4659. t.tm_year -= 1900;
  4660. t.tm_mon -= 1;
  4661. t.tm_isdst = -1;
  4662. if (mktime(&t) > 0)
  4663. m_TimeStamp = mktime(&t);
  4664. }
  4665. void CLASS parse_exif (int base)
  4666. {
  4667. unsigned kodak, entries, tag, type, len, save, c;
  4668. double expo;
  4669. kodak = !strncmp(m_CameraMake,"EASTMAN",7) && m_Tiff_NrIFDs < 3;
  4670. entries = get2();
  4671. while (entries--) {
  4672. tiff_get (base, &tag, &type, &len, &save);
  4673. switch (tag) {
  4674. case 33434: m_Shutter = getreal(type); break;
  4675. case 33437: m_Aperture = getreal(type); break;
  4676. case 34855: m_IsoSpeed = get2(); break;
  4677. case 36867:
  4678. case 36868: get_timestamp(0); break;
  4679. case 37377: if ((expo = -getreal(type)) < 128)
  4680. m_Shutter = pow (2, expo); break;
  4681. case 37378: m_Aperture = pow (2, getreal(type)/2); break;
  4682. case 37386: m_FocalLength = getreal(type); break;
  4683. case 37500: parse_makernote (base, 0); break;
  4684. case 40962: if (kodak) m_RawWidth = get4(); break;
  4685. case 40963: if (kodak) m_RawHeight = get4(); break;
  4686. case 41730:
  4687. if (get4() == 0x20002)
  4688. for (exif_cfa=c=0; c < 8; c+=2)
  4689. exif_cfa |= fgetc(m_InputFile) * 0x01010101 << c;
  4690. }
  4691. fseek (m_InputFile, save, SEEK_SET);
  4692. }
  4693. }
  4694. void CLASS romm_coeff (float romm_cam[3][3])
  4695. {
  4696. static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
  4697. { { 2.034193, -0.727420, -0.306766 },
  4698. { -0.228811, 1.231729, -0.002922 },
  4699. { -0.008565, -0.153273, 1.161839 } };
  4700. int i, j, k;
  4701. for (i=0; i < 3; i++)
  4702. for (j=0; j < 3; j++)
  4703. for (m_cmatrix[i][j] = k=0; k < 3; k++)
  4704. m_cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
  4705. }
  4706. void CLASS parse_mos (int offset)
  4707. {
  4708. char data[40];
  4709. int skip, from, i, c, neut[4], planes=0, frot=0;
  4710. static const char *mod[] =
  4711. { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
  4712. "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
  4713. "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7",
  4714. "","","","","","","","","","","","","","","","","","AFi-II 12" };
  4715. float romm_cam[3][3];
  4716. fseek (m_InputFile, offset, SEEK_SET);
  4717. while (1) {
  4718. if (get4() != 0x504b5453) break;
  4719. get4();
  4720. ptfread (data, 1, 40, m_InputFile);
  4721. skip = get4();
  4722. from = ftell(m_InputFile);
  4723. if (!strcmp(data,"JPEG_preview_data")) {
  4724. m_ThumbOffset = from;
  4725. m_ThumbLength = skip;
  4726. }
  4727. if (!strcmp(data,"icc_camera_profile")) {
  4728. m_ProfileOffset = from;
  4729. m_ProfileLength = skip;
  4730. }
  4731. if (!strcmp(data,"ShootObj_back_type")) {
  4732. ptfscanf (m_InputFile, "%d", &i);
  4733. if ((unsigned) i < sizeof mod / sizeof (*mod))
  4734. strcpy (m_CameraModel, mod[i]);
  4735. }
  4736. if (!strcmp(data,"icc_camera_to_tone_matrix")) {
  4737. for (i=0; i < 9; i++)
  4738. romm_cam[0][i] = int_to_float(get4());
  4739. romm_coeff (romm_cam);
  4740. }
  4741. if (!strcmp(data,"CaptProf_color_matrix")) {
  4742. for (i=0; i < 9; i++)
  4743. ptfscanf (m_InputFile, "%f", &romm_cam[0][i]);
  4744. romm_coeff (romm_cam);
  4745. }
  4746. if (!strcmp(data,"CaptProf_number_of_planes"))
  4747. ptfscanf (m_InputFile, "%d", &planes);
  4748. if (!strcmp(data,"CaptProf_raw_data_rotation"))
  4749. ptfscanf (m_InputFile, "%d", &m_Flip);
  4750. if (!strcmp(data,"CaptProf_mosaic_pattern"))
  4751. for (c=0; c < 4; c++) {
  4752. ptfscanf (m_InputFile, "%d", &i);
  4753. if (i == 1) frot = c ^ (c >> 1);
  4754. }
  4755. if (!strcmp(data,"ImgProf_rotation_angle")) {
  4756. ptfscanf (m_InputFile, "%d", &i);
  4757. m_Flip = i - m_Flip;
  4758. }
  4759. if (!strcmp(data,"NeutObj_neutrals") && !VALUE(m_CameraMultipliers[0])) {
  4760. for (c=0; c < 4; c++) ptfscanf (m_InputFile, "%d", neut+c);
  4761. for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], (float) neut[0] / neut[c+1]);
  4762. }
  4763. if (!strcmp(data,"Rows_data"))
  4764. m_Load_Flags = get4();
  4765. parse_mos (from);
  4766. fseek (m_InputFile, skip+from, SEEK_SET);
  4767. }
  4768. if (planes)
  4769. m_Filters = (planes == 1) * 0x01010101 *
  4770. (uint8_t) "\x94\x61\x16\x49"[(m_Flip/90 + frot) & 3];
  4771. }
  4772. void CLASS linear_table (unsigned len)
  4773. {
  4774. int i;
  4775. if (len > 0x1000) len = 0x1000;
  4776. read_shorts (m_Curve, len);
  4777. for (i=len; i < 0x1000; i++)
  4778. m_Curve[i] = m_Curve[i-1];
  4779. m_WhiteLevel = m_Curve[0xfff];
  4780. }
  4781. void CLASS parse_kodak_ifd (int base)
  4782. {
  4783. unsigned entries, tag, type, len, save;
  4784. int i, c, wbi=-2, wbtemp=6500;
  4785. float mul[3] = {1,1,1}, num = 0;
  4786. static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 };
  4787. entries = get2();
  4788. if (entries > 1024) return;
  4789. while (entries--) {
  4790. tiff_get (base, &tag, &type, &len, &save);
  4791. if (tag == 1020) wbi = getint(type);
  4792. if (tag == 1021 && len == 72) { /* WB set in software */
  4793. fseek (m_InputFile, 40, SEEK_CUR);
  4794. for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], 2048.0 / get2());
  4795. wbi = -2;
  4796. }
  4797. if (tag == 2118) wbtemp = getint(type);
  4798. if (tag == (unsigned)(2130 + wbi))
  4799. for (c=0; c<3; c++) mul[c] = getreal(type);
  4800. if (tag == (unsigned)(2140 + wbi) && wbi >= 0)
  4801. for (c=0; c<3; c++) {
  4802. for (num=i=0; i < 4; i++)
  4803. num += getreal(type) * pow (wbtemp/100.0, i);
  4804. ASSIGN(m_CameraMultipliers[c], 2048 / (num * mul[c]));
  4805. }
  4806. if (tag == 2317) linear_table (len);
  4807. if (tag == 6020) m_IsoSpeed = getint(type);
  4808. if (tag == 64013) wbi = fgetc(m_InputFile);
  4809. if (wbi < 7 && (int) tag == wbtag[wbi])
  4810. for(c=0;c<3;c++) ASSIGN(m_CameraMultipliers[c],get4());
  4811. if (tag == 64019) m_Width = getint(type);
  4812. if (tag == 64020) m_Height = (getint(type)+1) & -2;
  4813. fseek (m_InputFile, save, SEEK_SET);
  4814. }
  4815. }
  4816. //void CLASS parse_minolta (int base);
  4817. int CLASS parse_tiff_ifd (int l_Base) {
  4818. unsigned l_Entries;
  4819. unsigned l_Tag;
  4820. unsigned l_Type;
  4821. unsigned l_Length;
  4822. unsigned l_plen=16;
  4823. unsigned l_Save;
  4824. int l_ifd;
  4825. int l_use_cm=0;
  4826. int l_cfa;
  4827. int i, j, c;
  4828. int l_ImageLength=0;
  4829. int blrr=1, blrc=1, dblack[] = { 0,0,0,0 };
  4830. char l_Software[64];
  4831. char *l_cbuf;
  4832. char *cp;
  4833. uint8_t l_cfa_pat[16];
  4834. uint8_t l_cfa_pc[] = { 0,1,2,3 };
  4835. uint8_t l_tab[256];
  4836. double l_cc[4][4];
  4837. double l_cm[4][3];
  4838. double l_cam_xyz[4][3];
  4839. double l_num;
  4840. double l_ab[]={ 1,1,1,1 };
  4841. double l_asn[] = { 0,0,0,0 };
  4842. double l_xyz[] = { 1,1,1 };
  4843. unsigned l_sony_curve[] = { 0,0,0,0,0,4095 };
  4844. unsigned* l_buf;
  4845. unsigned l_sony_offset=0;
  4846. unsigned l_sony_length=0;
  4847. unsigned l_sony_key=0;
  4848. FILE* l_sfp;
  4849. struct jhead l_JHead;
  4850. if (m_Tiff_NrIFDs >= sizeof m_Tiff_IFD / sizeof m_Tiff_IFD[0])
  4851. return 1;
  4852. l_ifd = m_Tiff_NrIFDs++;
  4853. for (j=0; j < 4; j++)
  4854. for (i=0; i < 4; i++)
  4855. l_cc[j][i] = (i == j);
  4856. l_Entries = get2();
  4857. if (l_Entries > 512) return 1;
  4858. while (l_Entries--) {
  4859. tiff_get (l_Base, &l_Tag, &l_Type, &l_Length, &l_Save);
  4860. switch (l_Tag) {
  4861. case 5: m_Width = get2(); break;
  4862. case 6: m_Height = get2(); break;
  4863. case 7: m_Width += get2(); break;
  4864. case 9: m_Filters = get2(); break;
  4865. case 14: case 15: case 16:
  4866. m_WhiteLevel = get2();
  4867. break;
  4868. case 17: case 18:
  4869. if (l_Type == 3 && l_Length == 1)
  4870. ASSIGN(m_CameraMultipliers[(l_Tag-17)*2], get2() / 256.0);
  4871. break;
  4872. case 23:
  4873. if (l_Type == 3) m_IsoSpeed = get2();
  4874. break;
  4875. case 36: case 37: case 38:
  4876. ASSIGN(m_CameraMultipliers[l_Tag-0x24], get2());
  4877. break;
  4878. case 39:
  4879. if (l_Length < 50 || VALUE(m_CameraMultipliers[0])) break;
  4880. fseek (m_InputFile, 12, SEEK_CUR);
  4881. for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], get2());
  4882. break;
  4883. case 46:
  4884. if (l_Type != 7 || fgetc(m_InputFile) != 0xff || fgetc(m_InputFile) != 0xd8) break;
  4885. m_ThumbOffset = ftell(m_InputFile) - 2;
  4886. m_ThumbLength = l_Length;
  4887. break;
  4888. case 61440: /* Fuji HS10 table */
  4889. parse_tiff_ifd (l_Base);
  4890. break;
  4891. case 2: case 256: case 61441: /* ImageWidth */
  4892. m_Tiff_IFD[l_ifd].width = getint(l_Type);
  4893. break;
  4894. case 3: case 257: case 61442: /* ImageHeight */
  4895. m_Tiff_IFD[l_ifd].height = getint(l_Type);
  4896. break;
  4897. case 258: /* BitsPerSample */
  4898. case 61443:
  4899. m_Tiff_IFD[l_ifd].samples = l_Length & 7;
  4900. m_Tiff_IFD[l_ifd].bps = getint(l_Type);
  4901. break;
  4902. case 61446:
  4903. m_RawHeight = 0;
  4904. m_LoadRawFunction = &CLASS packed_load_raw;
  4905. m_Load_Flags = get4() && (m_Filters=0x16161616) ? 24:80;
  4906. break;
  4907. case 259: /* Compression */
  4908. m_Tiff_IFD[l_ifd].comp = getint(l_Type);
  4909. break;
  4910. case 262: /* PhotometricInterpretation */
  4911. m_Tiff_IFD[l_ifd].phint = get2();
  4912. break;
  4913. case 270: /* ImageDescription */
  4914. ptfread (m_Description, 512, 1, m_InputFile);
  4915. break;
  4916. case 271: /* Make */
  4917. ptfgets (m_CameraMake, 64, m_InputFile);
  4918. break;
  4919. case 272: /* Model */
  4920. ptfgets (m_CameraModel, 64, m_InputFile);
  4921. break;
  4922. case 280: /* Panasonic RW2 offset */
  4923. if (l_Type != 4) break;
  4924. m_LoadRawFunction = &CLASS panasonic_load_raw;
  4925. m_Load_Flags = 0x2008;
  4926. case 273: /* StripOffset */
  4927. case 513: /* JpegIFOffset */
  4928. case 61447:
  4929. m_Tiff_IFD[l_ifd].offset = get4()+l_Base;
  4930. if (!m_Tiff_IFD[l_ifd].bps && m_Tiff_IFD[l_ifd].offset > 0) {
  4931. fseek (m_InputFile, m_Tiff_IFD[l_ifd].offset, SEEK_SET);
  4932. if (ljpeg_start (&l_JHead, 1)) {
  4933. m_Tiff_IFD[l_ifd].comp = 6;
  4934. m_Tiff_IFD[l_ifd].width = l_JHead.wide;
  4935. m_Tiff_IFD[l_ifd].height = l_JHead.high;
  4936. m_Tiff_IFD[l_ifd].bps = l_JHead.bits;
  4937. m_Tiff_IFD[l_ifd].samples = l_JHead.clrs;
  4938. if (!(l_JHead.sraw || (l_JHead.clrs & 1)))
  4939. m_Tiff_IFD[l_ifd].width *= l_JHead.clrs;
  4940. i = m_ByteOrder;
  4941. parse_tiff (m_Tiff_IFD[l_ifd].offset + 12);
  4942. m_ByteOrder = i;
  4943. }
  4944. }
  4945. break;
  4946. case 274: /* Orientation */
  4947. m_Tiff_IFD[l_ifd].flip = "50132467"[get2() & 7]-'0';
  4948. break;
  4949. case 277: /* SamplesPerPixel */
  4950. m_Tiff_IFD[l_ifd].samples = getint(l_Type) & 7;
  4951. break;
  4952. case 279: /* StripByteCounts */
  4953. case 514:
  4954. case 61448:
  4955. m_Tiff_IFD[l_ifd].bytes = get4();
  4956. break;
  4957. case 61454:
  4958. for (c=0; c < 3; c++) ASSIGN(m_CameraMultipliers[(4-c) % 3],getint(l_Type));
  4959. break;
  4960. case 305: case 11: /* Software */
  4961. ptfgets (l_Software, 64, m_InputFile);
  4962. if (!strncmp(l_Software,"Adobe",5) ||
  4963. !strncmp(l_Software,"dcraw",5) ||
  4964. !strncmp(l_Software,"UFRaw",5) ||
  4965. !strncmp(l_Software,"Bibble",6) ||
  4966. !strncmp(l_Software,"Nikon Scan",10) ||
  4967. !strcmp (l_Software,"Digital Photo Professional"))
  4968. m_IsRaw = 0;
  4969. break;
  4970. case 306: /* DateTime */
  4971. get_timestamp(0);
  4972. break;
  4973. case 315: /* Artist */
  4974. ptfread (m_Artist, 64, 1, m_InputFile);
  4975. break;
  4976. case 322: /* TileWidth */
  4977. m_Tiff_IFD[l_ifd].tile_width = getint(l_Type);
  4978. break;
  4979. case 323: /* TileLength */
  4980. m_Tiff_IFD[l_ifd].tile_length = getint(l_Type);
  4981. break;
  4982. case 324: /* TileOffsets */
  4983. m_Tiff_IFD[l_ifd].offset = l_Length > 1 ? ftell(m_InputFile) : get4();
  4984. if (l_Length == 4) {
  4985. m_LoadRawFunction = &CLASS sinar_4shot_load_raw;
  4986. m_IsRaw = 5;
  4987. }
  4988. break;
  4989. case 330: /* SubIFDs */
  4990. if (!strcmp(m_CameraModel,"DSLR-A100") && m_Tiff_IFD[l_ifd].width == 3872) {
  4991. m_LoadRawFunction = &CLASS sony_arw_load_raw;
  4992. m_Data_Offset = get4()+l_Base;
  4993. l_ifd++; break;
  4994. }
  4995. while (l_Length--) {
  4996. i = ftell(m_InputFile);
  4997. fseek (m_InputFile, get4()+l_Base, SEEK_SET);
  4998. if (parse_tiff_ifd (l_Base)) break;
  4999. fseek (m_InputFile, i+4, SEEK_SET);
  5000. }
  5001. break;
  5002. case 400:
  5003. strcpy (m_CameraMake, "Sarnoff");
  5004. m_WhiteLevel = 0xfff;
  5005. break;
  5006. case 28688:
  5007. for (c=0; c < 4; c++) l_sony_curve[c+1] = get2() >> 2 & 0xfff;
  5008. for (i=0; i < 5; i++)
  5009. for (j = l_sony_curve[i]+1; (unsigned) j <= l_sony_curve[i+1]; j++)
  5010. m_Curve[j] = m_Curve[j-1] + (1 << i);
  5011. break;
  5012. case 29184: l_sony_offset = get4(); break;
  5013. case 29185: l_sony_length = get4(); break;
  5014. case 29217: l_sony_key = get4(); break;
  5015. case 29264:
  5016. parse_minolta (ftell(m_InputFile));
  5017. m_RawWidth = 0;
  5018. break;
  5019. case 29443:
  5020. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c < 2)], get2());
  5021. break;
  5022. case 29459:
  5023. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c], get2());
  5024. i = (m_CameraMultipliers[1] == 1024 && m_CameraMultipliers[2] == 1024) << 1;
  5025. SWAP (m_CameraMultipliers[i],m_CameraMultipliers[i+1])
  5026. break;
  5027. case 33405: /* Model2 */
  5028. ptfgets (m_CameraModelBis, 64, m_InputFile);
  5029. break;
  5030. case 33422: /* CFAPattern */
  5031. case 64777: /* Kodak P-series */
  5032. if ((l_plen=l_Length) > 16) l_plen = 16;
  5033. ptfread (l_cfa_pat, 1, l_plen, m_InputFile);
  5034. for (m_Colors=l_cfa=i=0; (unsigned) i < l_plen; i++) {
  5035. m_Colors += !(l_cfa & (1 << l_cfa_pat[i]));
  5036. l_cfa |= 1 << l_cfa_pat[i];
  5037. }
  5038. if (l_cfa == 070) memcpy (l_cfa_pc,"\003\004\005",3); /* CMY */
  5039. if (l_cfa == 072) memcpy (l_cfa_pc,"\005\003\004\001",4); /* GMCY */
  5040. goto guess_l_cfa_pc;
  5041. case 33424:
  5042. case 65024:
  5043. fseek (m_InputFile, get4()+l_Base, SEEK_SET);
  5044. parse_kodak_ifd (l_Base);
  5045. break;
  5046. case 33434: /* ExposureTime */
  5047. m_Shutter = getreal(l_Type);
  5048. break;
  5049. case 33437: /* FNumber */
  5050. m_Aperture = getreal(l_Type);
  5051. break;
  5052. case 34306: /* Leaf white balance */
  5053. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ 1], 4096.0 / get2());
  5054. break;
  5055. case 34307: /* Leaf CatchLight color matrix */
  5056. ptfread (l_Software, 1, 7, m_InputFile);
  5057. if (strncmp(l_Software,"MATRIX",6)) break;
  5058. m_Colors = 4;
  5059. for (m_RawColor = i=0; i < 3; i++) {
  5060. for (c=0; c < 4; c++) ptfscanf (m_InputFile, "%f", &m_MatrixCamRGBToSRGB[i][c^1]);
  5061. if (!m_UserSetting_CameraWb) continue;
  5062. l_num = 0;
  5063. for (c=0; c < 4; c++) l_num += m_MatrixCamRGBToSRGB[i][c];
  5064. for (c=0; c < 4; c++) m_MatrixCamRGBToSRGB[i][c] /= l_num;
  5065. }
  5066. break;
  5067. case 34310: /* Leaf metadata */
  5068. parse_mos (ftell(m_InputFile));
  5069. case 34303:
  5070. strcpy (m_CameraMake, "Leaf");
  5071. break;
  5072. case 34665: /* EXIF tag */
  5073. fseek (m_InputFile, get4()+l_Base, SEEK_SET);
  5074. parse_exif (l_Base);
  5075. break;
  5076. case 34675: /* InterColorProfile */
  5077. case 50831: /* AsShotICCProfile */
  5078. m_ProfileOffset = ftell(m_InputFile);
  5079. m_ProfileLength = l_Length;
  5080. break;
  5081. case 37122: /* CompressedBitsPerPixel */
  5082. m_Kodak_cbpp = get4();
  5083. break;
  5084. case 37386: /* FocalLength */
  5085. m_FocalLength = getreal(l_Type);
  5086. break;
  5087. case 37393: /* ImageNumber */
  5088. m_ShotOrder = getint(l_Type);
  5089. break;
  5090. case 37400: /* old Kodak KDC tag */
  5091. for (m_RawColor = i=0; i < 3; i++) {
  5092. getreal(l_Type);
  5093. for (c=0; c<3; c++) m_MatrixCamRGBToSRGB[i][c] = getreal(l_Type);
  5094. }
  5095. break;
  5096. case 46275: /* Imacon tags */
  5097. strcpy (m_CameraMake, "Imacon");
  5098. m_Data_Offset = ftell(m_InputFile);
  5099. l_ImageLength = l_Length;
  5100. break;
  5101. case 46279:
  5102. if (l_ImageLength) break;
  5103. fseek (m_InputFile, 38, SEEK_CUR);
  5104. case 46274:
  5105. fseek (m_InputFile, 40, SEEK_CUR);
  5106. m_RawWidth = get4();
  5107. m_RawHeight = get4();
  5108. m_LeftMargin = get4() & 7;
  5109. m_Width = m_RawWidth - m_LeftMargin - (get4() & 7);
  5110. m_TopMargin = get4() & 7;
  5111. m_Height = m_RawHeight - m_TopMargin - (get4() & 7);
  5112. if (m_RawWidth == 7262) {
  5113. m_Height = 5444;
  5114. m_Width = 7244;
  5115. m_LeftMargin = 7;
  5116. }
  5117. fseek (m_InputFile, 52, SEEK_CUR);
  5118. for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], getreal(11));
  5119. fseek (m_InputFile, 114, SEEK_CUR);
  5120. m_Flip = (get2() >> 7) * 90;
  5121. if (m_Width * m_Height * 6 == l_ImageLength) {
  5122. if (m_Flip % 180 == 90) SWAP(m_Width,m_Height);
  5123. m_RawWidth = m_Width;
  5124. m_RawHeight = m_Height;
  5125. m_LeftMargin = m_TopMargin = m_Filters = m_Flip = 0;
  5126. }
  5127. sprintf (m_CameraModel, "Ixpress %d-Mp", m_Height*m_Width/1000000);
  5128. m_LoadRawFunction = &CLASS imacon_full_load_raw;
  5129. if (m_Filters) {
  5130. if (m_LeftMargin & 1) m_Filters = 0x61616161;
  5131. m_LoadRawFunction = &CLASS unpacked_load_raw;
  5132. }
  5133. m_WhiteLevel = 0xffff;
  5134. break;
  5135. case 50454: /* Sinar tag */
  5136. case 50455:
  5137. if (!(l_cbuf = (char *) MALLOC(l_Length))) break;
  5138. ptfread (l_cbuf, 1, l_Length, m_InputFile);
  5139. for (cp = l_cbuf-1; cp && cp < l_cbuf+l_Length; cp = strchr(cp,'\n'))
  5140. if (!strncmp (++cp,"Neutral ",8))
  5141. sscanf (cp+8, "%f %f %f",
  5142. &VALUE(m_CameraMultipliers[0]),
  5143. &VALUE(m_CameraMultipliers[1]),
  5144. &VALUE(m_CameraMultipliers[2]));
  5145. FREE (l_cbuf);
  5146. break;
  5147. case 50458:
  5148. if(!m_CameraMake[0]) strcpy(m_CameraMake,"Hasselblad");
  5149. break;
  5150. case 50459: /* Hasselblad tag */
  5151. i = m_ByteOrder;
  5152. j = ftell(m_InputFile);
  5153. c = m_Tiff_NrIFDs;
  5154. m_ByteOrder = get2();
  5155. fseek (m_InputFile, j+(get2(),get4()), SEEK_SET);
  5156. parse_tiff_ifd (j);
  5157. m_WhiteLevel = 0xffff;
  5158. m_Tiff_NrIFDs = c;
  5159. m_ByteOrder = i;
  5160. break;
  5161. case 50706: /* DNGVersion */
  5162. for (c=0; c < 4; c++) m_DNG_Version = (m_DNG_Version << 8) + fgetc(m_InputFile);
  5163. if (!m_CameraMake[0]) strcpy (m_CameraMake,"DNG");
  5164. m_IsRaw = 1;
  5165. break;
  5166. case 50710: /* CFAPlaneColor */
  5167. if (l_Length > 4) l_Length = 4;
  5168. m_Colors = l_Length;
  5169. ptfread (l_cfa_pc, 1, m_Colors, m_InputFile);
  5170. guess_l_cfa_pc:
  5171. for (c=0; c < m_Colors; c++) l_tab[l_cfa_pc[c]] = c;
  5172. m_ColorDescriptor[c] = 0;
  5173. for (i=16; i--; )
  5174. m_Filters = m_Filters << 2 | l_tab[l_cfa_pat[i % l_plen]];
  5175. break;
  5176. case 50711: /* CFALayout */
  5177. if (get2() == 2) {
  5178. m_Fuji_Width = 1;
  5179. m_Filters = 0x49494949;
  5180. }
  5181. break;
  5182. case 291:
  5183. case 50712: /* LinearizationTable */
  5184. linear_table (l_Length);
  5185. break;
  5186. case 50713: /* BlackLevelRepeatDim */
  5187. blrr = get2();
  5188. blrc = get2();
  5189. break;
  5190. case 61450:
  5191. blrr = blrc = 2;
  5192. case 50714: /* BlackLevel */
  5193. m_BlackLevel = getreal(l_Type);
  5194. if (!m_Filters || !~m_Filters) break;
  5195. dblack[0] = m_BlackLevel;
  5196. dblack[1] = (blrc == 2) ? getreal(l_Type):dblack[0];
  5197. dblack[2] = (blrr == 2) ? getreal(l_Type):dblack[0];
  5198. dblack[3] = (blrc == 2 && blrr == 2) ? getreal(l_Type):dblack[1];
  5199. if (m_Colors == 3)
  5200. m_Filters |= ((m_Filters >> 2 & 0x22222222) |
  5201. (m_Filters << 2 & 0x88888888)) & m_Filters << 1;
  5202. for (c=0; c<4; c++) m_CBlackLevel[m_Filters >> (c << 1) & 3] = dblack[c];
  5203. m_BlackLevel = 0;
  5204. break;
  5205. case 50715: /* BlackLevelDeltaH */
  5206. case 50716: /* BlackLevelDeltaV */
  5207. for (l_num=i=0; (unsigned)i < l_Length; i++)
  5208. l_num += getreal(l_Type);
  5209. m_BlackLevel += l_num/l_Length + 0.5;
  5210. break;
  5211. case 50717: /* WhiteLevel */
  5212. m_WhiteLevel = getint(l_Type);
  5213. break;
  5214. case 50718: /* DefaultScale */
  5215. m_PixelAspect = getreal(l_Type);
  5216. m_PixelAspect /= getreal(l_Type);
  5217. break;
  5218. case 50721: /* ColorMatrix1 */
  5219. case 50722: /* ColorMatrix2 */
  5220. for (c=0; c < m_Colors; c++) for (j=0; j < 3; j++)
  5221. l_cm[c][j] = getreal(l_Type);
  5222. l_use_cm = 1;
  5223. break;
  5224. case 50723: /* CameraCalibration1 */
  5225. case 50724: /* CameraCalibration2 */
  5226. for (i=0; i < m_Colors; i++)
  5227. for (c=0; c < m_Colors; c++) l_cc[i][c] = getreal(l_Type);
  5228. break;
  5229. case 50727: /* AnalogBalance */
  5230. for (c=0; c < m_Colors; c++) l_ab[c] = getreal(l_Type);
  5231. break;
  5232. case 50728: /* AsShotNeutral */
  5233. for (c=0; c < m_Colors; c++) l_asn[c] = getreal(l_Type);
  5234. break;
  5235. case 50729: /* AsShotWhiteXY */
  5236. l_xyz[0] = getreal(l_Type);
  5237. l_xyz[1] = getreal(l_Type);
  5238. l_xyz[2] = 1 - l_xyz[0] - l_xyz[1];
  5239. for (c=0; c<3; c++) l_xyz[c] /= D65Reference[c];
  5240. break;
  5241. case 50740: /* DNGPrivateData */
  5242. if (m_DNG_Version) break;
  5243. parse_minolta (j = get4()+l_Base);
  5244. fseek (m_InputFile, j, SEEK_SET);
  5245. parse_tiff_ifd (l_Base);
  5246. break;
  5247. case 50752:
  5248. read_shorts (cr2_slice, 3);
  5249. break;
  5250. case 50829: /* ActiveArea */
  5251. m_TopMargin = getint(l_Type);
  5252. m_LeftMargin = getint(l_Type);
  5253. m_Height = getint(l_Type) - m_TopMargin;
  5254. m_Width = getint(l_Type) - m_LeftMargin;
  5255. break;
  5256. case 50830: /* MaskedAreas */
  5257. for (i=0; i < (int32_t)l_Length && i < 32; i++)
  5258. m_Mask[0][i] = getint(l_Type);
  5259. m_BlackLevel = 0;
  5260. break;
  5261. case 51009: /* OpcodeList2 */
  5262. meta_offset = ftell(m_InputFile);
  5263. break;
  5264. case 64772: /* Kodak P-series */
  5265. if (l_Length < 13) break;
  5266. fseek (m_InputFile, 16, SEEK_CUR);
  5267. m_Data_Offset = get4();
  5268. fseek (m_InputFile, 28, SEEK_CUR);
  5269. m_Data_Offset += get4();
  5270. m_LoadRawFunction = &CLASS packed_load_raw;
  5271. break;
  5272. case 65026:
  5273. if (l_Type == 2) ptfgets(m_CameraModelBis,64,m_InputFile);
  5274. }
  5275. fseek (m_InputFile, l_Save, SEEK_SET);
  5276. }
  5277. if (l_sony_length && (l_buf = (unsigned *) MALLOC(l_sony_length))) {
  5278. fseek (m_InputFile, l_sony_offset, SEEK_SET);
  5279. ptfread (l_buf, l_sony_length, 1, m_InputFile);
  5280. sony_decrypt (l_buf, l_sony_length/4, 1, l_sony_key);
  5281. l_sfp = m_InputFile;
  5282. if ((m_InputFile = tmpfile())) {
  5283. ptfwrite (l_buf, l_sony_length, 1, m_InputFile);
  5284. fseek (m_InputFile, 0, SEEK_SET);
  5285. parse_tiff_ifd (-l_sony_offset);
  5286. FCLOSE (m_InputFile);
  5287. }
  5288. m_InputFile = l_sfp;
  5289. FREE (l_buf);
  5290. }
  5291. for (i=0; i < m_Colors; i++)
  5292. for (c=0; c < m_Colors; c++) l_cc[i][c] *= l_ab[i];
  5293. if (l_use_cm) {
  5294. for (c=0; c < m_Colors; c++) for (i=0; i < 3; i++)
  5295. for (l_cam_xyz[c][i]=j=0; j < m_Colors; j++)
  5296. l_cam_xyz[c][i] += l_cc[c][j] * l_cm[j][i] * l_xyz[i];
  5297. cam_xyz_coeff (l_cam_xyz);
  5298. }
  5299. if (l_asn[0]) {
  5300. ASSIGN(m_CameraMultipliers[3], 0);
  5301. for (c=0; c < m_Colors; c++) ASSIGN(m_CameraMultipliers[c], 1 / l_asn[c]);
  5302. }
  5303. if (!l_use_cm)
  5304. for (c=0; c < m_Colors; c++)
  5305. ASSIGN(m_D65Multipliers[c],VALUE(m_D65Multipliers[c]) / l_cc[c][c]);
  5306. return 0;
  5307. }
  5308. // To get out of the mess what is global and what is local
  5309. // I started here with l_ tagging of the variables.
  5310. // (but the most simple like i or c which are evidently , hopefully , local)
  5311. // What remains must be a global.
  5312. // (jpta) This is what my EOS400D would do.
  5313. int CLASS parse_tiff (int l_Base) {
  5314. // Set to start of tiff
  5315. fseek (m_InputFile, l_Base, SEEK_SET);
  5316. // Check byte order and return if not OK
  5317. m_ByteOrder = get2();
  5318. if (m_ByteOrder != 0x4949 && m_ByteOrder != 0x4d4d) return 0;
  5319. get2();
  5320. int l_doff;
  5321. while ((l_doff = get4())) {
  5322. fseek (m_InputFile, l_doff+l_Base, SEEK_SET);
  5323. if (parse_tiff_ifd (l_Base)) break;
  5324. }
  5325. return 1;
  5326. }
  5327. void CLASS apply_tiff()
  5328. {
  5329. int l_MaxSample=0;
  5330. int l_Raw=-1;
  5331. int l_Thumb=-1;
  5332. int i;
  5333. struct jhead l_Jhead;
  5334. m_ThumbMisc = 16;
  5335. if (m_ThumbOffset) {
  5336. fseek (m_InputFile,m_ThumbOffset,SEEK_SET);
  5337. if (ljpeg_start (&l_Jhead, 1)) {
  5338. m_ThumbMisc = l_Jhead.bits;
  5339. m_ThumbWidth = l_Jhead.wide;
  5340. m_ThumbHeight = l_Jhead.high;
  5341. }
  5342. }
  5343. for (i=0; (unsigned) i < m_Tiff_NrIFDs; i++) {
  5344. if (l_MaxSample < m_Tiff_IFD[i].samples)
  5345. l_MaxSample = m_Tiff_IFD[i].samples;
  5346. if (l_MaxSample > 3) l_MaxSample = 3;
  5347. if ((m_Tiff_IFD[i].comp != 6 || m_Tiff_IFD[i].samples != 3) &&
  5348. (m_Tiff_IFD[i].width | m_Tiff_IFD[i].height) < 0x10000 &&
  5349. m_Tiff_IFD[i].width*m_Tiff_IFD[i].height > m_RawWidth*m_RawHeight) {
  5350. m_RawWidth = m_Tiff_IFD[i].width;
  5351. m_RawHeight = m_Tiff_IFD[i].height;
  5352. m_Tiff_bps = m_Tiff_IFD[i].bps;
  5353. m_Tiff_Compress = m_Tiff_IFD[i].comp;
  5354. m_Data_Offset = m_Tiff_IFD[i].offset;
  5355. m_Tiff_Flip = m_Tiff_IFD[i].flip;
  5356. m_Tiff_Samples = m_Tiff_IFD[i].samples;
  5357. m_TileWidth = m_Tiff_IFD[i].tile_width;
  5358. m_TileLength = m_Tiff_IFD[i].tile_length;
  5359. l_Raw = i;
  5360. }
  5361. }
  5362. if (!m_TileWidth ) m_TileWidth = INT_MAX;
  5363. if (!m_TileLength) m_TileLength = INT_MAX;
  5364. for (i=m_Tiff_NrIFDs; i--; )
  5365. if (m_Tiff_IFD[i].flip) m_Tiff_Flip = m_Tiff_IFD[i].flip;
  5366. if (l_Raw >= 0 && !m_LoadRawFunction)
  5367. switch (m_Tiff_Compress) {
  5368. case 32767:
  5369. if (m_Tiff_IFD[l_Raw].bytes == m_RawWidth*m_RawHeight) {
  5370. m_Tiff_bps = 12;
  5371. m_LoadRawFunction = &CLASS sony_arw2_load_raw;
  5372. break;
  5373. }
  5374. if (m_Tiff_IFD[l_Raw].bytes*8U != m_RawWidth*m_RawHeight*m_Tiff_bps) {
  5375. m_RawHeight += 8;
  5376. m_LoadRawFunction = &CLASS sony_arw_load_raw;
  5377. break;
  5378. }
  5379. m_Load_Flags = 79;
  5380. case 32769:
  5381. m_Load_Flags++;
  5382. case 32770:
  5383. case 32773: goto slr;
  5384. case 0: case 1:
  5385. if (m_Tiff_IFD[l_Raw].bytes*5 == m_RawWidth*m_RawHeight*8) {
  5386. m_Load_Flags = 81;
  5387. m_Tiff_bps = 12;
  5388. } slr:
  5389. switch (m_Tiff_bps) {
  5390. case 8: m_LoadRawFunction = &CLASS eight_bit_load_raw; break;
  5391. case 12: if (m_Tiff_IFD[l_Raw].phint == 2)
  5392. m_Load_Flags = 6;
  5393. m_LoadRawFunction = &CLASS packed_load_raw; break;
  5394. case 14: m_Load_Flags = 0;
  5395. case 16: m_LoadRawFunction = &CLASS unpacked_load_raw; break;
  5396. }
  5397. break;
  5398. case 6: case 7: case 99:
  5399. m_LoadRawFunction = &CLASS lossless_jpeg_load_raw; break;
  5400. case 262:
  5401. m_LoadRawFunction = &CLASS kodak_262_load_raw; break;
  5402. case 34713:
  5403. if ((m_RawWidth+9)/10*16*m_RawHeight == m_Tiff_IFD[l_Raw].bytes) {
  5404. m_LoadRawFunction = &CLASS packed_load_raw;
  5405. m_Load_Flags = 1;
  5406. } else if (m_RawWidth*m_RawHeight*2 == m_Tiff_IFD[l_Raw].bytes) {
  5407. m_LoadRawFunction = &CLASS unpacked_load_raw;
  5408. m_Load_Flags = 4;
  5409. m_ByteOrder = 0x4d4d;
  5410. } else
  5411. m_LoadRawFunction = &CLASS nikon_load_raw; break;
  5412. case 34892:
  5413. m_LoadRawFunction = &CLASS lossy_dng_load_raw; break;
  5414. case 65535:
  5415. m_LoadRawFunction = &CLASS pentax_load_raw;
  5416. break;
  5417. case 65000:
  5418. switch (m_Tiff_IFD[l_Raw].phint) {
  5419. case 2: m_LoadRawFunction = &CLASS kodak_rgb_load_raw;
  5420. m_Filters = 0;
  5421. break;
  5422. case 6: m_LoadRawFunction = &CLASS kodak_ycbcr_load_raw;
  5423. m_Filters = 0;
  5424. break;
  5425. case 32803: m_LoadRawFunction = &CLASS kodak_65000_load_raw;
  5426. }
  5427. case 32867: break;
  5428. default: m_IsRaw = 0;
  5429. }
  5430. if (!m_DNG_Version)
  5431. if ( (m_Tiff_Samples == 3 && m_Tiff_IFD[l_Raw].bytes &&
  5432. m_Tiff_bps != 14 && m_Tiff_bps != 2048 &&
  5433. m_Tiff_Compress != 32769 && m_Tiff_Compress != 32770)
  5434. || (m_Tiff_bps == 8 && !strstr(m_CameraMake,"KODAK") &&
  5435. !strstr(m_CameraMake,"Kodak") &&
  5436. !strstr(m_CameraModelBis,"DEBUG RAW")))
  5437. m_IsRaw = 0;
  5438. for (i=0; (unsigned) i < m_Tiff_NrIFDs; i++) {
  5439. auto l_denom1 = SQR(m_Tiff_IFD[i].bps+1);
  5440. auto l_denom2 = SQR(m_ThumbMisc+1);
  5441. if (l_denom1 == 0 || l_denom2 == 0)
  5442. continue; // prevent divide by zero crash
  5443. if (i != l_Raw &&
  5444. m_Tiff_IFD[i].samples == l_MaxSample &&
  5445. (unsigned)(m_Tiff_IFD[i].width * m_Tiff_IFD[i].height / l_denom1) >
  5446. m_ThumbWidth * m_ThumbHeight / l_denom2 &&
  5447. m_Tiff_IFD[i].comp != 34892)
  5448. {
  5449. m_ThumbWidth = m_Tiff_IFD[i].width;
  5450. m_ThumbHeight = m_Tiff_IFD[i].height;
  5451. m_ThumbOffset = m_Tiff_IFD[i].offset;
  5452. m_ThumbLength = m_Tiff_IFD[i].bytes;
  5453. m_ThumbMisc = m_Tiff_IFD[i].bps;
  5454. l_Thumb = i;
  5455. }
  5456. }
  5457. if (l_Thumb >= 0) {
  5458. m_ThumbMisc |= m_Tiff_IFD[l_Thumb].samples << 5;
  5459. switch (m_Tiff_IFD[l_Thumb].comp) {
  5460. case 0:
  5461. m_WriteThumb = &CLASS layer_thumb;
  5462. break;
  5463. case 1:
  5464. if (m_Tiff_IFD[l_Thumb].bps <= 8)
  5465. m_WriteThumb = &CLASS ppm_thumb;
  5466. else if (!strcmp(m_CameraMake,"Imacon"))
  5467. m_WriteThumb = &CLASS ppm16_thumb;
  5468. else
  5469. m_ThumbLoadRawFunction = &CLASS kodak_thumb_load_raw;
  5470. break;
  5471. case 65000:
  5472. m_ThumbLoadRawFunction = m_Tiff_IFD[l_Thumb].phint == 6 ?
  5473. &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
  5474. }
  5475. }
  5476. }
  5477. void CLASS parse_minolta (int base)
  5478. {
  5479. int save, tag, len, offset, high=0, wide=0, i, c;
  5480. short sorder=m_ByteOrder;
  5481. fseek (m_InputFile, base, SEEK_SET);
  5482. if (fgetc(m_InputFile) || fgetc(m_InputFile)-'M' || fgetc(m_InputFile)-'R') return;
  5483. m_ByteOrder = fgetc(m_InputFile) * 0x101;
  5484. offset = base + get4() + 8;
  5485. while ((save=ftell(m_InputFile)) < offset) {
  5486. for (tag=i=0; i < 4; i++)
  5487. tag = tag << 8 | fgetc(m_InputFile);
  5488. len = get4();
  5489. switch (tag) {
  5490. case 0x505244: /* PRD */
  5491. fseek (m_InputFile, 8, SEEK_CUR);
  5492. high = get2();
  5493. wide = get2();
  5494. break;
  5495. case 0x574247: /* WBG */
  5496. get4();
  5497. i = strcmp(m_CameraModel,"DiMAGE A200") ? 0:3;
  5498. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ i], get2());
  5499. break;
  5500. case 0x545457: /* TTW */
  5501. parse_tiff (ftell(m_InputFile));
  5502. m_Data_Offset = offset;
  5503. }
  5504. fseek (m_InputFile, save+len+8, SEEK_SET);
  5505. }
  5506. m_RawHeight = high;
  5507. m_RawWidth = wide;
  5508. m_ByteOrder = sorder;
  5509. }
  5510. /*
  5511. Many cameras have a "debug mode" that writes JPEG and raw
  5512. at the same time. The raw file has no header, so try to
  5513. to open the matching JPEG file and read its metadata.
  5514. */
  5515. void CLASS parse_external_jpeg()
  5516. {
  5517. const char *file, *ext;
  5518. char *jname, *jfile, *jext;
  5519. FILE *save=m_InputFile;
  5520. ext = strrchr (m_UserSetting_InputFileName, '.');
  5521. file = strrchr (m_UserSetting_InputFileName, '/');
  5522. if (!file) file = strrchr (m_UserSetting_InputFileName, '\\');
  5523. if (!file) file = m_UserSetting_InputFileName-1;
  5524. file++;
  5525. if (!ext || strlen(ext) != 4 || ext-file != 8) return;
  5526. jname = (char *) MALLOC (strlen(m_UserSetting_InputFileName) + 1);
  5527. merror (jname, "parse_external_jpeg()");
  5528. strcpy (jname, m_UserSetting_InputFileName);
  5529. jfile = file - m_UserSetting_InputFileName + jname;
  5530. jext = ext - m_UserSetting_InputFileName + jname;
  5531. if (strcasecmp (ext, ".jpg")) {
  5532. strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
  5533. if (isdigit(*file)) {
  5534. memcpy (jfile, file+4, 4);
  5535. memcpy (jfile+4, file, 4);
  5536. }
  5537. } else
  5538. while (isdigit(*--jext)) {
  5539. if (*jext != '9') {
  5540. (*jext)++;
  5541. break;
  5542. }
  5543. *jext = '0';
  5544. }
  5545. if (strcmp (jname, m_UserSetting_InputFileName)) {
  5546. if ((m_InputFile = fopen (jname, "rb"))) {
  5547. TRACEKEYVALS("Reading metadata from","%s",jname);
  5548. parse_tiff (12);
  5549. m_ThumbOffset = 0;
  5550. m_IsRaw = 1;
  5551. FCLOSE (m_InputFile);
  5552. }
  5553. }
  5554. if (!m_TimeStamp)
  5555. fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
  5556. FREE (jname);
  5557. m_InputFile = save;
  5558. }
  5559. /*
  5560. CIFF block 0x1030 contains an 8x8 white sample.
  5561. Load this into white[][] for use in scale_colors().
  5562. */
  5563. void CLASS ciff_block_1030()
  5564. {
  5565. static const uint16_t key[] = { 0x410, 0x45f3 };
  5566. int i, bpp, row, col, vbits=0;
  5567. unsigned long bitbuf=0;
  5568. if ((get2(),get4()) != 0x80008 || !get4()) return;
  5569. bpp = get2();
  5570. if (bpp != 10 && bpp != 12) return;
  5571. for (i=row=0; row < 8; row++)
  5572. for (col=0; col < 8; col++) {
  5573. if (vbits < bpp) {
  5574. bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
  5575. vbits += 16;
  5576. }
  5577. white[row][col] =
  5578. bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
  5579. vbits -= bpp;
  5580. }
  5581. }
  5582. /*
  5583. Parse a CIFF file, better known as Canon CRW format.
  5584. */
  5585. void CLASS parse_ciff (int offset, int length)
  5586. {
  5587. int tboff, nrecs, c, type, len, save, wbi=-1;
  5588. uint16_t key[] = { 0x410, 0x45f3 };
  5589. fseek (m_InputFile, offset+length-4, SEEK_SET);
  5590. tboff = get4() + offset;
  5591. fseek (m_InputFile, tboff, SEEK_SET);
  5592. nrecs = get2();
  5593. if (nrecs > 100) return;
  5594. while (nrecs--) {
  5595. type = get2();
  5596. len = get4();
  5597. save = ftell(m_InputFile) + 4;
  5598. fseek (m_InputFile, offset+get4(), SEEK_SET);
  5599. if ((((type >> 8) + 8) | 8) == 0x38)
  5600. parse_ciff (ftell(m_InputFile), len); /* Parse a sub-table */
  5601. if (type == 0x0810)
  5602. ptfread (m_Artist, 64, 1, m_InputFile);
  5603. if (type == 0x080a) {
  5604. ptfread (m_CameraMake, 64, 1, m_InputFile);
  5605. fseek (m_InputFile, strlen(m_CameraMake) - 63, SEEK_CUR);
  5606. ptfread (m_CameraModel, 64, 1, m_InputFile);
  5607. }
  5608. if (type == 0x1810) {
  5609. fseek (m_InputFile, 12, SEEK_CUR);
  5610. m_Flip = get4();
  5611. }
  5612. if (type == 0x1835) /* Get the decoder table */
  5613. m_Tiff_Compress = get4();
  5614. if (type == 0x2007) {
  5615. m_ThumbOffset = ftell(m_InputFile);
  5616. m_ThumbLength = len;
  5617. }
  5618. if (type == 0x1818) {
  5619. m_Shutter = pow (2, -int_to_float((get4(),get4())));
  5620. m_Aperture = pow (2, int_to_float(get4())/2);
  5621. }
  5622. if (type == 0x102a) {
  5623. m_IsoSpeed = pow (2, (get4(),get2())/32.0 - 4) * 50;
  5624. m_Aperture = pow (2, (get2(),(short)get2())/64.0);
  5625. m_Shutter = pow (2,-((short)get2())/32.0);
  5626. wbi = (get2(),get2());
  5627. if (wbi > 17) wbi = 0;
  5628. fseek (m_InputFile, 32, SEEK_CUR);
  5629. if (m_Shutter > 1e6) m_Shutter = get2()/10.0;
  5630. }
  5631. if (type == 0x102c) {
  5632. if (get2() > 512) { /* Pro90, G1 */
  5633. fseek (m_InputFile, 118, SEEK_CUR);
  5634. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ 2], get2());
  5635. } else { /* G2, S30, S40 */
  5636. fseek (m_InputFile, 98, SEEK_CUR);
  5637. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ 1], get2());
  5638. }
  5639. }
  5640. if (type == 0x0032) {
  5641. if (len == 768) { /* EOS D30 */
  5642. fseek (m_InputFile, 72, SEEK_CUR);
  5643. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], 1024.0 / get2());
  5644. if (!wbi) ASSIGN(m_CameraMultipliers[0], -1); /* use my auto white balance */
  5645. } else if (!VALUE(m_CameraMultipliers[0])) {
  5646. if (get2() == key[0]) /* Pro1, G6, S60, S70 */
  5647. c = (strstr(m_CameraModel,"Pro1") ?
  5648. "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
  5649. else { /* G3, G5, S45, S50 */
  5650. c = "023457000000006000"[wbi]-'0';
  5651. key[0] = key[1] = 0;
  5652. }
  5653. fseek (m_InputFile, 78 + c*8, SEEK_CUR);
  5654. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1) ^ 1], get2() ^ key[c & 1]);
  5655. if (!wbi) ASSIGN(m_CameraMultipliers[0], -1);
  5656. }
  5657. }
  5658. if (type == 0x10a9) { /* D60, 10D, 300D, and clones */
  5659. if (len > 66) wbi = "0134567028"[wbi]-'0';
  5660. fseek (m_InputFile, 2 + wbi*8, SEEK_CUR);
  5661. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get2());
  5662. }
  5663. if (type == 0x1030 && (0x18040 >> wbi & 1))
  5664. ciff_block_1030(); /* all that don't have 0x10a9 */
  5665. if (type == 0x1031) {
  5666. m_RawWidth = (get2(),get2());
  5667. m_RawHeight = get2();
  5668. }
  5669. if (type == 0x5029) {
  5670. m_FocalLength = len >> 16;
  5671. if ((len & 0xffff) == 2) m_FocalLength /= 32;
  5672. }
  5673. if (type == 0x5813) flash_used = int_to_float(len);
  5674. if (type == 0x5814) canon_ev = int_to_float(len);
  5675. if (type == 0x5817) m_ShotOrder = len;
  5676. if (type == 0x5834) unique_id = len;
  5677. if (type == 0x580e) m_TimeStamp = len;
  5678. if (type == 0x180e) m_TimeStamp = get4();
  5679. #ifdef LOCALTIME
  5680. if ((type | 0x4000) == 0x580e)
  5681. m_TimeStamp = mktime (gmtime (&m_TimeStamp));
  5682. #endif
  5683. fseek (m_InputFile, save, SEEK_SET);
  5684. }
  5685. }
  5686. void CLASS parse_rollei()
  5687. {
  5688. char line[128], *val;
  5689. struct tm t;
  5690. fseek (m_InputFile, 0, SEEK_SET);
  5691. memset (&t, 0, sizeof t);
  5692. do {
  5693. ptfgets (line, 128, m_InputFile);
  5694. if ((val = strchr(line,'=')))
  5695. *val++ = 0;
  5696. else
  5697. val = line + strlen(line);
  5698. if (!strcmp(line,"DAT"))
  5699. sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
  5700. if (!strcmp(line,"TIM"))
  5701. sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
  5702. if (!strcmp(line,"HDR"))
  5703. m_ThumbOffset = atoi(val);
  5704. if (!strcmp(line,"X "))
  5705. m_RawWidth = atoi(val);
  5706. if (!strcmp(line,"Y "))
  5707. m_RawHeight = atoi(val);
  5708. if (!strcmp(line,"TX "))
  5709. m_ThumbWidth = atoi(val);
  5710. if (!strcmp(line,"TY "))
  5711. m_ThumbHeight = atoi(val);
  5712. } while (strncmp(line,"EOHD",4));
  5713. m_Data_Offset = m_ThumbOffset + m_ThumbWidth * m_ThumbHeight * 2;
  5714. t.tm_year -= 1900;
  5715. t.tm_mon -= 1;
  5716. if (mktime(&t) > 0)
  5717. m_TimeStamp = mktime(&t);
  5718. strcpy (m_CameraMake, "Rollei");
  5719. strcpy (m_CameraModel,"d530flex");
  5720. m_WriteThumb = &CLASS rollei_thumb;
  5721. }
  5722. void CLASS parse_sinar_ia()
  5723. {
  5724. int entries, off;
  5725. char str[8], *cp;
  5726. m_ByteOrder = 0x4949;
  5727. fseek (m_InputFile, 4, SEEK_SET);
  5728. entries = get4();
  5729. fseek (m_InputFile, get4(), SEEK_SET);
  5730. while (entries--) {
  5731. off = get4(); get4();
  5732. ptfread (str, 8, 1, m_InputFile);
  5733. if (!strcmp(str,"META")) meta_offset = off;
  5734. if (!strcmp(str,"THUMB")) m_ThumbOffset = off;
  5735. if (!strcmp(str,"RAW0")) m_Data_Offset = off;
  5736. }
  5737. fseek (m_InputFile, meta_offset+20, SEEK_SET);
  5738. ptfread (m_CameraMake, 64, 1, m_InputFile);
  5739. m_CameraMake[63] = 0;
  5740. if ((cp = strchr(m_CameraMake,' '))) {
  5741. strcpy (m_CameraModel, cp+1);
  5742. *cp = 0;
  5743. }
  5744. m_RawWidth = get2();
  5745. m_RawHeight = get2();
  5746. m_LoadRawFunction = &CLASS unpacked_load_raw;
  5747. m_ThumbWidth = (get4(),get2());
  5748. m_ThumbHeight = get2();
  5749. m_WriteThumb = &CLASS ppm_thumb;
  5750. m_WhiteLevel = 0x3fff;
  5751. }
  5752. void CLASS parse_phase_one (int base)
  5753. {
  5754. //warning: variable 'type' set but not used [-Wunused-but-set-variable]
  5755. unsigned entries, tag, /*type,*/ len, data, save, i, c;
  5756. float romm_cam[3][3];
  5757. char *cp;
  5758. memset (&ph1, 0, sizeof ph1);
  5759. fseek (m_InputFile, base, SEEK_SET);
  5760. m_ByteOrder = get4() & 0xffff;
  5761. if (get4() >> 8 != 0x526177) return; /* "Raw" */
  5762. fseek (m_InputFile, get4()+base, SEEK_SET);
  5763. entries = get4();
  5764. get4();
  5765. while (entries--) {
  5766. tag = get4();
  5767. // type = get4();
  5768. len = get4();
  5769. data = get4();
  5770. save = ftell(m_InputFile);
  5771. fseek (m_InputFile, base+data, SEEK_SET);
  5772. switch (tag) {
  5773. case 0x100: m_Flip = "0653"[data & 3]-'0'; break;
  5774. case 0x106:
  5775. for (i=0; i < 3; i++)
  5776. for (short j=0; j<3; j++)
  5777. romm_cam[i][j] = getreal(11);
  5778. romm_coeff (romm_cam);
  5779. break;
  5780. case 0x107:
  5781. for (c=0; c<3; c++) ASSIGN(m_CameraMultipliers[c], getreal(11));
  5782. break;
  5783. case 0x108: m_RawWidth = data; break;
  5784. case 0x109: m_RawHeight = data; break;
  5785. case 0x10a: m_LeftMargin = data; break;
  5786. case 0x10b: m_TopMargin = data; break;
  5787. case 0x10c: m_Width = data; break;
  5788. case 0x10d: m_Height = data; break;
  5789. case 0x10e: ph1.format = data; break;
  5790. case 0x10f: m_Data_Offset = data+base; break;
  5791. case 0x110: meta_offset = data+base;
  5792. m_MetaLength = len; break;
  5793. case 0x112: ph1.key_off = save - 4; break;
  5794. case 0x210: ph1.tag_210 = int_to_float(data); break;
  5795. case 0x21a: ph1.tag_21a = data; break;
  5796. case 0x21c: strip_offset = data+base; break;
  5797. case 0x21d: ph1.black = data; break;
  5798. case 0x222: ph1.split_col = data; break;
  5799. case 0x223: ph1.black_off = data+base; break;
  5800. case 0x301:
  5801. m_CameraModel[63] = 0;
  5802. ptfread (m_CameraModel, 1, 63, m_InputFile);
  5803. if ((cp = strstr(m_CameraModel," camera"))) *cp = 0;
  5804. }
  5805. fseek (m_InputFile, save, SEEK_SET);
  5806. }
  5807. m_LoadRawFunction = ph1.format < 3 ?
  5808. &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
  5809. m_WhiteLevel = 0xffff;
  5810. strcpy (m_CameraMake, "Phase One");
  5811. if (m_CameraModel[0]) return;
  5812. switch (m_RawHeight) {
  5813. case 2060: strcpy (m_CameraModel,"LightPhase"); break;
  5814. case 2682: strcpy (m_CameraModel,"H 10"); break;
  5815. case 4128: strcpy (m_CameraModel,"H 20"); break;
  5816. case 5488: strcpy (m_CameraModel,"H 25"); break;
  5817. }
  5818. }
  5819. void CLASS parse_fuji (int offset)
  5820. {
  5821. unsigned entries, tag, len, save, c;
  5822. fseek (m_InputFile, offset, SEEK_SET);
  5823. entries = get4();
  5824. if (entries > 255) return;
  5825. while (entries--) {
  5826. tag = get2();
  5827. len = get2();
  5828. save = ftell(m_InputFile);
  5829. if (tag == 0x100) {
  5830. m_RawHeight = get2();
  5831. m_RawWidth = get2();
  5832. } else if (tag == 0x121) {
  5833. m_Height = get2();
  5834. if ((m_Width = get2()) == 4284) m_Width += 3;
  5835. } else if (tag == 0x130) {
  5836. fuji_layout = fgetc(m_InputFile) >> 7;
  5837. m_Fuji_Width = !(fgetc(m_InputFile) & 8);
  5838. } else if (tag == 0x2ff0) {
  5839. for (c=0; c<4; c++) m_CameraMultipliers[c ^ 1] = get2();
  5840. } else if (tag == 0xc000) {
  5841. c = m_ByteOrder;
  5842. m_ByteOrder = 0x4949;
  5843. if ((m_Width = get4()) > 10000) m_Width = get4();
  5844. m_Height = get4();
  5845. m_ByteOrder = c;
  5846. }
  5847. fseek (m_InputFile, save+len, SEEK_SET);
  5848. }
  5849. if (!m_RawHeight) {
  5850. m_Filters = 0x16161616;
  5851. m_LoadRawFunction = &CLASS packed_load_raw;
  5852. m_Load_Flags = 24;
  5853. }
  5854. m_Height <<= fuji_layout;
  5855. m_Width >>= fuji_layout;
  5856. }
  5857. int CLASS parse_jpeg (int offset)
  5858. {
  5859. int len, save, hlen, mark;
  5860. fseek (m_InputFile, offset, SEEK_SET);
  5861. if (fgetc(m_InputFile) != 0xff || fgetc(m_InputFile) != 0xd8) return 0;
  5862. while (fgetc(m_InputFile) == 0xff && (mark = fgetc(m_InputFile)) != 0xda) {
  5863. m_ByteOrder = 0x4d4d;
  5864. len = get2() - 2;
  5865. save = ftell(m_InputFile);
  5866. if (mark == 0xc0 || mark == 0xc3) {
  5867. fgetc(m_InputFile);
  5868. m_RawHeight = get2();
  5869. m_RawWidth = get2();
  5870. }
  5871. m_ByteOrder = get2();
  5872. hlen = get4();
  5873. if (get4() == 0x48454150) /* "HEAP" */
  5874. parse_ciff (save+hlen, len-hlen);
  5875. if (parse_tiff (save+6)) apply_tiff();
  5876. fseek (m_InputFile, save+len, SEEK_SET);
  5877. }
  5878. return 1;
  5879. }
  5880. void CLASS parse_riff()
  5881. {
  5882. unsigned i, size, end;
  5883. char tag[4], date[64], month[64];
  5884. static const char mon[12][4] =
  5885. { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
  5886. struct tm t;
  5887. m_ByteOrder = 0x4949;
  5888. ptfread (tag, 4, 1, m_InputFile);
  5889. size = get4();
  5890. end = ftell(m_InputFile) + size;
  5891. if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
  5892. get4();
  5893. while (ftell(m_InputFile)+7 < (long) end)
  5894. parse_riff();
  5895. } else if (!memcmp(tag,"nctg",4)) {
  5896. while ((unsigned) ftell(m_InputFile)+7 < end) {
  5897. i = get2();
  5898. size = get2();
  5899. if ((i+1) >> 1 == 10 && size == 20)
  5900. get_timestamp(0);
  5901. else fseek (m_InputFile, size, SEEK_CUR);
  5902. }
  5903. } else if (!memcmp(tag,"IDIT",4) && size < 64) {
  5904. ptfread (date, 64, 1, m_InputFile);
  5905. date[size] = 0;
  5906. memset (&t, 0, sizeof t);
  5907. if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
  5908. &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
  5909. for (i=0; i < 12 && strcasecmp(mon[i],month); i++) {};
  5910. t.tm_mon = i;
  5911. t.tm_year -= 1900;
  5912. if (mktime(&t) > 0)
  5913. m_TimeStamp = mktime(&t);
  5914. }
  5915. } else
  5916. fseek (m_InputFile, size, SEEK_CUR);
  5917. }
  5918. void CLASS parse_smal (int offset, int fsize)
  5919. {
  5920. int ver;
  5921. fseek (m_InputFile, offset+2, SEEK_SET);
  5922. m_ByteOrder = 0x4949;
  5923. ver = fgetc(m_InputFile);
  5924. if (ver == 6)
  5925. fseek (m_InputFile, 5, SEEK_CUR);
  5926. if (get4() != (unsigned) fsize) return;
  5927. if (ver > 6) m_Data_Offset = get4();
  5928. m_RawHeight = m_Height = get2();
  5929. m_RawWidth = m_Width = get2();
  5930. strcpy (m_CameraMake, "SMaL");
  5931. sprintf (m_CameraModel, "v%d %dx%d", ver, m_Width, m_Height);
  5932. if (ver == 6) m_LoadRawFunction = &CLASS smal_v6_load_raw;
  5933. if (ver == 9) m_LoadRawFunction = &CLASS smal_v9_load_raw;
  5934. }
  5935. void CLASS parse_cine()
  5936. {
  5937. unsigned off_head, off_setup, off_image, i;
  5938. m_ByteOrder = 0x4949;
  5939. fseek (m_InputFile, 4, SEEK_SET);
  5940. m_IsRaw = get2() == 2;
  5941. fseek (m_InputFile, 14, SEEK_CUR);
  5942. m_IsRaw *= get4();
  5943. off_head = get4();
  5944. off_setup = get4();
  5945. off_image = get4();
  5946. m_TimeStamp = get4();
  5947. if ((i = get4())) m_TimeStamp = i;
  5948. fseek (m_InputFile, off_head+4, SEEK_SET);
  5949. m_RawWidth = get4();
  5950. m_RawHeight = get4();
  5951. switch (get2(),get2()) {
  5952. case 8: m_LoadRawFunction = &CLASS eight_bit_load_raw; break;
  5953. case 16: m_LoadRawFunction = &CLASS unpacked_load_raw;
  5954. }
  5955. fseek (m_InputFile, off_setup+792, SEEK_SET);
  5956. strcpy (m_CameraMake, "CINE");
  5957. sprintf (m_CameraModel, "%d", get4());
  5958. fseek (m_InputFile, 12, SEEK_CUR);
  5959. switch ((i=get4()) & 0xffffff) {
  5960. case 3: m_Filters = 0x94949494; break;
  5961. case 4: m_Filters = 0x49494949; break;
  5962. default: m_IsRaw = 0;
  5963. }
  5964. fseek (m_InputFile, 72, SEEK_CUR);
  5965. switch ((get4()+3600) % 360) {
  5966. case 270: m_Flip = 4; break;
  5967. case 180: m_Flip = 1; break;
  5968. case 90: m_Flip = 7; break;
  5969. case 0: m_Flip = 2;
  5970. }
  5971. ASSIGN(m_CameraMultipliers[0], getreal(11));
  5972. ASSIGN(m_CameraMultipliers[2], getreal(11));
  5973. m_WhiteLevel = ~(-1 << get4());
  5974. fseek (m_InputFile, 668, SEEK_CUR);
  5975. m_Shutter = get4()/1000000000.0;
  5976. fseek (m_InputFile, off_image, SEEK_SET);
  5977. if (m_UserSetting_ShotSelect < m_IsRaw)
  5978. fseek (m_InputFile, m_UserSetting_ShotSelect*8, SEEK_CUR);
  5979. m_Data_Offset = (int64_t) get4() + 8;
  5980. m_Data_Offset += (int64_t) get4() << 32;
  5981. }
  5982. void CLASS parse_redcine()
  5983. {
  5984. unsigned i, len, rdvo;
  5985. m_ByteOrder = 0x4d4d;
  5986. m_IsRaw = 0;
  5987. fseek (m_InputFile, 52, SEEK_SET);
  5988. m_Width = get4();
  5989. m_Height = get4();
  5990. fseek (m_InputFile, 0, SEEK_END);
  5991. fseek (m_InputFile, -(i = ftell(m_InputFile) & 511), SEEK_CUR);
  5992. if (get4() != i || get4() != 0x52454f42) {
  5993. fprintf (stderr,_("%s: Tail is missing, parsing from head...\n"), m_UserSetting_InputFileName);
  5994. fseek (m_InputFile, 0, SEEK_SET);
  5995. while ((int)(len = get4()) != EOF) {
  5996. if (get4() == 0x52454456)
  5997. if (m_IsRaw++ == m_UserSetting_ShotSelect)
  5998. m_Data_Offset = ftell(m_InputFile) - 8;
  5999. fseek (m_InputFile, len-8, SEEK_CUR);
  6000. }
  6001. } else {
  6002. rdvo = get4();
  6003. fseek (m_InputFile, 12, SEEK_CUR);
  6004. m_IsRaw = get4();
  6005. fseek (m_InputFile, rdvo+8 + m_UserSetting_ShotSelect*4, SEEK_SET);
  6006. m_Data_Offset = get4();
  6007. }
  6008. }
  6009. char * CLASS foveon_gets (int offset, char *str, int len)
  6010. {
  6011. int i;
  6012. fseek (m_InputFile, offset, SEEK_SET);
  6013. for (i=0; i < len-1; i++)
  6014. if ((str[i] = get2()) == 0) break;
  6015. str[i] = 0;
  6016. return str;
  6017. }
  6018. void CLASS parse_foveon()
  6019. {
  6020. int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
  6021. char name[64], value[64];
  6022. m_ByteOrder = 0x4949; /* Little-endian */
  6023. fseek (m_InputFile, 36, SEEK_SET);
  6024. m_Flip = get4();
  6025. fseek (m_InputFile, -4, SEEK_END);
  6026. fseek (m_InputFile, get4(), SEEK_SET);
  6027. if (get4() != 0x64434553) return; /* SECd */
  6028. entries = (get4(),get4());
  6029. while (entries--) {
  6030. off = get4();
  6031. len = get4();
  6032. tag = get4();
  6033. save = ftell(m_InputFile);
  6034. fseek (m_InputFile, off, SEEK_SET);
  6035. if (get4() != (unsigned)(0x20434553 | (tag << 24))) return;
  6036. switch (tag) {
  6037. case 0x47414d49: /* IMAG */
  6038. case 0x32414d49: /* IMA2 */
  6039. fseek (m_InputFile, 8, SEEK_CUR);
  6040. pent = get4();
  6041. wide = get4();
  6042. high = get4();
  6043. if (wide > m_RawWidth && high > m_RawHeight) {
  6044. switch (pent) {
  6045. case 5: m_Load_Flags = 1;
  6046. case 6: m_LoadRawFunction = &CLASS foveon_sd_load_raw; break;
  6047. case 30: m_LoadRawFunction = &CLASS foveon_dp_load_raw; break;
  6048. default: m_LoadRawFunction = 0;
  6049. }
  6050. m_RawWidth = wide;
  6051. m_RawHeight = high;
  6052. m_Data_Offset = off+28;
  6053. }
  6054. fseek (m_InputFile, off+28, SEEK_SET);
  6055. if (fgetc(m_InputFile) == 0xff && fgetc(m_InputFile) == 0xd8
  6056. && m_ThumbLength < (unsigned)(len-28)) {
  6057. m_ThumbOffset = off+28;
  6058. m_ThumbLength = len-28;
  6059. m_WriteThumb = &CLASS jpeg_thumb;
  6060. }
  6061. if (++img == 2 && !m_ThumbLength) {
  6062. m_ThumbOffset = off+24;
  6063. m_ThumbWidth = wide;
  6064. m_ThumbHeight = high;
  6065. m_WriteThumb = &CLASS foveon_thumb;
  6066. }
  6067. break;
  6068. case 0x464d4143: /* CAMF */
  6069. meta_offset = off+8;
  6070. m_MetaLength = len-28;
  6071. break;
  6072. case 0x504f5250: /* PROP */
  6073. pent = (get4(),get4());
  6074. fseek (m_InputFile, 12, SEEK_CUR);
  6075. off += pent*8 + 24;
  6076. if ((unsigned) pent > 256) pent=256;
  6077. for (i=0; i < pent*2; i++)
  6078. poff[0][i] = off + get4()*2;
  6079. for (i=0; i < pent; i++) {
  6080. foveon_gets (poff[i][0], name, 64);
  6081. foveon_gets (poff[i][1], value, 64);
  6082. if (!strcmp (name, "ISO"))
  6083. m_IsoSpeed = atoi(value);
  6084. if (!strcmp (name, "CAMMANUF"))
  6085. strcpy (m_CameraMake, value);
  6086. if (!strcmp (name, "CAMMODEL"))
  6087. strcpy (m_CameraModel, value);
  6088. if (!strcmp (name, "WB_DESC"))
  6089. strcpy (m_CameraModelBis, value);
  6090. if (!strcmp (name, "TIME"))
  6091. m_TimeStamp = atoi(value);
  6092. if (!strcmp (name, "EXPTIME"))
  6093. m_Shutter = atoi(value) / 1000000.0;
  6094. if (!strcmp (name, "APERTURE"))
  6095. m_Aperture = atof(value);
  6096. if (!strcmp (name, "FLENGTH"))
  6097. m_FocalLength = atof(value);
  6098. }
  6099. #ifdef LOCALTIME
  6100. m_TimeStamp = mktime (gmtime (&m_TimeStamp));
  6101. #endif
  6102. }
  6103. fseek (m_InputFile, save, SEEK_SET);
  6104. }
  6105. m_IsFoveon = 1;
  6106. }
  6107. /*
  6108. Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
  6109. All matrices are from Adobe DNG Converter unless otherwise noted.
  6110. */
  6111. #include "ptAdobeTable.h"
  6112. void CLASS adobe_coeff (const char *make, const char *model) {
  6113. double MatrixXYZToCamRGB[4][3];
  6114. char name[130];
  6115. unsigned i;
  6116. sprintf (name, "%s %s", make , model);
  6117. for (i=0; i < sizeof AdobeTable / sizeof *AdobeTable; i++)
  6118. if (!strncmp (name,
  6119. AdobeTable[i].Identification,
  6120. strlen(AdobeTable[i].Identification))) {
  6121. strcpy(m_CameraAdobeIdentification,AdobeTable[i].Identification);
  6122. if (AdobeTable[i].Blackpoint) {
  6123. m_BlackLevel = (uint16_t) AdobeTable[i].Blackpoint;
  6124. }
  6125. if (AdobeTable[i].Whitepoint) {
  6126. m_WhiteLevel = (uint16_t) AdobeTable[i].Whitepoint;
  6127. }
  6128. if (AdobeTable[i].XYZToCam[0]) {
  6129. for (short j=0; j < 4; j++) {
  6130. for (short k=0; k<3; k++) {
  6131. MatrixXYZToCamRGB[j][k] = AdobeTable[i].XYZToCam[j*3+k] / 10000.0;
  6132. }
  6133. }
  6134. cam_xyz_coeff (MatrixXYZToCamRGB);
  6135. }
  6136. break;
  6137. }
  6138. }
  6139. void CLASS simple_coeff (int index)
  6140. {
  6141. static const float table[][12] = {
  6142. /* index 0 -- all Foveon cameras */
  6143. { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
  6144. /* index 1 -- Kodak DC20 and DC25 */
  6145. { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
  6146. /* index 2 -- Logitech Fotoman Pixtura */
  6147. { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
  6148. /* index 3 -- Nikon E880, E900, and E990 */
  6149. { -1.936280, 1.800443, -1.448486, 2.584324,
  6150. 1.405365, -0.524955, -0.289090, 0.408680,
  6151. -1.204965, 1.082304, 2.941367, -1.818705 }
  6152. };
  6153. int i, c;
  6154. for (m_RawColor = i=0; i < 3; i++)
  6155. for (c=0; c < m_Colors; c++) m_MatrixCamRGBToSRGB[i][c] = table[index][i*m_Colors+c];
  6156. }
  6157. short CLASS guess_byte_order (int words)
  6158. {
  6159. uint8_t test[4][2];
  6160. int t=2, msb;
  6161. double diff, sum[2] = {0,0};
  6162. ptfread (test[0], 2, 2, m_InputFile);
  6163. for (words-=2; words--; ) {
  6164. ptfread (test[t], 2, 1, m_InputFile);
  6165. for (msb=0; msb < 2; msb++) {
  6166. diff = (test[t^2][msb] << 8 | test[t^2][!msb])
  6167. - (test[t ][msb] << 8 | test[t ][!msb]);
  6168. sum[msb] += diff*diff;
  6169. }
  6170. t = (t+1) & 3;
  6171. }
  6172. return sum[0] < sum[1] ? 0x4d4d : 0x4949;
  6173. }
  6174. float CLASS find_green (int bps, int bite, int off0, int off1)
  6175. {
  6176. uint64_t bitbuf=0;
  6177. int vbits, col, i, c;
  6178. uint16_t img[2][2064];
  6179. double sum[]={0,0};
  6180. for (c=0;c<2;c++) {
  6181. fseek (m_InputFile, c ? off1:off0, SEEK_SET);
  6182. for (vbits=col=0; col < m_Width; col++) {
  6183. for (vbits -= bps; vbits < 0; vbits += bite) {
  6184. bitbuf <<= bite;
  6185. for (i=0; i < bite; i+=8)
  6186. bitbuf |= (unsigned) (fgetc(m_InputFile) << i);
  6187. }
  6188. img[c][col] = bitbuf << (64-bps-vbits) >> (64-bps);
  6189. }
  6190. }
  6191. for (c=0;c<(m_Width-1);c++) {
  6192. sum[ c & 1] += ABS(img[0][c]-img[1][c+1]);
  6193. sum[~c & 1] += ABS(img[1][c]-img[0][c+1]);
  6194. }
  6195. return 100 * log(sum[0]/sum[1]);
  6196. }
  6197. /*
  6198. Identify which camera created this file, and set global variables
  6199. accordingly.
  6200. */
  6201. void CLASS identify() {
  6202. char l_Head[32];
  6203. char* l_CharPointer;
  6204. unsigned l_HLen;
  6205. unsigned l_FLen;
  6206. unsigned l_FileSize;
  6207. int zero_fsize = 1;
  6208. unsigned l_IsCanon;
  6209. struct jhead l_JHead;
  6210. unsigned i,c;
  6211. short pana[][6] = {
  6212. { 3130, 1743, 4, 0, -6, 0 },
  6213. { 3130, 2055, 4, 0, -6, 0 },
  6214. { 3130, 2319, 4, 0, -6, 0 },
  6215. { 3170, 2103, 18, 0,-42, 20 },
  6216. { 3170, 2367, 18, 13,-42,-21 },
  6217. { 3177, 2367, 0, 0, -1, 0 },
  6218. { 3304, 2458, 0, 0, -1, 0 },
  6219. { 3330, 2463, 9, 0, -5, 0 },
  6220. { 3330, 2479, 9, 0,-17, 4 },
  6221. { 3370, 1899, 15, 0,-44, 20 },
  6222. { 3370, 2235, 15, 0,-44, 20 },
  6223. { 3370, 2511, 15, 10,-44,-21 },
  6224. { 3690, 2751, 3, 0, -8, -3 },
  6225. { 3710, 2751, 0, 0, -3, 0 },
  6226. { 3724, 2450, 0, 0, 0, -2 },
  6227. { 3770, 2487, 17, 0,-44, 19 },
  6228. { 3770, 2799, 17, 15,-44,-19 },
  6229. { 3880, 2170, 6, 0, -6, 0 },
  6230. { 4060, 3018, 0, 0, 0, -2 },
  6231. { 4290, 2391, 3, 0, -8, -1 },
  6232. { 4330, 2439, 17, 15,-44,-19 },
  6233. { 4508, 2962, 0, 0, -3, -4 },
  6234. { 4508, 3330, 0, 0, -3, -6 } };
  6235. static const struct {
  6236. int fsize;
  6237. char make[12], model[19], withjpeg;
  6238. } l_Table[] = {
  6239. { 62464, "Kodak", "DC20" ,0 },
  6240. { 124928, "Kodak", "DC20" ,0 },
  6241. { 1652736, "Kodak", "DCS200" ,0 },
  6242. { 4159302, "Kodak", "C330" ,0 },
  6243. { 4162462, "Kodak", "C330" ,0 },
  6244. { 460800, "Kodak", "C603v" ,0 },
  6245. { 614400, "Kodak", "C603v" ,0 },
  6246. { 6163328, "Kodak", "C603" ,0 },
  6247. { 6166488, "Kodak", "C603" ,0 },
  6248. { 9116448, "Kodak", "C603y" ,0 },
  6249. { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */
  6250. { 787456, "Creative", "PC-CAM 600" ,0 },
  6251. { 1138688, "Minolta", "RD175" ,0 },
  6252. { 3840000, "Foculus", "531C" ,0 },
  6253. { 307200, "Generic", "640x480" ,0 },
  6254. { 786432, "AVT", "F-080C" ,0 },
  6255. { 1447680, "AVT", "F-145C" ,0 },
  6256. { 1920000, "AVT", "F-201C" ,0 },
  6257. { 5067304, "AVT", "F-510C" ,0 },
  6258. { 5067316, "AVT", "F-510C" ,0 },
  6259. { 10134608, "AVT", "F-510C" ,0 },
  6260. { 10134620, "AVT", "F-510C" ,0 },
  6261. { 16157136, "AVT", "F-810C" ,0 },
  6262. { 1409024, "Sony", "XCD-SX910CR" ,0 },
  6263. { 2818048, "Sony", "XCD-SX910CR" ,0 },
  6264. { 3884928, "Micron", "2010" ,0 },
  6265. { 6624000, "Pixelink", "A782" ,0 },
  6266. { 13248000, "Pixelink", "A782" ,0 },
  6267. { 6291456, "RoverShot","3320AF" ,0 },
  6268. { 6553440, "Canon", "PowerShot A460" ,0 },
  6269. { 6653280, "Canon", "PowerShot A530" ,0 },
  6270. { 6573120, "Canon", "PowerShot A610" ,0 },
  6271. { 9219600, "Canon", "PowerShot A620" ,0 },
  6272. { 9243240, "Canon", "PowerShot A470" ,0 },
  6273. { 10341600, "Canon", "PowerShot A720 IS" ,0 },
  6274. { 10383120, "Canon", "PowerShot A630" ,0 },
  6275. { 12945240, "Canon", "PowerShot A640" ,0 },
  6276. { 15636240, "Canon", "PowerShot A650" ,0 },
  6277. { 5298000, "Canon", "PowerShot SD300" ,0 },
  6278. { 7710960, "Canon", "PowerShot S3 IS" ,0 },
  6279. { 15467760, "Canon", "PowerShot SX110 IS",0 },
  6280. { 15534576, "Canon", "PowerShot SX120 IS",0 },
  6281. { 18653760, "Canon", "PowerShot SX20 IS",0 },
  6282. { 19131120, "Canon", "PowerShot SX220 HS",0 },
  6283. { 21936096, "Canon", "PowerShot SX30 IS",0 },
  6284. { 5939200, "OLYMPUS", "C770UZ" ,0 },
  6285. { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */
  6286. { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */
  6287. { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */
  6288. { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */
  6289. { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */
  6290. { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */
  6291. { 5865472, "NIKON", "E4500" ,1 },
  6292. { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */
  6293. { 8998912, "NIKON", "COOLPIX S6" ,1 },
  6294. { 1976352, "CASIO", "QV-2000UX" ,1 },
  6295. { 3217760, "CASIO", "QV-3*00EX" ,1 },
  6296. { 6218368, "CASIO", "QV-5700" ,1 },
  6297. { 6054400, "CASIO", "QV-R41" ,1 },
  6298. { 7530816, "CASIO", "QV-R51" ,1 },
  6299. { 7684000, "CASIO", "QV-4000" ,1 },
  6300. { 2937856, "CASIO", "EX-S20" ,1 },
  6301. { 4948608, "CASIO", "EX-S100" ,1 },
  6302. { 7542528, "CASIO", "EX-Z50" ,1 },
  6303. { 7562048, "CASIO", "EX-Z500" ,1 },
  6304. { 7753344, "CASIO", "EX-Z55" ,1 },
  6305. { 7816704, "CASIO", "EX-Z60" ,1 },
  6306. { 10843712, "CASIO", "EX-Z75" ,1 },
  6307. { 10834368, "CASIO", "EX-Z750" ,1 },
  6308. { 12310144, "CASIO", "EX-Z850" ,1 },
  6309. { 12489984, "CASIO", "EX-Z8" ,1 },
  6310. { 15499264, "CASIO", "EX-Z1050" ,1 },
  6311. { 18702336, "CASIO", "EX-ZR100" ,1 },
  6312. { 7426656, "CASIO", "EX-P505" ,1 },
  6313. { 9313536, "CASIO", "EX-P600" ,1 },
  6314. { 10979200, "CASIO", "EX-P700" ,1 },
  6315. { 3178560, "PENTAX", "Optio S" ,1 },
  6316. { 4841984, "PENTAX", "Optio S" ,1 },
  6317. { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */
  6318. { 10702848, "PENTAX", "Optio 750Z" ,1 },
  6319. { 15980544, "AGFAPHOTO","DC-833m" ,1 },
  6320. { 16098048, "SAMSUNG", "S85" ,1 },
  6321. { 16215552, "SAMSUNG", "S85" ,1 },
  6322. { 20487168, "SAMSUNG", "WB550" ,1 },
  6323. { 24000000, "SAMSUNG", "WB550" ,1 },
  6324. { 12582980, "Sinar", "" ,0 },
  6325. { 33292868, "Sinar", "" ,0 },
  6326. { 44390468, "Sinar", "" ,0 } };
  6327. static const char *l_Corporation[] =
  6328. { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
  6329. "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
  6330. "SAMSUNG", "Mamiya", "MOTOROLA", "LEICA" };
  6331. // Byte order of input file.
  6332. memset (m_Mask, 0, sizeof m_Mask);
  6333. m_ByteOrder = get2();
  6334. // Length of header.
  6335. l_HLen = get4();
  6336. /* m_BlackLevel = 0;
  6337. for (int k=0; k<4; k++) m_CBlackLevel[k]=0; TODO Mike */
  6338. // Length of file.
  6339. fseek (m_InputFile, 0, SEEK_SET);
  6340. ptfread (l_Head, 1, 32, m_InputFile);
  6341. fseek (m_InputFile, 0, SEEK_END);
  6342. l_FLen = l_FileSize = ftell(m_InputFile);
  6343. #pragma GCC diagnostic push
  6344. #pragma GCC diagnostic ignored "-Wwrite-strings"
  6345. if ((l_CharPointer = (char *) memmem (l_Head, 32, "MMMM", 4)) ||
  6346. (l_CharPointer = (char *) memmem (l_Head, 32, "IIII", 4))) {
  6347. #pragma GCC diagnostic pop
  6348. parse_phase_one (l_CharPointer-l_Head);
  6349. if ((l_CharPointer-l_Head) && parse_tiff(0)) apply_tiff();
  6350. } else if (m_ByteOrder == 0x4949 || m_ByteOrder == 0x4d4d) {
  6351. if (!memcmp (l_Head+6,"HEAPCCDR",8)) {
  6352. m_Data_Offset = l_HLen;
  6353. parse_ciff (l_HLen, l_FLen - l_HLen);
  6354. } else if (parse_tiff(0)) apply_tiff();
  6355. } else if (!memcmp (l_Head,"\xff\xd8\xff\xe1",4) &&
  6356. !memcmp (l_Head+6,"Exif",4)) {
  6357. fseek (m_InputFile, 4, SEEK_SET);
  6358. m_Data_Offset = 4 + get2();
  6359. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  6360. if (fgetc(m_InputFile) != 0xff)
  6361. parse_tiff(12);
  6362. m_ThumbOffset = 0;
  6363. } else if (!memcmp (l_Head+25,"ARECOYK",7)) {
  6364. strcpy (m_CameraMake, "Contax");
  6365. strcpy (m_CameraModel,"N Digital");
  6366. fseek (m_InputFile, 33, SEEK_SET);
  6367. get_timestamp(1);
  6368. fseek (m_InputFile, 60, SEEK_SET);
  6369. for (c=0; c < 4; c++) ASSIGN(m_CameraMultipliers[c ^ (c >> 1)], get4());
  6370. } else if (!strcmp (l_Head, "PXN")) {
  6371. strcpy (m_CameraMake, "Logitech");
  6372. strcpy (m_CameraModel,"Fotoman Pixtura");
  6373. } else if (!strcmp (l_Head, "qktk")) {
  6374. strcpy (m_CameraMake, "Apple");
  6375. strcpy (m_CameraModel,"QuickTake 100");
  6376. m_LoadRawFunction = &CLASS quicktake_100_load_raw;
  6377. } else if (!strcmp (l_Head, "qktn")) {
  6378. strcpy (m_CameraMake, "Apple");
  6379. strcpy (m_CameraModel,"QuickTake 150");
  6380. m_LoadRawFunction = &CLASS kodak_radc_load_raw;
  6381. } else if (!memcmp (l_Head,"FUJIFILM",8)) {
  6382. fseek (m_InputFile, 84, SEEK_SET);
  6383. m_ThumbOffset = get4();
  6384. m_ThumbLength = get4();
  6385. fseek (m_InputFile, 92, SEEK_SET);
  6386. parse_fuji (get4());
  6387. if (m_ThumbOffset > 120) {
  6388. fseek (m_InputFile, 120, SEEK_SET);
  6389. m_IsRaw += (i = get4());
  6390. if (m_IsRaw == 2 && m_UserSetting_ShotSelect)
  6391. parse_fuji (i);
  6392. }
  6393. m_LoadRawFunction = &CLASS unpacked_load_raw;
  6394. fseek (m_InputFile, 100+28*(m_UserSetting_ShotSelect > 0), SEEK_SET);
  6395. parse_tiff (m_Data_Offset = get4());
  6396. parse_tiff (m_ThumbOffset+12);
  6397. apply_tiff();
  6398. } else if (!memcmp (l_Head,"RIFF",4)) {
  6399. fseek (m_InputFile, 0, SEEK_SET);
  6400. parse_riff();
  6401. } else if (!memcmp (l_Head,"\0\001\0\001\0@",6)) {
  6402. fseek (m_InputFile, 6, SEEK_SET);
  6403. ptfread (m_CameraMake, 1, 8, m_InputFile);
  6404. ptfread (m_CameraModel, 1, 8, m_InputFile);
  6405. ptfread (m_CameraModelBis, 1, 16, m_InputFile);
  6406. m_Data_Offset = get2();
  6407. get2();
  6408. m_RawWidth = get2();
  6409. m_RawHeight = get2();
  6410. m_LoadRawFunction = &CLASS nokia_load_raw;
  6411. m_Filters = 0x61616161;
  6412. } else if (!memcmp (l_Head,"NOKIARAW",8)) {
  6413. strcpy (m_CameraMake, "NOKIA");
  6414. strcpy (m_CameraModel, "X2");
  6415. m_ByteOrder = 0x4949;
  6416. fseek (m_InputFile, 300, SEEK_SET);
  6417. m_Data_Offset = get4();
  6418. i = get4();
  6419. m_Width = get2();
  6420. m_Height = get2();
  6421. m_Data_Offset += i - m_Width * 5 / 4 * m_Height;
  6422. m_LoadRawFunction = &CLASS nokia_load_raw;
  6423. m_Filters = 0x61616161;
  6424. } else if (!memcmp (l_Head,"ARRI",4)) {
  6425. m_ByteOrder = 0x4949;
  6426. fseek (m_InputFile, 20, SEEK_SET);
  6427. m_Width = get4();
  6428. m_Height = get4();
  6429. strcpy (m_CameraMake, "ARRI");
  6430. fseek (m_InputFile, 668, SEEK_SET);
  6431. ptfread (m_CameraModel, 1, 64, m_InputFile);
  6432. m_Data_Offset = 4096;
  6433. m_LoadRawFunction = &CLASS packed_load_raw;
  6434. m_Load_Flags = 88;
  6435. m_Filters = 0x61616161;
  6436. } else if (!memcmp (l_Head+4,"RED1",4)) {
  6437. strcpy (m_CameraMake, "RED");
  6438. strcpy (m_CameraModel,"ONE");
  6439. parse_redcine();
  6440. m_LoadRawFunction = &CLASS redcine_load_raw;
  6441. gamma_curve (1/2.4, 12.92, 1, 4095);
  6442. m_Filters = 0x49494949;
  6443. } else if (!memcmp (l_Head,"DSC-Image",9))
  6444. parse_rollei();
  6445. else if (!memcmp (l_Head,"PWAD",4))
  6446. parse_sinar_ia();
  6447. else if (!memcmp (l_Head,"\0MRM",4))
  6448. parse_minolta(0);
  6449. else if (!memcmp (l_Head,"FOVb",4))
  6450. parse_foveon();
  6451. else if (!memcmp (l_Head,"CI",2))
  6452. parse_cine();
  6453. else {
  6454. for (zero_fsize=i=0; i < sizeof l_Table / sizeof *l_Table; i++)
  6455. if (l_FileSize == (unsigned) l_Table[i].fsize) {
  6456. strcpy (m_CameraMake, l_Table[i].make );
  6457. strcpy (m_CameraModel, l_Table[i].model);
  6458. if (l_Table[i].withjpeg)
  6459. parse_external_jpeg();
  6460. }
  6461. }
  6462. if (zero_fsize) l_FileSize = 0;
  6463. if (m_CameraMake[0] == 0) parse_smal (0, l_FLen);
  6464. if (m_CameraMake[0] == 0) parse_jpeg (m_IsRaw = 0);
  6465. for (i=0; i < sizeof l_Corporation / sizeof *l_Corporation; i++)
  6466. if (strstr (m_CameraMake, l_Corporation[i])) /* Simplify company names */
  6467. strcpy (m_CameraMake, l_Corporation[i]);
  6468. if (!strncmp (m_CameraMake,"KODAK",5) &&
  6469. ((l_CharPointer = strstr(m_CameraModel," DIGITAL CAMERA")) ||
  6470. (l_CharPointer = strstr(m_CameraModel," Digital Camera")) ||
  6471. (l_CharPointer = strstr(m_CameraModel,"FILE VERSION"))))
  6472. *l_CharPointer = 0;
  6473. l_CharPointer = m_CameraMake + strlen(m_CameraMake); /* Remove trailing spaces */
  6474. while (*--l_CharPointer == ' ') *l_CharPointer = 0;
  6475. l_CharPointer = m_CameraModel + strlen(m_CameraModel);
  6476. while (*--l_CharPointer == ' ') *l_CharPointer = 0;
  6477. i = strlen(m_CameraMake); /* Remove make from model */
  6478. if (!strncasecmp (m_CameraModel, m_CameraMake, i) && m_CameraModel[i++] == ' ')
  6479. memmove (m_CameraModel, m_CameraModel+i, 64-i);
  6480. if (!strncmp (m_CameraModel,"FinePix ",8))
  6481. strcpy (m_CameraModel, m_CameraModel+8);
  6482. if (!strncmp (m_CameraModel,"Digital Camera ",15))
  6483. strcpy (m_CameraModel, m_CameraModel+15);
  6484. m_Description[511] = m_Artist[63] = m_CameraMake[63] = m_CameraModel[63] = m_CameraModelBis[63] = 0;
  6485. if (!m_IsRaw) goto notraw;
  6486. if (!m_Height) m_Height = m_RawHeight;
  6487. if (!m_Width) m_Width = m_RawWidth;
  6488. if (m_Height == 2624 && m_Width == 3936) /* Pentax K10D and Samsung GX10 */
  6489. { m_Height = 2616; m_Width = 3896; }
  6490. if (m_Height == 3136 && m_Width == 4864) /* Pentax K20D and Samsung GX20 */
  6491. { m_Height = 3124; m_Width = 4688; m_Filters = 0x16161616; }
  6492. if (m_Width == 4352 && (!strcmp(m_CameraModel,"K-r") || !strcmp(m_CameraModel,"K-x")))
  6493. { m_Width = 4309; m_Filters = 0x16161616; }
  6494. if (m_Width >= 4960 && !strncmp(m_CameraModel,"K-5",3))
  6495. { m_LeftMargin = 10; m_Width = 4950; m_Filters = 0x16161616; }
  6496. if (m_Width == 4736 && !strcmp(m_CameraModel,"K-7"))
  6497. { m_Height = 3122; m_Width = 4684; m_Filters = 0x16161616; m_TopMargin = 2; }
  6498. if (m_Width == 7424 && !strcmp(m_CameraModel,"645D"))
  6499. { m_Height = 5502; m_Width = 7328; m_Filters = 0x61616161; m_TopMargin = 29;
  6500. m_LeftMargin = 48; }
  6501. if (m_Height == 3014 && m_Width == 4096) /* Ricoh GX200 */
  6502. m_Width = 4014;
  6503. if (m_DNG_Version) {
  6504. if (m_Filters == UINT_MAX) m_Filters = 0;
  6505. if (m_Filters) m_IsRaw = m_Tiff_Samples;
  6506. else m_Colors = m_Tiff_Samples;
  6507. if (m_Tiff_Compress == 1)
  6508. m_LoadRawFunction = &CLASS packed_dng_load_raw;
  6509. if (m_Tiff_Compress == 7)
  6510. m_LoadRawFunction = &CLASS lossless_dng_load_raw;
  6511. goto dng_skip;
  6512. }
  6513. if ((l_IsCanon = !strcmp(m_CameraMake,"Canon"))) {
  6514. m_LoadRawFunction = memcmp (l_Head+6,"HEAPCCDR",8) ?
  6515. &CLASS lossless_jpeg_load_raw : &CLASS canon_load_raw;
  6516. }
  6517. if (!strcmp(m_CameraMake,"NIKON")) {
  6518. if (!m_LoadRawFunction)
  6519. m_LoadRawFunction = &CLASS packed_load_raw;
  6520. if (m_CameraModel[0] == 'E')
  6521. m_Load_Flags |= !m_Data_Offset << 2 | 2;
  6522. }
  6523. if (!strcmp(m_CameraMake,"CASIO")) {
  6524. m_LoadRawFunction = &CLASS packed_load_raw;
  6525. m_WhiteLevel = 0xf7f;
  6526. }
  6527. /* Set parameters based on camera name (for non-DNG files). */
  6528. if (m_IsFoveon) {
  6529. if (m_Height*2 < m_Width) m_PixelAspect = 0.5;
  6530. if (m_Height > m_Width) m_PixelAspect = 2;
  6531. m_Filters = 0;
  6532. simple_coeff(0);
  6533. } else if (l_IsCanon && m_Tiff_bps == 15) {
  6534. switch (m_Width) {
  6535. case 3344: m_Width -= 66;
  6536. case 3872: m_Width -= 6;
  6537. }
  6538. if (m_Height > m_Width) SWAP(m_Height,m_Width);
  6539. m_Filters = 0;
  6540. m_LoadRawFunction = &CLASS canon_sraw_load_raw;
  6541. } else if (!strcmp(m_CameraModel,"PowerShot 600")) {
  6542. m_Height = 613;
  6543. m_Width = 854;
  6544. m_RawWidth = 896;
  6545. m_PixelAspect = 607/628.0;
  6546. m_Colors = 4;
  6547. m_Filters = 0xe1e4e1e4;
  6548. m_LoadRawFunction = &CLASS canon_600_load_raw;
  6549. } else if (!strcmp(m_CameraModel,"PowerShot A5") ||
  6550. !strcmp(m_CameraModel,"PowerShot A5 Zoom")) {
  6551. m_Height = 773;
  6552. m_Width = 960;
  6553. m_RawWidth = 992;
  6554. m_PixelAspect = 256/235.0;
  6555. m_Colors = 4;
  6556. m_Filters = 0x1e4e1e4e;
  6557. goto canon_a5;
  6558. } else if (!strcmp(m_CameraModel,"PowerShot A50")) {
  6559. m_Height = 968;
  6560. m_Width = 1290;
  6561. m_RawWidth = 1320;
  6562. m_Colors = 4;
  6563. m_Filters = 0x1b4e4b1e;
  6564. goto canon_a5;
  6565. } else if (!strcmp(m_CameraModel,"PowerShot Pro70")) {
  6566. m_Height = 1024;
  6567. m_Width = 1552;
  6568. m_Colors = 4;
  6569. m_Filters = 0x1e4b4e1b;
  6570. goto canon_a5;
  6571. } else if (!strcmp(m_CameraModel,"PowerShot SD300")) {
  6572. m_Height = 1752;
  6573. m_Width = 2344;
  6574. m_RawHeight = 1766;
  6575. m_RawWidth = 2400;
  6576. m_TopMargin = 12;
  6577. m_LeftMargin = 12;
  6578. goto canon_a5;
  6579. } else if (!strcmp(m_CameraModel,"PowerShot A460")) {
  6580. m_Height = 1960;
  6581. m_Width = 2616;
  6582. m_RawHeight = 1968;
  6583. m_RawWidth = 2664;
  6584. m_TopMargin = 4;
  6585. m_LeftMargin = 4;
  6586. goto canon_a5;
  6587. } else if (!strcmp(m_CameraModel,"PowerShot A530")) {
  6588. m_Height = 1984;
  6589. m_Width = 2620;
  6590. m_RawHeight = 1992;
  6591. m_RawWidth = 2672;
  6592. m_TopMargin = 6;
  6593. m_LeftMargin = 10;
  6594. goto canon_a5;
  6595. } else if (!strcmp(m_CameraModel,"PowerShot A610")) {
  6596. if (canon_s2is()) strcpy (m_CameraModel+10, "S2 IS");
  6597. m_Height = 1960;
  6598. m_Width = 2616;
  6599. m_RawHeight = 1968;
  6600. m_RawWidth = 2672;
  6601. m_TopMargin = 8;
  6602. m_LeftMargin = 12;
  6603. goto canon_a5;
  6604. } else if (!strcmp(m_CameraModel,"PowerShot A620")) {
  6605. m_Height = 2328;
  6606. m_Width = 3112;
  6607. m_RawHeight = 2340;
  6608. m_RawWidth = 3152;
  6609. m_TopMargin = 12;
  6610. m_LeftMargin = 36;
  6611. goto canon_a5;
  6612. } else if (!strcmp(m_CameraModel,"PowerShot A470")) {
  6613. m_Height = 2328;
  6614. m_Width = 3096;
  6615. m_RawHeight = 2346;
  6616. m_RawWidth = 3152;
  6617. m_TopMargin = 6;
  6618. m_LeftMargin = 12;
  6619. goto canon_a5;
  6620. } else if (!strcmp(m_CameraModel,"PowerShot A720 IS")) {
  6621. m_Height = 2472;
  6622. m_Width = 3298;
  6623. m_RawHeight = 2480;
  6624. m_RawWidth = 3336;
  6625. m_TopMargin = 5;
  6626. m_LeftMargin = 6;
  6627. goto canon_a5;
  6628. } else if (!strcmp(m_CameraModel,"PowerShot A630")) {
  6629. m_Height = 2472;
  6630. m_Width = 3288;
  6631. m_RawHeight = 2484;
  6632. m_RawWidth = 3344;
  6633. m_TopMargin = 6;
  6634. m_LeftMargin = 12;
  6635. goto canon_a5;
  6636. } else if (!strcmp(m_CameraModel,"PowerShot A640")) {
  6637. m_Height = 2760;
  6638. m_Width = 3672;
  6639. m_RawHeight = 2772;
  6640. m_RawWidth = 3736;
  6641. m_TopMargin = 6;
  6642. m_LeftMargin = 12;
  6643. goto canon_a5;
  6644. } else if (!strcmp(m_CameraModel,"PowerShot A650")) {
  6645. m_Height = 3024;
  6646. m_Width = 4032;
  6647. m_RawHeight = 3048;
  6648. m_RawWidth = 4104;
  6649. m_TopMargin = 12;
  6650. m_LeftMargin = 48;
  6651. goto canon_a5;
  6652. } else if (!strcmp(m_CameraModel,"PowerShot S3 IS")) {
  6653. m_Height = 2128;
  6654. m_Width = 2840;
  6655. m_RawHeight = 2136;
  6656. m_RawWidth = 2888;
  6657. m_TopMargin = 8;
  6658. m_LeftMargin = 44;
  6659. canon_a5:
  6660. m_Tiff_bps = 10;
  6661. m_LoadRawFunction = &CLASS packed_load_raw;
  6662. m_Load_Flags = 40;
  6663. if (m_RawWidth > 1600) m_ZeroIsBad = 1;
  6664. } else if (!strcmp(m_CameraModel,"PowerShot SX110 IS")) {
  6665. m_Height = 2760;
  6666. m_Width = 3684;
  6667. m_RawHeight = 2772;
  6668. m_RawWidth = 3720;
  6669. m_TopMargin = 12;
  6670. m_LeftMargin = 6;
  6671. m_LoadRawFunction = &CLASS packed_load_raw;
  6672. m_Load_Flags = 40;
  6673. m_ZeroIsBad = 1;
  6674. } else if (!strcmp(m_CameraModel,"PowerShot SX120 IS")) {
  6675. m_Height = 2742;
  6676. m_Width = 3664;
  6677. m_RawHeight = 2778;
  6678. m_RawWidth = 3728;
  6679. m_TopMargin = 18;
  6680. m_LeftMargin = 16;
  6681. m_Filters = 0x49494949;
  6682. m_LoadRawFunction = &CLASS packed_load_raw;
  6683. m_Load_Flags = 40;
  6684. m_ZeroIsBad = 1;
  6685. } else if (!strcmp(m_CameraModel,"PowerShot SX20 IS")) {
  6686. m_Height = 3024;
  6687. m_Width = 4032;
  6688. m_RawHeight = 3048;
  6689. m_RawWidth = 4080;
  6690. m_TopMargin = 12;
  6691. m_LeftMargin = 24;
  6692. m_LoadRawFunction = &CLASS packed_load_raw;
  6693. m_Load_Flags = 40;
  6694. m_ZeroIsBad = 1;
  6695. } else if (!strcmp(m_CameraModel,"PowerShot SX220 HS")) {
  6696. m_Height = 3043;
  6697. m_Width = 4072;
  6698. m_RawHeight = 3060;
  6699. m_RawWidth = 4168;
  6700. m_Mask[0][0] = m_TopMargin = 16;
  6701. m_Mask[0][2] = m_TopMargin + m_Height;
  6702. m_Mask[0][3] = m_LeftMargin = 92;
  6703. m_LoadRawFunction = &CLASS packed_load_raw;
  6704. m_Load_Flags = 8;
  6705. m_ZeroIsBad = 1;
  6706. } else if (!strcmp(m_CameraModel,"PowerShot SX30 IS")) {
  6707. m_Height = 3254;
  6708. m_Width = 4366;
  6709. m_RawHeight = 3276;
  6710. m_RawWidth = 4464;
  6711. m_TopMargin = 10;
  6712. m_LeftMargin = 25;
  6713. m_Filters = 0x16161616;
  6714. m_LoadRawFunction = &CLASS packed_load_raw;
  6715. m_Load_Flags = 40;
  6716. m_ZeroIsBad = 1;
  6717. } else if (!strcmp(m_CameraModel,"PowerShot Pro90 IS")) {
  6718. m_Width = 1896;
  6719. m_Colors = 4;
  6720. m_Filters = 0xb4b4b4b4;
  6721. } else if (l_IsCanon && m_RawWidth == 2144) {
  6722. m_Height = 1550;
  6723. m_Width = 2088;
  6724. m_TopMargin = 8;
  6725. m_LeftMargin = 4;
  6726. if (!strcmp(m_CameraModel,"PowerShot G1")) {
  6727. m_Colors = 4;
  6728. m_Filters = 0xb4b4b4b4;
  6729. }
  6730. } else if (l_IsCanon && m_RawWidth == 2224) {
  6731. m_Height = 1448;
  6732. m_Width = 2176;
  6733. m_TopMargin = 6;
  6734. m_LeftMargin = 48;
  6735. } else if (l_IsCanon && m_RawWidth == 2376) {
  6736. m_Height = 1720;
  6737. m_Width = 2312;
  6738. m_TopMargin = 6;
  6739. m_LeftMargin = 12;
  6740. } else if (l_IsCanon && m_RawWidth == 2672) {
  6741. m_Height = 1960;
  6742. m_Width = 2616;
  6743. m_TopMargin = 6;
  6744. m_LeftMargin = 12;
  6745. } else if (l_IsCanon && m_RawWidth == 3152) {
  6746. m_Height = 2056;
  6747. m_Width = 3088;
  6748. m_TopMargin = 12;
  6749. m_LeftMargin = 64;
  6750. if (unique_id == 0x80000170)
  6751. adobe_coeff ("Canon","EOS 300D");
  6752. } else if (l_IsCanon && m_RawWidth == 3160) {
  6753. m_Height = 2328;
  6754. m_Width = 3112;
  6755. m_TopMargin = 12;
  6756. m_LeftMargin = 44;
  6757. } else if (l_IsCanon && m_RawWidth == 3344) {
  6758. m_Height = 2472;
  6759. m_Width = 3288;
  6760. m_TopMargin = 6;
  6761. m_LeftMargin = 4;
  6762. } else if (!strcmp(m_CameraModel,"EOS D2000C")) {
  6763. m_Filters = 0x61616161;
  6764. m_BlackLevel = m_Curve[200];
  6765. } else if (l_IsCanon && m_RawWidth == 3516) {
  6766. m_TopMargin = 14;
  6767. m_LeftMargin = 42;
  6768. if (unique_id == 0x80000189)
  6769. adobe_coeff ("Canon","EOS 350D");
  6770. goto canon_cr2;
  6771. } else if (l_IsCanon && m_RawWidth == 3596) {
  6772. m_TopMargin = 12;
  6773. m_LeftMargin = 74;
  6774. goto canon_cr2;
  6775. } else if (l_IsCanon && m_RawWidth == 3744) {
  6776. m_Height = 2760;
  6777. m_Width = 3684;
  6778. m_TopMargin = 16;
  6779. m_LeftMargin = 8;
  6780. if (unique_id > 0x2720000) {
  6781. m_TopMargin = 12;
  6782. m_LeftMargin = 52;
  6783. }
  6784. } else if (l_IsCanon && m_RawWidth == 3944) {
  6785. m_Height = 2602;
  6786. m_Width = 3908;
  6787. m_TopMargin = 18;
  6788. m_LeftMargin = 30;
  6789. } else if (l_IsCanon && m_RawWidth == 3948) {
  6790. m_TopMargin = 18;
  6791. m_LeftMargin = 42;
  6792. m_Height -= 2;
  6793. if (unique_id == 0x80000236)
  6794. adobe_coeff ("Canon","EOS 400D");
  6795. if (unique_id == 0x80000254)
  6796. adobe_coeff ("Canon","EOS 1000D");
  6797. goto canon_cr2;
  6798. } else if (l_IsCanon && m_RawWidth == 3984) {
  6799. m_TopMargin = 20;
  6800. m_LeftMargin = 76;
  6801. m_Height -= 2;
  6802. goto canon_cr2;
  6803. } else if (l_IsCanon && m_RawWidth == 4104) {
  6804. m_Height = 3024;
  6805. m_Width = 4032;
  6806. m_TopMargin = 12;
  6807. m_LeftMargin = 48;
  6808. } else if (l_IsCanon && m_RawWidth == 4152) {
  6809. m_TopMargin = 12;
  6810. m_LeftMargin = 192;
  6811. goto canon_cr2;
  6812. } else if (l_IsCanon && m_RawWidth == 4160) {
  6813. m_Height = 3048;
  6814. m_Width = 4048;
  6815. m_TopMargin = 11;
  6816. m_LeftMargin = 104;
  6817. } else if (l_IsCanon && m_RawWidth == 4176) {
  6818. m_Height = 3045;
  6819. m_Width = 4072;
  6820. m_LeftMargin = 96;
  6821. m_Mask[0][0] = m_TopMargin = 17;
  6822. m_Mask[0][2] = m_RawHeight;
  6823. m_Mask[0][3] = 80;
  6824. m_Filters = 0x49494949;
  6825. } else if (l_IsCanon && m_RawWidth == 4312) {
  6826. m_TopMargin = 18;
  6827. m_LeftMargin = 22;
  6828. m_Height -= 2;
  6829. if (unique_id == 0x80000176)
  6830. adobe_coeff ("Canon","EOS 450D");
  6831. goto canon_cr2;
  6832. } else if (l_IsCanon && m_RawWidth == 4352) {
  6833. m_TopMargin = 18;
  6834. m_LeftMargin = 62;
  6835. if (unique_id == 0x80000288)
  6836. adobe_coeff ("Canon","EOS 1100D");
  6837. goto canon_cr2;
  6838. } else if (l_IsCanon && m_RawWidth == 4476) {
  6839. m_TopMargin = 34;
  6840. m_LeftMargin = 90;
  6841. goto canon_cr2;
  6842. } else if (l_IsCanon && m_RawWidth == 4480) {
  6843. m_Height = 3326;
  6844. m_Width = 4432;
  6845. m_TopMargin = 10;
  6846. m_LeftMargin = 12;
  6847. m_Filters = 0x49494949;
  6848. } else if (l_IsCanon && m_RawWidth == 4496) {
  6849. m_Height = 3316;
  6850. m_Width = 4404;
  6851. m_TopMargin = 50;
  6852. m_LeftMargin = 80;
  6853. } else if (l_IsCanon && m_RawWidth == 4832) {
  6854. m_TopMargin = unique_id == 0x80000261 ? 51:26;
  6855. m_LeftMargin = 62;
  6856. if (unique_id == 0x80000252)
  6857. adobe_coeff ("Canon","EOS 500D");
  6858. goto canon_cr2;
  6859. } else if (l_IsCanon && m_RawWidth == 5108) {
  6860. m_TopMargin = 13;
  6861. m_LeftMargin = 98;
  6862. goto canon_cr2;
  6863. } else if (l_IsCanon && m_RawWidth == 5120) {
  6864. m_Height -= m_TopMargin = 45;
  6865. m_LeftMargin = 142;
  6866. m_Width = 4916;
  6867. } else if (l_IsCanon && m_RawWidth == 5280) {
  6868. m_TopMargin = 52;
  6869. m_LeftMargin = 72;
  6870. if (unique_id == 0x80000301)
  6871. adobe_coeff ("Canon","EOS 650D");
  6872. goto canon_cr2;
  6873. } else if (l_IsCanon && m_RawWidth == 5344) {
  6874. m_TopMargin = 51;
  6875. m_LeftMargin = 142;
  6876. if (unique_id == 0x80000269) {
  6877. m_TopMargin = 100;
  6878. m_LeftMargin = 126;
  6879. m_Height -= 2;
  6880. adobe_coeff ("Canon","EOS-1D X");
  6881. }
  6882. if (unique_id == 0x80000270)
  6883. adobe_coeff ("Canon","EOS 550D");
  6884. if (unique_id == 0x80000286)
  6885. adobe_coeff ("Canon","EOS 600D");
  6886. goto canon_cr2;
  6887. } else if (l_IsCanon && m_RawWidth == 5360) {
  6888. m_TopMargin = 51;
  6889. m_LeftMargin = 158;
  6890. goto canon_cr2;
  6891. } else if (l_IsCanon && m_RawWidth == 5568) {
  6892. m_TopMargin = 38;
  6893. m_LeftMargin = 72;
  6894. goto canon_cr2;
  6895. } else if (l_IsCanon && m_RawWidth == 5712) {
  6896. m_Height = 3752;
  6897. m_Width = 5640;
  6898. m_TopMargin = 20;
  6899. m_LeftMargin = 62;
  6900. } else if (l_IsCanon && m_RawWidth == 5792) {
  6901. m_TopMargin = 51;
  6902. m_LeftMargin = 158;
  6903. canon_cr2:
  6904. m_Height -= m_TopMargin;
  6905. m_Width -= m_LeftMargin;
  6906. } else if (l_IsCanon && m_RawWidth == 5920) {
  6907. m_Height = 3870;
  6908. m_Width = 5796;
  6909. m_TopMargin = 80;
  6910. m_LeftMargin = 122;
  6911. } else if (!strcmp(m_CameraModel,"D1")) {
  6912. ASSIGN(m_CameraMultipliers[0],VALUE(m_CameraMultipliers[0]) * 256/527.0);
  6913. ASSIGN(m_CameraMultipliers[2],VALUE(m_CameraMultipliers[2]) * 256/317.0);
  6914. } else if (!strcmp(m_CameraModel,"D1X")) {
  6915. m_Width -= 4;
  6916. m_PixelAspect = 0.5;
  6917. } else if (!strcmp(m_CameraModel,"D40X") ||
  6918. !strcmp(m_CameraModel,"D60") ||
  6919. !strcmp(m_CameraModel,"D80") ||
  6920. !strcmp(m_CameraModel,"D3000")) {
  6921. m_Height -= 3;
  6922. m_Width -= 4;
  6923. } else if (!strcmp(m_CameraModel,"D3") ||
  6924. !strcmp(m_CameraModel,"D3S") ||
  6925. !strcmp(m_CameraModel,"D700")) {
  6926. m_Width -= 4;
  6927. m_LeftMargin = 2;
  6928. } else if (!strcmp(m_CameraModel,"D3100")) {
  6929. m_Width -= 28;
  6930. m_LeftMargin = 6;
  6931. } else if (!strcmp(m_CameraModel,"D5000") ||
  6932. !strcmp(m_CameraModel,"D90")) {
  6933. m_Width -= 42;
  6934. } else if (!strcmp(m_CameraModel,"D5100") ||
  6935. !strcmp(m_CameraModel,"D7000")) {
  6936. m_Width -= 44;
  6937. } else if (!strcmp(m_CameraModel,"D3200") ||
  6938. !strcmp(m_CameraModel,"D600") ||
  6939. !strcmp(m_CameraModel,"D800")) {
  6940. m_Width -= 46;
  6941. } else if (!strcmp(m_CameraModel,"D4")) {
  6942. m_Width -= 52;
  6943. m_LeftMargin = 2;
  6944. } else if (!strncmp(m_CameraModel,"D40",3) ||
  6945. !strncmp(m_CameraModel,"D50",3) ||
  6946. !strncmp(m_CameraModel,"D70",3)) {
  6947. m_Width--;
  6948. } else if (!strcmp(m_CameraModel,"D100")) {
  6949. if (m_Load_Flags)
  6950. m_RawWidth = (m_Width += 3) + 3;
  6951. } else if (!strcmp(m_CameraModel,"D200")) {
  6952. m_LeftMargin = 1;
  6953. m_Width -= 4;
  6954. m_Filters = 0x94949494;
  6955. } else if (!strncmp(m_CameraModel,"D2H",3)) {
  6956. m_LeftMargin = 6;
  6957. m_Width -= 14;
  6958. } else if (!strncmp(m_CameraModel,"D2X",3)) {
  6959. if (m_Width == 3264) m_Width -= 32;
  6960. else m_Width -= 8;
  6961. } else if (!strncmp(m_CameraModel,"D300",4)) {
  6962. m_Width -= 32;
  6963. } else if (!strcmp(m_CameraMake,"NIKON") && m_RawWidth == 4032) {
  6964. adobe_coeff ("NIKON","COOLPIX P7700");
  6965. } else if (!strncmp(m_CameraModel,"COOLPIX P",9)) {
  6966. m_Load_Flags = 24;
  6967. m_Filters = 0x94949494;
  6968. if (m_CameraModel[9] == '7' && m_IsoSpeed >= 400)
  6969. m_BlackLevel = 255;
  6970. } else if (!strncmp(m_CameraModel,"1 ",2)) {
  6971. m_Height -= 2;
  6972. } else if (l_FileSize == 1581060) {
  6973. m_Height = 963;
  6974. m_Width = 1287;
  6975. m_RawWidth = 1632;
  6976. m_WhiteLevel = 0x3f4;
  6977. m_Colors = 4;
  6978. m_Filters = 0x1e1e1e1e;
  6979. simple_coeff(3);
  6980. ASSIGN(m_D65Multipliers[0], 1.2085);
  6981. ASSIGN(m_D65Multipliers[1], 1.0943);
  6982. ASSIGN(m_D65Multipliers[3], 1.1103);
  6983. goto e900;
  6984. } else if (l_FileSize == 2465792) {
  6985. m_Height = 1203;
  6986. m_Width = 1616;
  6987. m_RawWidth = 2048;
  6988. m_Colors = 4;
  6989. m_Filters = 0x4b4b4b4b;
  6990. adobe_coeff ("NIKON","E950");
  6991. e900:
  6992. m_Tiff_bps = 10;
  6993. m_LoadRawFunction = &CLASS packed_load_raw;
  6994. m_Load_Flags = 6;
  6995. } else if (l_FileSize == 4771840) {
  6996. m_Height = 1540;
  6997. m_Width = 2064;
  6998. m_Colors = 4;
  6999. m_Filters = 0xe1e1e1e1;
  7000. m_LoadRawFunction = &CLASS packed_load_raw;
  7001. m_Load_Flags = 6;
  7002. if (!m_TimeStamp && nikon_e995())
  7003. strcpy (m_CameraModel, "E995");
  7004. if (strcmp(m_CameraModel,"E995")) {
  7005. m_Filters = 0xb4b4b4b4;
  7006. simple_coeff(3);
  7007. ASSIGN(m_D65Multipliers[0], 1.196);
  7008. ASSIGN(m_D65Multipliers[1], 1.246);
  7009. ASSIGN(m_D65Multipliers[2], 1.018);
  7010. }
  7011. } else if (!strcmp(m_CameraModel,"E2100")) {
  7012. if (!m_TimeStamp && !nikon_e2100()) goto cp_e2500;
  7013. m_Height = 1206;
  7014. m_Width = 1616;
  7015. m_Load_Flags = 30;
  7016. } else if (!strcmp(m_CameraModel,"E2500")) {
  7017. cp_e2500:
  7018. strcpy (m_CameraModel, "E2500");
  7019. m_Height = 1204;
  7020. m_Width = 1616;
  7021. m_Colors = 4;
  7022. m_Filters = 0x4b4b4b4b;
  7023. } else if (l_FileSize == 4775936) {
  7024. m_Height = 1542;
  7025. m_Width = 2064;
  7026. m_LoadRawFunction = &CLASS packed_load_raw;
  7027. m_Load_Flags = 30;
  7028. if (!m_TimeStamp) nikon_3700();
  7029. if (m_CameraModel[0] == 'E' && atoi(m_CameraModel+1) < 3700)
  7030. m_Filters = 0x49494949;
  7031. if (!strcmp(m_CameraModel,"Optio 33WR")) {
  7032. m_Flip = 1;
  7033. m_Filters = 0x16161616;
  7034. }
  7035. if (m_CameraMake[0] == 'O') {
  7036. int li = find_green (12, 32, 1188864, 3576832);
  7037. int lc = find_green (12, 32, 2383920, 2387016);
  7038. if (abs(li) < abs(lc)) {
  7039. SWAP(li,lc);
  7040. m_Load_Flags = 24;
  7041. }
  7042. if (li < 0) m_Filters = 0x61616161;
  7043. }
  7044. } else if (l_FileSize == 5869568) {
  7045. m_Height = 1710;
  7046. m_Width = 2288;
  7047. m_Filters = 0x16161616;
  7048. if (!m_TimeStamp && minolta_z2()) {
  7049. strcpy (m_CameraMake, "Minolta");
  7050. strcpy (m_CameraModel,"DiMAGE Z2");
  7051. }
  7052. m_LoadRawFunction = &CLASS packed_load_raw;
  7053. m_Load_Flags = 6 + 24 * (m_CameraMake[0] == 'M');
  7054. } else if (!strcmp(m_CameraModel,"E4500")) {
  7055. m_Height = 1708;
  7056. m_Width = 2288;
  7057. m_Colors = 4;
  7058. m_Filters = 0xb4b4b4b4;
  7059. } else if (l_FileSize == 7438336) {
  7060. m_Height = 1924;
  7061. m_Width = 2576;
  7062. m_Colors = 4;
  7063. m_Filters = 0xb4b4b4b4;
  7064. } else if (l_FileSize == 8998912) {
  7065. m_Height = 2118;
  7066. m_Width = 2832;
  7067. m_WhiteLevel = 0xf83;
  7068. m_LoadRawFunction = &CLASS packed_load_raw;
  7069. m_Load_Flags = 30;
  7070. } else if (!strcmp(m_CameraMake,"FUJIFILM")) {
  7071. if (!strcmp(m_CameraModel+7,"S2Pro")) {
  7072. strcpy (m_CameraModel,"S2Pro");
  7073. m_Height = 2144;
  7074. m_Width = 2880;
  7075. m_Flip = 6;
  7076. } else if (m_LoadRawFunction != &CLASS packed_load_raw)
  7077. m_WhiteLevel = (m_IsRaw == 2 && m_UserSetting_ShotSelect) ? 0x2f00 : 0x3e00;
  7078. m_TopMargin = (m_RawHeight - m_Height) >> 2 << 1;
  7079. m_LeftMargin = (m_RawWidth - m_Width ) >> 2 << 1;
  7080. if (m_Width == 2848) m_Filters = 0x16161616;
  7081. if (m_Width == 3328) {
  7082. m_Width = 3262;
  7083. m_LeftMargin = 34;
  7084. }
  7085. if (m_Width == 4952) {
  7086. m_LeftMargin = 0;
  7087. m_Filters = 2;
  7088. }
  7089. if (fuji_layout) m_RawWidth *= m_IsRaw;
  7090. } else if (!strcmp(m_CameraModel,"RD175")) {
  7091. m_Height = 986;
  7092. m_Width = 1534;
  7093. m_Data_Offset = 513;
  7094. m_Filters = 0x61616161;
  7095. m_LoadRawFunction = &CLASS minolta_rd175_load_raw;
  7096. } else if (!strcmp(m_CameraModel,"KD-400Z")) {
  7097. m_Height = 1712;
  7098. m_Width = 2312;
  7099. m_RawWidth = 2336;
  7100. goto konica_400z;
  7101. } else if (!strcmp(m_CameraModel,"KD-510Z")) {
  7102. goto konica_510z;
  7103. } else if (!strcasecmp(m_CameraMake,"MINOLTA")) {
  7104. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7105. m_WhiteLevel = 0xfff;
  7106. if (!strncmp(m_CameraModel,"DiMAGE A",8)) {
  7107. if (!strcmp(m_CameraModel,"DiMAGE A200"))
  7108. m_Filters = 0x49494949;
  7109. m_Tiff_bps = 12;
  7110. m_LoadRawFunction = &CLASS packed_load_raw;
  7111. } else if (!strncmp(m_CameraModel,"ALPHA",5) ||
  7112. !strncmp(m_CameraModel,"DYNAX",5) ||
  7113. !strncmp(m_CameraModel,"MAXXUM",6)) {
  7114. sprintf (m_CameraModel+20, "DYNAX %-10s", m_CameraModel+6+(m_CameraModel[0]=='M'));
  7115. adobe_coeff (m_CameraMake, m_CameraModel+20);
  7116. m_LoadRawFunction = &CLASS packed_load_raw;
  7117. } else if (!strncmp(m_CameraModel,"DiMAGE G",8)) {
  7118. if (m_CameraModel[8] == '4') {
  7119. m_Height = 1716;
  7120. m_Width = 2304;
  7121. } else if (m_CameraModel[8] == '5') {
  7122. konica_510z:
  7123. m_Height = 1956;
  7124. m_Width = 2607;
  7125. m_RawWidth = 2624;
  7126. } else if (m_CameraModel[8] == '6') {
  7127. m_Height = 2136;
  7128. m_Width = 2848;
  7129. }
  7130. m_Data_Offset += 14;
  7131. m_Filters = 0x61616161;
  7132. konica_400z:
  7133. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7134. m_WhiteLevel = 0x3df;
  7135. m_ByteOrder = 0x4d4d;
  7136. }
  7137. } else if (!strcmp(m_CameraModel,"*ist D")) {
  7138. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7139. data_error = -1;
  7140. } else if (!strcmp(m_CameraModel,"*ist DS")) {
  7141. m_Height -= 2;
  7142. } else if (!strcmp(m_CameraModel,"K-x")) {
  7143. m_Width = 4309;
  7144. m_Filters = 0x16161616;
  7145. } else if (!strcmp(m_CameraModel,"Optio S")) {
  7146. if (l_FileSize == 3178560) {
  7147. m_Height = 1540;
  7148. m_Width = 2064;
  7149. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7150. ASSIGN(m_CameraMultipliers[0],VALUE(m_CameraMultipliers[0]) * 4);
  7151. ASSIGN(m_CameraMultipliers[2],VALUE(m_CameraMultipliers[2]) * 4);
  7152. } else {
  7153. m_Height = 1544;
  7154. m_Width = 2068;
  7155. m_RawWidth = 3136;
  7156. m_LoadRawFunction = &CLASS packed_load_raw;
  7157. m_WhiteLevel = 0xf7c;
  7158. }
  7159. } else if (l_FileSize == 6114240) {
  7160. m_Height = 1737;
  7161. m_Width = 2324;
  7162. m_RawWidth = 3520;
  7163. m_LoadRawFunction = &CLASS packed_load_raw;
  7164. m_WhiteLevel = 0xf7a;
  7165. } else if (!strcmp(m_CameraModel,"Optio 750Z")) {
  7166. m_Height = 2302;
  7167. m_Width = 3072;
  7168. m_LoadRawFunction = &CLASS packed_load_raw;
  7169. m_Load_Flags = 30;
  7170. } else if (!strcmp(m_CameraModel,"DC-833m")) {
  7171. m_Height = 2448;
  7172. m_Width = 3264;
  7173. m_ByteOrder = 0x4949;
  7174. m_Filters = 0x61616161;
  7175. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7176. m_WhiteLevel = 0xfc00;
  7177. } else if (!strncmp(m_CameraModel,"S85",3)) {
  7178. m_Height = 2448;
  7179. m_Width = 3264;
  7180. m_RawWidth = l_FileSize/m_Height/2;
  7181. m_ByteOrder = 0x4d4d;
  7182. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7183. } else if (!strcmp(m_CameraMake,"SAMSUNG") && m_RawWidth == 4704) {
  7184. m_Height -= m_TopMargin = 8;
  7185. m_Width -= 2 * (m_LeftMargin = 8);
  7186. m_Load_Flags = 32;
  7187. } else if (!strcmp(m_CameraMake,"SAMSUNG") && m_RawWidth == 5632) {
  7188. m_ByteOrder = 0x4949;
  7189. m_Height = 3694;
  7190. m_TopMargin = 2;
  7191. m_Width = 5574 - (m_LeftMargin = 32 + m_Tiff_bps);
  7192. if (m_Tiff_bps == 12) m_Load_Flags = 80;
  7193. } else if (!strcmp(m_CameraModel,"EX1")) {
  7194. m_ByteOrder = 0x4949;
  7195. m_Height -= 20;
  7196. m_TopMargin = 2;
  7197. if ((m_Width -= 6) > 3682) {
  7198. m_Height -= 10;
  7199. m_Width -= 46;
  7200. m_TopMargin = 8;
  7201. }
  7202. } else if (!strcmp(m_CameraModel,"WB2000")) {
  7203. m_ByteOrder = 0x4949;
  7204. m_Height -= 3;
  7205. m_TopMargin = 2;
  7206. if ((m_Width -= 10) > 3718) {
  7207. m_Height -= 28;
  7208. m_Width -= 56;
  7209. m_TopMargin = 8;
  7210. }
  7211. } else if (l_FileSize == 20487168) {
  7212. m_Height = 2808;
  7213. m_Width = 3648;
  7214. goto wb550;
  7215. } else if (l_FileSize == 24000000) {
  7216. m_Height = 3000;
  7217. m_Width = 4000;
  7218. wb550:
  7219. strcpy (m_CameraModel, "WB550");
  7220. m_ByteOrder = 0x4d4d;
  7221. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7222. m_Load_Flags = 6;
  7223. m_WhiteLevel = 0x3df;
  7224. } else if (!strcmp(m_CameraModel,"EX2F")) {
  7225. m_Height = 3045;
  7226. m_Width = 4070;
  7227. m_TopMargin = 3;
  7228. m_ByteOrder = 0x4949;
  7229. m_Filters = 0x49494949;
  7230. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7231. } else if (!strcmp(m_CameraModel,"STV680 VGA")) {
  7232. m_Height = 484;
  7233. m_Width = 644;
  7234. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7235. m_Flip = 2;
  7236. m_Filters = 0x16161616;
  7237. m_BlackLevel = 16;
  7238. } else if (!strcmp(m_CameraModel,"N95")) {
  7239. m_TopMargin = 2;
  7240. m_Height = m_RawHeight - m_TopMargin;
  7241. } else if (!strcmp(m_CameraModel,"531C")) {
  7242. m_Height = 1200;
  7243. m_Width = 1600;
  7244. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7245. m_Filters = 0x49494949;
  7246. } else if (!strcmp(m_CameraModel,"640x480")) {
  7247. m_Height = 480;
  7248. m_Width = 640;
  7249. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7250. gamma_curve (0.45, 4.5, 1, 255);
  7251. } else if (!strcmp(m_CameraModel,"F-080C")) {
  7252. m_Height = 768;
  7253. m_Width = 1024;
  7254. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7255. } else if (!strcmp(m_CameraModel,"F-145C")) {
  7256. m_Height = 1040;
  7257. m_Width = 1392;
  7258. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7259. } else if (!strcmp(m_CameraModel,"F-201C")) {
  7260. m_Height = 1200;
  7261. m_Width = 1600;
  7262. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7263. } else if (!strcmp(m_CameraModel,"F-510C")) {
  7264. m_Height = 1958;
  7265. m_Width = 2588;
  7266. m_LoadRawFunction = l_FileSize < 7500000 ?
  7267. &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
  7268. m_Data_Offset = l_FileSize - m_Width*m_Height*(l_FileSize >> 22);
  7269. m_WhiteLevel = 0xfff0;
  7270. } else if (!strcmp(m_CameraModel,"F-810C")) {
  7271. m_Height = 2469;
  7272. m_Width = 3272;
  7273. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7274. m_WhiteLevel = 0xfff0;
  7275. } else if (!strcmp(m_CameraModel,"XCD-SX910CR")) {
  7276. m_Height = 1024;
  7277. m_Width = 1375;
  7278. m_RawWidth = 1376;
  7279. m_Filters = 0x49494949;
  7280. m_WhiteLevel = 0x3ff;
  7281. m_LoadRawFunction = l_FileSize < 2000000 ?
  7282. &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
  7283. } else if (!strcmp(m_CameraModel,"2010")) {
  7284. m_Height = 1207;
  7285. m_Width = 1608;
  7286. m_ByteOrder = 0x4949;
  7287. m_Filters = 0x16161616;
  7288. m_Data_Offset = 3212;
  7289. m_WhiteLevel = 0x3ff;
  7290. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7291. } else if (!strcmp(m_CameraModel,"A782")) {
  7292. m_Height = 3000;
  7293. m_Width = 2208;
  7294. m_Filters = 0x61616161;
  7295. m_LoadRawFunction = l_FileSize < 10000000 ?
  7296. &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
  7297. m_WhiteLevel = 0xffc0;
  7298. } else if (!strcmp(m_CameraModel,"3320AF")) {
  7299. m_Height = 1536;
  7300. m_RawWidth = m_Width = 2048;
  7301. m_Filters = 0x61616161;
  7302. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7303. m_WhiteLevel = 0x3ff;
  7304. fseek (m_InputFile, 0x300000, SEEK_SET);
  7305. if ((m_ByteOrder = guess_byte_order(0x10000)) == 0x4d4d) {
  7306. m_Height -= (m_TopMargin = 16);
  7307. m_Width -= (m_LeftMargin = 28);
  7308. m_WhiteLevel = 0xf5c0;
  7309. strcpy (m_CameraMake, "ISG");
  7310. m_CameraModel[0] = 0;
  7311. }
  7312. } else if (!strcmp(m_CameraMake,"Hasselblad")) {
  7313. if (m_LoadRawFunction == &CLASS lossless_jpeg_load_raw)
  7314. m_LoadRawFunction = &CLASS hasselblad_load_raw;
  7315. if (m_RawWidth == 7262) {
  7316. m_Height = 5444;
  7317. m_Width = 7248;
  7318. m_TopMargin = 4;
  7319. m_LeftMargin = 7;
  7320. m_Filters = 0x61616161;
  7321. } else if (m_RawWidth == 7410) {
  7322. m_Height = 5502;
  7323. m_Width = 7328;
  7324. m_TopMargin = 4;
  7325. m_LeftMargin = 41;
  7326. m_Filters = 0x61616161;
  7327. } else if (m_RawWidth == 9044) {
  7328. m_Height = 6716;
  7329. m_Width = 8964;
  7330. m_TopMargin = 8;
  7331. m_LeftMargin = 40;
  7332. m_BlackLevel += m_Load_Flags = 256;
  7333. m_WhiteLevel = 0x8101;
  7334. } else if (m_RawWidth == 4090) {
  7335. strcpy (m_CameraModel, "V96C");
  7336. m_Height -= (m_TopMargin = 6);
  7337. m_Width -= (m_LeftMargin = 3) + 7;
  7338. m_Filters = 0x61616161;
  7339. }
  7340. } else if (!strcmp(m_CameraMake,"Sinar")) {
  7341. if (!memcmp(l_Head,"8BPS",4)) {
  7342. fseek (m_InputFile, 14, SEEK_SET);
  7343. m_Height = get4();
  7344. m_Width = get4();
  7345. m_Filters = 0x61616161;
  7346. m_Data_Offset = 68;
  7347. }
  7348. if (!m_LoadRawFunction) m_LoadRawFunction = &CLASS unpacked_load_raw;
  7349. m_WhiteLevel = 0x3fff;
  7350. } else if (!strcmp(m_CameraMake,"Leaf")) {
  7351. m_WhiteLevel = 0x3fff;
  7352. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  7353. if (ljpeg_start (&l_JHead, 1) && l_JHead.bits == 15)
  7354. m_WhiteLevel = 0x1fff;
  7355. if (m_Tiff_Samples > 1) m_Filters = 0;
  7356. if (m_Tiff_Samples > 1 || m_TileLength < m_RawHeight) {
  7357. m_LoadRawFunction = &CLASS leaf_hdr_load_raw;
  7358. m_RawWidth = m_TileWidth;
  7359. }
  7360. if ((m_Width | m_Height) == 2048) {
  7361. if (m_Tiff_Samples == 1) {
  7362. m_Filters = 1;
  7363. strcpy (m_ColorDescriptor, "RBTG");
  7364. strcpy (m_CameraModel, "CatchLight");
  7365. m_TopMargin = 8; m_LeftMargin = 18; m_Height = 2032; m_Width = 2016;
  7366. } else {
  7367. strcpy (m_CameraModel, "DCB2");
  7368. m_TopMargin = 10; m_LeftMargin = 16; m_Height = 2028; m_Width = 2022;
  7369. }
  7370. } else if (m_Width+m_Height == 3144+2060) {
  7371. if (!m_CameraModel[0]) strcpy (m_CameraModel, "Cantare");
  7372. if (m_Width > m_Height) {
  7373. m_TopMargin = 6; m_LeftMargin = 32; m_Height = 2048; m_Width = 3072;
  7374. m_Filters = 0x61616161;
  7375. } else {
  7376. m_LeftMargin = 6; m_TopMargin = 32; m_Width = 2048; m_Height = 3072;
  7377. m_Filters = 0x16161616;
  7378. }
  7379. if (!VALUE(m_CameraMultipliers[0]) || m_CameraModel[0] == 'V') m_Filters = 0;
  7380. else m_IsRaw = m_Tiff_Samples;
  7381. } else if (m_Width == 2116) {
  7382. strcpy (m_CameraModel, "Valeo 6");
  7383. m_Height -= 2 * (m_TopMargin = 30);
  7384. m_Width -= 2 * (m_LeftMargin = 55);
  7385. m_Filters = 0x49494949;
  7386. } else if (m_Width == 3171) {
  7387. strcpy (m_CameraModel, "Valeo 6");
  7388. m_Height -= 2 * (m_TopMargin = 24);
  7389. m_Width -= 2 * (m_LeftMargin = 24);
  7390. m_Filters = 0x16161616;
  7391. }
  7392. } else if (!strcmp(m_CameraMake,"LEICA") || !strcmp(m_CameraMake,"Panasonic")) {
  7393. if ((l_FLen-m_Data_Offset) / (m_RawWidth*8/7) == m_RawHeight)
  7394. m_LoadRawFunction = &CLASS panasonic_load_raw;
  7395. if (!m_LoadRawFunction) {
  7396. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7397. m_Load_Flags = 4;
  7398. }
  7399. m_ZeroIsBad = 1;
  7400. if ((m_Height += 12) > m_RawHeight) m_Height = m_RawHeight;
  7401. for (i=0; i < sizeof pana / sizeof *pana; i++)
  7402. if (m_RawWidth == pana[i][0] && m_RawHeight == pana[i][1]) {
  7403. m_LeftMargin = pana[i][2];
  7404. m_TopMargin = pana[i][3];
  7405. m_Width += pana[i][4];
  7406. m_Height += pana[i][5];
  7407. }
  7408. m_Filters = 0x01010101 * (unsigned char) "\x94\x61\x49\x16"
  7409. [((m_Filters-1) ^ (m_LeftMargin & 1) ^ (m_TopMargin << 1)) & 3];
  7410. } else if (!strcmp(m_CameraModel,"C770UZ")) {
  7411. m_Height = 1718;
  7412. m_Width = 2304;
  7413. m_Filters = 0x16161616;
  7414. m_LoadRawFunction = &CLASS packed_load_raw;
  7415. m_Load_Flags = 30;
  7416. } else if (!strcmp(m_CameraMake,"OLYMPUS")) {
  7417. m_Height += m_Height & 1;
  7418. m_Filters = exif_cfa;
  7419. if (m_Width == 4100) m_Width -= 4;
  7420. if (m_Width == 4080) m_Width -= 24;
  7421. if (m_LoadRawFunction == &CLASS unpacked_load_raw)
  7422. m_Load_Flags = 4;
  7423. m_Tiff_bps = 12;
  7424. if (!strcmp(m_CameraModel,"E-300") ||
  7425. !strcmp(m_CameraModel,"E-500")) {
  7426. m_Width -= 20;
  7427. if (m_LoadRawFunction == &CLASS unpacked_load_raw) {
  7428. m_WhiteLevel = 0xfc3;
  7429. memset (m_CBlackLevel, 0, sizeof m_CBlackLevel);
  7430. }
  7431. } else if (!strcmp(m_CameraModel,"E-330")) {
  7432. m_Width -= 30;
  7433. if (m_LoadRawFunction == &CLASS unpacked_load_raw)
  7434. m_WhiteLevel = 0xf79;
  7435. } else if (!strcmp(m_CameraModel,"SP550UZ")) {
  7436. m_ThumbLength = l_FLen - (m_ThumbOffset = 0xa39800);
  7437. m_ThumbHeight = 480;
  7438. m_ThumbWidth = 640;
  7439. } else if (!strcmp(m_CameraModel,"XZ-2")) {
  7440. m_LoadRawFunction = &CLASS packed_load_raw;
  7441. m_Load_Flags = 24;
  7442. }
  7443. } else if (!strcmp(m_CameraModel,"N Digital")) {
  7444. m_Height = 2047;
  7445. m_Width = 3072;
  7446. m_Filters = 0x61616161;
  7447. m_Data_Offset = 0x1a00;
  7448. m_LoadRawFunction = &CLASS packed_load_raw;
  7449. } else if (!strcmp(m_CameraModel,"DSC-F828")) {
  7450. m_Width = 3288;
  7451. m_LeftMargin = 5;
  7452. m_Mask[1][3] = -17;
  7453. m_Data_Offset = 862144;
  7454. m_LoadRawFunction = &CLASS sony_load_raw;
  7455. m_Filters = 0x9c9c9c9c;
  7456. m_Colors = 4;
  7457. strcpy (m_ColorDescriptor, "RGBE");
  7458. } else if (!strcmp(m_CameraModel,"DSC-V3")) {
  7459. m_Width = 3109;
  7460. m_LeftMargin = 59;
  7461. m_Mask[0][1] = 9;
  7462. m_Data_Offset = 787392;
  7463. m_LoadRawFunction = &CLASS sony_load_raw;
  7464. } else if (!strcmp(m_CameraMake,"SONY") && m_RawWidth == 3984) {
  7465. adobe_coeff ("SONY","DSC-R1");
  7466. m_Width = 3925;
  7467. m_ByteOrder = 0x4d4d;
  7468. } else if (!strcmp(m_CameraMake,"SONY") && m_RawWidth == 5504) {
  7469. m_Width -= 8;
  7470. } else if (!strcmp(m_CameraMake,"SONY") && m_RawWidth == 6048) {
  7471. m_Width -= 24;
  7472. } else if (!strcmp(m_CameraModel,"DSLR-A100")) {
  7473. if (m_Width == 3880) {
  7474. m_Height--;
  7475. m_Width = ++m_RawWidth;
  7476. } else {
  7477. m_ByteOrder = 0x4d4d;
  7478. m_Load_Flags = 2;
  7479. }
  7480. m_Filters = 0x61616161;
  7481. } else if (!strcmp(m_CameraModel,"DSLR-A350")) {
  7482. m_Height -= 4;
  7483. } else if (!strcmp(m_CameraModel,"PIXL")) {
  7484. m_Height -= m_TopMargin = 4;
  7485. m_Width -= m_LeftMargin = 32;
  7486. gamma_curve (0, 7, 1, 255);
  7487. } else if (!strcmp(m_CameraModel,"C603v")) {
  7488. m_Height = 480;
  7489. m_Width = 640;
  7490. if (l_FileSize < 614400 || find_green (16, 16, 3840, 5120) < 25) goto c603v;
  7491. strcpy (m_CameraModel,"KAI-0340");
  7492. m_Height -= 3;
  7493. m_Data_Offset = 3840;
  7494. m_ByteOrder = 0x4949;
  7495. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7496. } else if (!strcmp(m_CameraModel,"C603y")) {
  7497. m_Height = 2134;
  7498. m_Width = 2848;
  7499. c603v:
  7500. m_Filters = 0;
  7501. m_LoadRawFunction = &CLASS kodak_yrgb_load_raw;
  7502. gamma_curve (0, 3.875, 1, 255);
  7503. } else if (!strcmp(m_CameraModel,"C603")) {
  7504. m_RawHeight = m_Height = 2152;
  7505. m_RawWidth = m_Width = 2864;
  7506. goto c603;
  7507. } else if (!strcmp(m_CameraModel,"C330")) {
  7508. m_Height = 1744;
  7509. m_Width = 2336;
  7510. m_RawHeight = 1779;
  7511. m_RawWidth = 2338;
  7512. m_TopMargin = 33;
  7513. m_LeftMargin = 1;
  7514. c603:
  7515. m_ByteOrder = 0x4949;
  7516. if ((m_Data_Offset = l_FileSize - m_RawHeight*m_RawWidth)) {
  7517. fseek (m_InputFile, 168, SEEK_SET);
  7518. read_shorts (m_Curve, 256);
  7519. } else gamma_curve (0, 3.875, 1, 255);
  7520. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7521. } else if (!strncasecmp(m_CameraMake,"EasyShare",9)) {
  7522. m_Data_Offset = m_Data_Offset < 0x15000 ? 0x15000 : 0x17000;
  7523. m_LoadRawFunction = &CLASS packed_load_raw;
  7524. } else if (!strcasecmp(m_CameraMake,"KODAK")) {
  7525. if (m_Filters == UINT_MAX) m_Filters = 0x61616161;
  7526. if (!strncmp(m_CameraModel,"NC2000",6)) {
  7527. m_Width -= 4;
  7528. m_LeftMargin = 2;
  7529. } else if (!strcmp(m_CameraModel,"EOSDCS3B")) {
  7530. m_Width -= 4;
  7531. m_LeftMargin = 2;
  7532. } else if (!strcmp(m_CameraModel,"EOSDCS1")) {
  7533. m_Width -= 4;
  7534. m_LeftMargin = 2;
  7535. } else if (!strcmp(m_CameraModel,"DCS420")) {
  7536. m_Width -= 4;
  7537. m_LeftMargin = 2;
  7538. } else if (!strncmp(m_CameraModel,"DCS460",7)) {
  7539. m_CameraModel[6]=0;
  7540. m_Width -= 4;
  7541. m_LeftMargin = 2;
  7542. } else if (!strcmp(m_CameraModel,"DCS460A")) {
  7543. m_Width -= 4;
  7544. m_LeftMargin = 2;
  7545. m_Colors = 1;
  7546. m_Filters = 0;
  7547. } else if (!strcmp(m_CameraModel,"DCS660M")) {
  7548. m_BlackLevel = 214;
  7549. m_Colors = 1;
  7550. m_Filters = 0;
  7551. } else if (!strcmp(m_CameraModel,"DCS760M")) {
  7552. m_Colors = 1;
  7553. m_Filters = 0;
  7554. }
  7555. if (!strcmp(m_CameraModel+4,"20X"))
  7556. strcpy (m_ColorDescriptor, "MYCY");
  7557. if (strstr(m_CameraModel,"DC25")) {
  7558. strcpy (m_CameraModel, "DC25");
  7559. m_Data_Offset = 15424;
  7560. }
  7561. if (!strncmp(m_CameraModel,"DC2",3)) {
  7562. m_RawHeight = m_Height = 242;
  7563. if (l_FLen < 100000) {
  7564. m_RawWidth = 256; m_Width = 249;
  7565. m_PixelAspect = (4.0*m_Height) / (3.0*m_Width);
  7566. } else {
  7567. m_RawWidth = 512; m_Width = 501;
  7568. m_PixelAspect = (493.0*m_Height) / (373.0*m_Width);
  7569. }
  7570. m_Data_Offset += m_RawWidth + 1;
  7571. m_Colors = 4;
  7572. m_Filters = 0x8d8d8d8d;
  7573. simple_coeff(1);
  7574. ASSIGN(m_D65Multipliers[1], 1.179);
  7575. ASSIGN(m_D65Multipliers[2], 1.209);
  7576. ASSIGN(m_D65Multipliers[3], 1.036);
  7577. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7578. } else if (!strcmp(m_CameraModel,"40")) {
  7579. strcpy (m_CameraModel, "DC40");
  7580. m_Height = 512;
  7581. m_Width = 768;
  7582. m_Data_Offset = 1152;
  7583. m_LoadRawFunction = &CLASS kodak_radc_load_raw;
  7584. } else if (strstr(m_CameraModel,"DC50")) {
  7585. strcpy (m_CameraModel, "DC50");
  7586. m_Height = 512;
  7587. m_Width = 768;
  7588. m_Data_Offset = 19712;
  7589. m_LoadRawFunction = &CLASS kodak_radc_load_raw;
  7590. } else if (strstr(m_CameraModel,"DC120")) {
  7591. strcpy (m_CameraModel, "DC120");
  7592. m_Height = 976;
  7593. m_Width = 848;
  7594. m_PixelAspect = m_Height/0.75/m_Width;
  7595. m_LoadRawFunction = m_Tiff_Compress == 7 ?
  7596. &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
  7597. } else if (!strcmp(m_CameraModel,"DCS200")) {
  7598. m_ThumbHeight = 128;
  7599. m_ThumbWidth = 192;
  7600. m_ThumbOffset = 6144;
  7601. m_ThumbMisc = 360;
  7602. m_WriteThumb = &CLASS layer_thumb;
  7603. m_Height = 1024;
  7604. m_Width = 1536;
  7605. m_Data_Offset = 79872;
  7606. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7607. m_BlackLevel = 17;
  7608. }
  7609. } else if (!strcmp(m_CameraModel,"Fotoman Pixtura")) {
  7610. m_Height = 512;
  7611. m_Width = 768;
  7612. m_Data_Offset = 3632;
  7613. m_LoadRawFunction = &CLASS kodak_radc_load_raw;
  7614. m_Filters = 0x61616161;
  7615. simple_coeff(2);
  7616. } else if (!strncmp(m_CameraModel,"QuickTake",9)) {
  7617. if (l_Head[5]) strcpy (m_CameraModel+10, "200");
  7618. fseek (m_InputFile, 544, SEEK_SET);
  7619. m_Height = get2();
  7620. m_Width = get2();
  7621. m_Data_Offset = (get4(),get2()) == 30 ? 738:736;
  7622. if (m_Height > m_Width) {
  7623. SWAP(m_Height,m_Width);
  7624. fseek (m_InputFile, m_Data_Offset-6, SEEK_SET);
  7625. m_Flip = ~get2() & 3 ? 5:6;
  7626. }
  7627. m_Filters = 0x61616161;
  7628. } else if (!strcmp(m_CameraMake,"Rollei") && !m_LoadRawFunction) {
  7629. switch (m_RawWidth) {
  7630. case 1316:
  7631. m_Height = 1030;
  7632. m_Width = 1300;
  7633. m_TopMargin = 1;
  7634. m_LeftMargin = 6;
  7635. break;
  7636. case 2568:
  7637. m_Height = 1960;
  7638. m_Width = 2560;
  7639. m_TopMargin = 2;
  7640. m_LeftMargin = 8;
  7641. }
  7642. m_Filters = 0x16161616;
  7643. m_LoadRawFunction = &CLASS rollei_load_raw;
  7644. } else if (!strcmp(m_CameraModel,"PC-CAM 600")) {
  7645. m_Height = 768;
  7646. m_Data_Offset = m_Width = 1024;
  7647. m_Filters = 0x49494949;
  7648. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7649. } else if (!strcmp(m_CameraModel,"QV-2000UX")) {
  7650. m_Height = 1208;
  7651. m_Width = 1632;
  7652. m_Data_Offset = m_Width * 2;
  7653. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7654. } else if (l_FileSize == 3217760) {
  7655. m_Height = 1546;
  7656. m_Width = 2070;
  7657. m_RawWidth = 2080;
  7658. m_LoadRawFunction = &CLASS eight_bit_load_raw;
  7659. } else if (!strcmp(m_CameraModel,"QV-4000")) {
  7660. m_Height = 1700;
  7661. m_Width = 2260;
  7662. m_LoadRawFunction = &CLASS unpacked_load_raw;
  7663. m_WhiteLevel = 0xffff;
  7664. } else if (!strcmp(m_CameraModel,"QV-5700")) {
  7665. m_Height = 1924;
  7666. m_Width = 2576;
  7667. m_RawWidth = 3232;
  7668. m_Tiff_bps = 10;
  7669. } else if (!strcmp(m_CameraModel,"QV-R41")) {
  7670. m_Height = 1720;
  7671. m_Width = 2312;
  7672. m_RawWidth = 3520;
  7673. m_LeftMargin = 2;
  7674. } else if (!strcmp(m_CameraModel,"QV-R51")) {
  7675. m_Height = 1926;
  7676. m_Width = 2580;
  7677. m_RawWidth = 3904;
  7678. } else if (!strcmp(m_CameraModel,"EX-S20")) {
  7679. m_Height = 1208;
  7680. m_Width = 1620;
  7681. m_RawWidth = 2432;
  7682. m_Flip = 3;
  7683. } else if (!strcmp(m_CameraModel,"EX-S100")) {
  7684. m_Height = 1544;
  7685. m_Width = 2058;
  7686. m_RawWidth = 3136;
  7687. } else if (!strcmp(m_CameraModel,"EX-Z50")) {
  7688. m_Height = 1931;
  7689. m_Width = 2570;
  7690. m_RawWidth = 3904;
  7691. } else if (!strcmp(m_CameraModel,"EX-Z500")) {
  7692. m_Height = 1937;
  7693. m_Width = 2577;
  7694. m_RawWidth = 3904;
  7695. m_Filters = 0x16161616;
  7696. } else if (!strcmp(m_CameraModel,"EX-Z55")) {
  7697. m_Height = 1960;
  7698. m_Width = 2570;
  7699. m_RawWidth = 3904;
  7700. } else if (!strcmp(m_CameraModel,"EX-Z60")) {
  7701. m_Height = 2145;
  7702. m_Width = 2833;
  7703. m_RawWidth = 3584;
  7704. m_Filters = 0x16161616;
  7705. m_Tiff_bps = 10;
  7706. } else if (!strcmp(m_CameraModel,"EX-Z75")) {
  7707. m_Height = 2321;
  7708. m_Width = 3089;
  7709. m_RawWidth = 4672;
  7710. m_WhiteLevel = 0xfff;
  7711. } else if (!strcmp(m_CameraModel,"EX-Z750")) {
  7712. m_Height = 2319;
  7713. m_Width = 3087;
  7714. m_RawWidth = 4672;
  7715. m_WhiteLevel = 0xfff;
  7716. } else if (!strcmp(m_CameraModel,"EX-Z850")) {
  7717. m_Height = 2468;
  7718. m_Width = 3279;
  7719. m_RawWidth = 4928;
  7720. m_WhiteLevel = 0xfff;
  7721. } else if (!strcmp(m_CameraModel,"EX-Z8")) {
  7722. m_Height = 2467;
  7723. m_Width = 3281;
  7724. m_RawHeight = 2502;
  7725. m_RawWidth = 4992;
  7726. m_WhiteLevel = 0xfff;
  7727. } else if (l_FileSize == 15499264) { /* EX-Z1050 or EX-Z1080 */
  7728. m_Height = 2752;
  7729. m_Width = 3672;
  7730. m_RawWidth = 5632;
  7731. } else if (!strcmp(m_CameraModel,"EX-ZR100")) {
  7732. m_Height = 3044;
  7733. m_Width = 4072;
  7734. m_RawWidth = 4096;
  7735. m_Load_Flags = 80;
  7736. } else if (!strcmp(m_CameraModel,"EX-P505")) {
  7737. m_Height = 1928;
  7738. m_Width = 2568;
  7739. m_RawWidth = 3852;
  7740. m_WhiteLevel = 0xfff;
  7741. } else if (l_FileSize == 9313536) { /* EX-P600 or QV-R61 */
  7742. m_Height = 2142;
  7743. m_Width = 2844;
  7744. m_RawWidth = 4288;
  7745. } else if (!strcmp(m_CameraModel,"EX-P700")) {
  7746. m_Height = 2318;
  7747. m_Width = 3082;
  7748. m_RawWidth = 4672;
  7749. }
  7750. if (!m_CameraModel[0])
  7751. sprintf (m_CameraModel, "%dx%d", m_Width, m_Height);
  7752. if (m_Filters == UINT_MAX) m_Filters = 0x94949494;
  7753. if (m_RawColor) adobe_coeff (m_CameraMake, m_CameraModel);
  7754. if (m_LoadRawFunction == &CLASS kodak_radc_load_raw)
  7755. if (m_RawColor) adobe_coeff ("Apple","Quicktake");
  7756. if (m_ThumbOffset && !m_ThumbHeight) {
  7757. fseek (m_InputFile, m_ThumbOffset, SEEK_SET);
  7758. if (ljpeg_start (&l_JHead, 1)) {
  7759. m_ThumbWidth = l_JHead.wide;
  7760. m_ThumbHeight = l_JHead.high;
  7761. }
  7762. }
  7763. dng_skip:
  7764. if (m_Fuji_Width) {
  7765. m_Fuji_Width = m_Width >> !fuji_layout;
  7766. if (~m_Fuji_Width & 1) m_Filters = 0x49494949;
  7767. m_Width = (m_Height >> fuji_layout) + m_Fuji_Width;
  7768. m_Height = m_Width - 1;
  7769. m_PixelAspect = 1;
  7770. } else {
  7771. if (m_RawHeight < m_Height) m_RawHeight = m_Height;
  7772. if (m_RawWidth < m_Width ) m_RawWidth = m_Width;
  7773. }
  7774. if (!m_Tiff_bps) m_Tiff_bps = 12;
  7775. if (!m_WhiteLevel) m_WhiteLevel = (1 << m_Tiff_bps) - 1;
  7776. if (!m_LoadRawFunction || m_Height < 22) m_IsRaw = 0;
  7777. #ifdef NO_JASPER
  7778. if (m_LoadRawFunction == &CLASS redcine_load_raw) {
  7779. fprintf (stderr,_("%s: You must link dcraw with %s!\n"),
  7780. m_UserSetting_InputFileName, "libjasper");
  7781. m_IsRaw = 0;
  7782. }
  7783. #endif
  7784. #ifdef NO_JPEG
  7785. if (m_LoadRawFunction == &CLASS kodak_jpeg_load_raw ||
  7786. m_LoadRawFunction == &CLASS lossy_dng_load_raw) {
  7787. fprintf (stderr,_("%s: You must link dcraw with %s!\n"),
  7788. m_UserSetting_InputFileName, "libjpeg");
  7789. m_IsRaw = 0;
  7790. }
  7791. #endif
  7792. if (!m_ColorDescriptor[0])
  7793. strcpy (m_ColorDescriptor, m_Colors == 3 ? "RGBG":"GMCY");
  7794. if (!m_RawHeight) m_RawHeight = m_Height;
  7795. if (!m_RawWidth ) m_RawWidth = m_Width;
  7796. if (m_Filters && m_Colors == 3)
  7797. m_Filters |= ((m_Filters >> 2 & 0x22222222) |
  7798. (m_Filters << 2 & 0x88888888)) & m_Filters << 1;
  7799. notraw:
  7800. // Somehow Nikon D90 files give a corrupt value here... although they shouldn't.
  7801. if (m_Flip == -1) m_Flip = m_Tiff_Flip;
  7802. if (m_Flip == -1) m_Flip = 0;
  7803. }
  7804. void CLASS fuji_rotate() {
  7805. int i, row, col;
  7806. double step;
  7807. float r, c, fr, fc;
  7808. unsigned ur, uc;
  7809. uint16_t wide, high, (*img)[4], (*pix)[4];
  7810. if (!m_Fuji_Width) return;
  7811. TRACEKEYVALS("Rotating image 45 degrees","%s","");
  7812. TRACEKEYVALS("m_Fuji_Width","%d",m_Fuji_Width);
  7813. TRACEKEYVALS("m_Shrink","%d",m_Shrink);
  7814. TRACEKEYVALS("m_UserSetting_HalfSize","%d",m_UserSetting_HalfSize);
  7815. // XXX JDLA : Was : m_Fuji_Width = (m_Fuji_Width - 1 + m_Shrink) >> m_Shrink;
  7816. m_Fuji_Width =
  7817. (m_Fuji_Width - 1 + m_UserSetting_HalfSize) >> m_UserSetting_HalfSize;
  7818. TRACEKEYVALS("m_Fuji_Width","%d",m_Fuji_Width);
  7819. step = sqrt(0.5);
  7820. wide = (uint16_t) (m_Fuji_Width / step);
  7821. high = (uint16_t) ((m_Height - m_Fuji_Width) / step);
  7822. img = (uint16_t (*)[4]) CALLOC (wide*high, sizeof *img);
  7823. TRACEKEYVALS("m_Width","%d",m_Width);
  7824. TRACEKEYVALS("m_Height","%d",m_Height);
  7825. TRACEKEYVALS("wide","%d",wide);
  7826. TRACEKEYVALS("high","%d",high);
  7827. merror (img, "fuji_rotate()");
  7828. for (row=0; row < high; row++)
  7829. for (col=0; col < wide; col++) {
  7830. ur = (unsigned) (r = m_Fuji_Width + (row-col)*step);
  7831. uc = (unsigned) (c = (row+col)*step);
  7832. if (ur > (unsigned)(m_Height-2) || uc > (unsigned)(m_Width-2)) continue;
  7833. fr = r - ur;
  7834. fc = c - uc;
  7835. pix = m_Image + ur*m_Width + uc;
  7836. for (i=0; i < m_Colors; i++)
  7837. img[row*wide+col][i] = (uint16_t) (
  7838. (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) +
  7839. (pix[m_Width][i]*(1-fc) + pix[m_Width+1][i]*fc) * fr);
  7840. }
  7841. FREE (m_Image);
  7842. m_OutWidth = m_Width = wide;
  7843. m_OutHeight = m_Height = high;
  7844. m_Image = img;
  7845. m_Fuji_Width = 0; // this prevents image rotation when only phase 2 is called
  7846. TRACEKEYVALS("m_Width","%d",m_Width);
  7847. TRACEKEYVALS("m_Height","%d",m_Height);
  7848. TRACEKEYVALS("m_OutWidth","%d",m_OutWidth);
  7849. TRACEKEYVALS("m_OutHeight","%d",m_OutHeight);
  7850. }
  7851. void CLASS stretch()
  7852. {
  7853. uint16_t newdim, (*img)[4], *pix0, *pix1;
  7854. int row, col, c;
  7855. double rc, frac;
  7856. if (m_PixelAspect == 1) return;
  7857. TRACEKEYVALS("Stretching the image","%s","");
  7858. TRACEKEYVALS("m_PixelAspect","%f",m_PixelAspect);
  7859. if (m_PixelAspect < 1) {
  7860. newdim = (uint16_t) (m_Height / m_PixelAspect + 0.5);
  7861. img = (uint16_t (*)[4]) CALLOC (m_Width*newdim, sizeof *img);
  7862. merror (img, "stretch()");
  7863. for (rc=row=0; row < newdim; row++, rc+=m_PixelAspect) {
  7864. frac = rc - (c = (int) rc);
  7865. pix0 = pix1 = m_Image[c*m_Width];
  7866. if (c+1 < m_Height) pix1 += m_Width*4;
  7867. for (col=0; col < m_Width; col++, pix0+=4, pix1+=4)
  7868. for (c=0; c < m_Colors; c++) img[row*m_Width+col][c] =
  7869. (uint16_t)(pix0[c]*(1-frac) + pix1[c]*frac + 0.5);
  7870. }
  7871. m_OutHeight = m_Height = newdim;
  7872. } else {
  7873. newdim = (uint16_t) (m_Width * m_PixelAspect + 0.5);
  7874. img = (uint16_t (*)[4]) CALLOC (m_Height*newdim, sizeof *img);
  7875. merror (img, "stretch()");
  7876. for (rc=col=0; col < newdim; col++, rc+=1/m_PixelAspect) {
  7877. frac = rc - (c = (int) rc);
  7878. pix0 = pix1 = m_Image[c];
  7879. if (c+1 < m_Width) pix1 += 4;
  7880. for (row=0; row < m_Height; row++, pix0+=m_Width*4, pix1+=m_Width*4)
  7881. for (c=0; c < m_Colors; c++) img[row*newdim+col][c] =
  7882. (uint16_t) (pix0[c]*(1-frac) + pix1[c]*frac + 0.5);
  7883. }
  7884. m_OutWidth = m_Width = newdim;
  7885. }
  7886. FREE (m_Image);
  7887. m_Image = img;
  7888. TRACEKEYVALS("m_Width","%d",m_Width);
  7889. TRACEKEYVALS("m_Height","%d",m_Height);
  7890. TRACEKEYVALS("m_OutWidth","%d",m_OutWidth);
  7891. TRACEKEYVALS("m_OutHeight","%d",m_OutHeight);
  7892. }
  7893. int CLASS flip_index (int row, int col)
  7894. {
  7895. if (m_Flip & 4) SWAP(row,col);
  7896. if (m_Flip & 2) row = m_OutHeight - 1 - row;
  7897. if (m_Flip & 1) col = m_OutWidth - 1 - col;
  7898. return row * m_OutWidth + col;
  7899. }
  7900. struct tiff_tag {
  7901. uint16_t tag, type;
  7902. int count;
  7903. union { char c[4]; short s[2]; int i; } val;
  7904. };
  7905. struct tiff_hdr {
  7906. uint16_t order, magic;
  7907. int ifd;
  7908. uint16_t pad, ntag;
  7909. struct tiff_tag tag[23];
  7910. int nextifd;
  7911. uint16_t pad2, nexif;
  7912. struct tiff_tag exif[4];
  7913. uint16_t pad3, ngps;
  7914. struct tiff_tag gpst[10];
  7915. short bps[4];
  7916. int rat[10];
  7917. unsigned gps[26];
  7918. char desc[512], make[64], model[64], soft[32], date[20], artist[64];
  7919. };
  7920. void CLASS tiff_set (uint16_t *ntag,
  7921. uint16_t tag, uint16_t type, int count, int val)
  7922. {
  7923. struct tiff_tag *tt;
  7924. int c;
  7925. tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
  7926. tt->tag = tag;
  7927. tt->type = type;
  7928. tt->count = count;
  7929. if (type < 3 && count <= 4)
  7930. for(c=0;c<4;c++) tt->val.c[c] = val >> (c << 3);
  7931. else if (type == 3 && count <= 2)
  7932. for(c=0;c<2;c++) tt->val.s[c] = val >> (c << 4);
  7933. else tt->val.i = val;
  7934. }
  7935. #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
  7936. void CLASS tiff_head (struct tiff_hdr *th)
  7937. {
  7938. int psize=0;
  7939. struct tm *t;
  7940. memset (th, 0, sizeof *th);
  7941. th->order = htonl(0x4d4d4949) >> 16;
  7942. th->magic = 42;
  7943. th->ifd = 10;
  7944. tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc));
  7945. tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make));
  7946. tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model));
  7947. tiff_set (&th->ntag, 274, 3, 1, "12435867"[m_Flip]-'0');
  7948. tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
  7949. tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
  7950. tiff_set (&th->ntag, 284, 3, 1, 1);
  7951. tiff_set (&th->ntag, 296, 3, 1, 2);
  7952. tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
  7953. tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
  7954. tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist));
  7955. tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
  7956. if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
  7957. tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
  7958. tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
  7959. tiff_set (&th->nexif, 34855, 3, 1, (int) m_IsoSpeed);
  7960. tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
  7961. strncpy (th->desc, m_Description, 512);
  7962. strncpy (th->make, m_CameraMake, 64);
  7963. strncpy (th->model, m_CameraModel, 64);
  7964. strcpy (th->soft, DCRAW_VERSION);
  7965. t = localtime (&m_TimeStamp);
  7966. sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
  7967. t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
  7968. strncpy (th->artist, m_Artist, 64);
  7969. }
  7970. void CLASS jpeg_thumb ()
  7971. /* Remember: This function is modified to write the rawÂ’s thumbnail to the
  7972. m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
  7973. */
  7974. {
  7975. char *thumb;
  7976. uint16_t exif[5];
  7977. struct tiff_hdr th;
  7978. thumb = (char *) MALLOC (m_ThumbLength);
  7979. merror (thumb, "jpeg_thumb()");
  7980. ptfread (thumb, 1, m_ThumbLength, m_InputFile);
  7981. // fputc (0xff, m_OutputFile);
  7982. // fputc (0xd8, m_OutputFile);
  7983. m_Thumb.push_back('\xff');
  7984. m_Thumb.push_back('\xd8');
  7985. if (strcmp (thumb+6, "Exif")) {
  7986. memcpy (exif, "\xff\xe1 Exif\0\0", 10);
  7987. exif[1] = htons (8 + sizeof th);
  7988. //ptfwrite (exif, 1, sizeof exif, m_OutputFile);
  7989. VAppend(m_Thumb, (char*)&exif[0], sizeof(exif));
  7990. tiff_head (&th);
  7991. //ptfwrite (&th, 1, sizeof th, m_OutputFile);
  7992. VAppend(m_Thumb, (char*)&th, sizeof(th));
  7993. }
  7994. //ptfwrite (thumb+2, 1, m_ThumbLength-2, m_OutputFile);
  7995. VAppend(m_Thumb, thumb+2, m_ThumbLength-2);
  7996. FREE (thumb);
  7997. }
  7998. ////////////////////////////////////////////////////////////////////////////////
  7999. //
  8000. // Identify
  8001. //
  8002. // First method to be called when in an photivo application.
  8003. // Hereafter camera, model, and a number of other picture and camera
  8004. // parameters are identified.
  8005. // Returns 0 on success.
  8006. //
  8007. ////////////////////////////////////////////////////////////////////////////////
  8008. short CLASS Identify(const QString NewInputFile) {
  8009. // This is here to support multiple calls.
  8010. ResetNonUserSettings();
  8011. FCLOSE(m_InputFile);
  8012. if (NewInputFile != "") {
  8013. FREE(m_UserSetting_InputFileName);
  8014. m_UserSetting_InputFileName = (char*) MALLOC(1 + strlen(NewInputFile.toLocal8Bit().data()));
  8015. ptMemoryError(m_UserSetting_InputFileName,__FILE__,__LINE__);
  8016. strcpy(m_UserSetting_InputFileName, NewInputFile.toLocal8Bit().data());
  8017. }
  8018. if (!(m_InputFile = fopen (m_UserSetting_InputFileName, "rb"))) {
  8019. perror (m_UserSetting_InputFileName);
  8020. return -1;
  8021. }
  8022. identify();
  8023. if (!m_IsRaw) {
  8024. FCLOSE(m_InputFile);
  8025. }
  8026. return !m_IsRaw;
  8027. }
  8028. ////////////////////////////////////////////////////////////////////////////////
  8029. //
  8030. // RunDcRaw_Phase1
  8031. //
  8032. // Settings are given via the m_UserSetting* members.
  8033. // It will end there where the raw image is loaded.
  8034. // Badpixels and darkframes subtracted.
  8035. // But before colorscaling and the like so that we can
  8036. // intervene in the whitebalances etc.
  8037. // Returns 0 on success.
  8038. //
  8039. ////////////////////////////////////////////////////////////////////////////////
  8040. short CLASS RunDcRaw_Phase1() {
  8041. // TODO foveon for the moment not in. Need study material
  8042. // to have this +/- right.
  8043. assert (!m_IsFoveon);
  8044. TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
  8045. TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
  8046. TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
  8047. TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
  8048. #ifdef TRACE_ORIGIN
  8049. TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
  8050. TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
  8051. #endif
  8052. TRACEKEYVALS("D65Mult[0]","%f",VALUE(m_D65Multipliers[0]));
  8053. TRACEKEYVALS("D65Mult[1]","%f",VALUE(m_D65Multipliers[1]));
  8054. TRACEKEYVALS("D65Mult[2]","%f",VALUE(m_D65Multipliers[2]));
  8055. TRACEKEYVALS("D65Mult[3]","%f",VALUE(m_D65Multipliers[3]));
  8056. #ifdef TRACE_ORIGIN
  8057. TRACEKEYVALS("D65Mult File","%s",m_D65Multipliers[0].File);
  8058. TRACEKEYVALS("D65Mult Line","%d",m_D65Multipliers[0].Line);
  8059. #endif
  8060. TRACEKEYVALS("RawWidth","%d",m_RawWidth);
  8061. TRACEKEYVALS("RawHeight","%d",m_RawHeight);
  8062. TRACEKEYVALS("TopMargin","%d",m_TopMargin);
  8063. TRACEKEYVALS("LeftMargin","%d",m_LeftMargin);
  8064. TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
  8065. // OK for second entry.
  8066. if (m_LoadRawFunction == &CLASS kodak_ycbcr_load_raw) {
  8067. m_Height += m_Height & 1;
  8068. m_Width += m_Width & 1;
  8069. }
  8070. m_OutHeight = m_Height;
  8071. m_OutWidth = m_Width;
  8072. TRACEKEYVALS("OutWidth","%d",m_OutWidth);
  8073. TRACEKEYVALS("Width","%d",m_Width);
  8074. // Also some reshuffling for second entry problem.
  8075. // not sure how c_matrix comes into play here ...
  8076. int l_CameraMatrix = (m_UserSetting_CameraMatrix < 0) ?
  8077. m_UserSetting_CameraWb : m_UserSetting_CameraMatrix;
  8078. TRACEKEYVALS("US_CameraWB","%d",m_UserSetting_CameraWb);
  8079. TRACEKEYVALS("US_CameraMatr","%d",m_UserSetting_CameraMatrix);
  8080. TRACEKEYVALS("CameraMatrix","%d",l_CameraMatrix);
  8081. TRACEKEYVALS("m_cmatrix[0][0","%f",m_cmatrix[0][0]);
  8082. if (l_CameraMatrix && m_cmatrix[0][0] > 0.25) {
  8083. TRACEKEYVALS("Using CamMatr","%s","Yes");
  8084. memcpy (m_MatrixCamRGBToSRGB, m_cmatrix, sizeof m_cmatrix);
  8085. m_RawColor = 0;
  8086. }
  8087. // Allocation is depending on m_Raw_Image below.
  8088. FREE(m_Image);
  8089. if (m_MetaLength) {
  8090. FREE(m_MetaData);
  8091. m_MetaData = (char *) MALLOC (m_MetaLength);
  8092. merror (m_MetaData, "main()");
  8093. }
  8094. if (m_Filters || m_Colors == 1) {
  8095. m_Raw_Image = (uint16_t *) CALLOC ((m_RawHeight+7)*m_RawWidth, 2);
  8096. merror (m_Raw_Image, "main().m_Raw_Image");
  8097. } else {
  8098. // Basic image memory allocation @ 4 int per pixel happens here.
  8099. m_Image = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8100. merror (m_Image, "main()");
  8101. }
  8102. TRACEKEYVALS("CameraMake","%s",m_CameraMake);
  8103. TRACEKEYVALS("CameraModel","%s",m_CameraModel);
  8104. TRACEKEYVALS("InputFile","%s",m_UserSetting_InputFileName);
  8105. TRACEKEYVALS("Filters","%x",m_Filters);
  8106. TRACEKEYVALS("Flip","%x",m_Flip);
  8107. fseek (m_InputFile, m_Data_Offset, SEEK_SET);
  8108. // Basic loading operation.
  8109. // That's the hook into the real workhorse.
  8110. (*this.*m_LoadRawFunction)();
  8111. if (m_Raw_Image) {
  8112. // Basic image memory allocation @ 4 int per pixel happens here.
  8113. m_Image = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8114. merror (m_Image, "main()");
  8115. crop_masked_pixels();
  8116. FREE (m_Raw_Image);
  8117. }
  8118. if (m_ZeroIsBad) remove_zeroes();
  8119. bad_pixels (m_UserSetting_BadPixelsFileName);
  8120. if (m_UserSetting_DarkFrameFileName)
  8121. subtract (m_UserSetting_DarkFrameFileName);
  8122. // photivo extra.
  8123. // Calculation of the inverse m_MatrixCamRGBToSRGB
  8124. double rgb_cam_transpose[4][3];
  8125. for (short i=0; i<4; i++) for (short j=0; j<3; j++)
  8126. rgb_cam_transpose[i][j] = m_MatrixCamRGBToSRGB[j][i];
  8127. pseudoinverse(rgb_cam_transpose,m_MatrixSRGBToCamRGB,m_Colors);
  8128. // ReportedWidth & Height correct for fuji_rotate stuff and pixelaspects.
  8129. m_ReportedWidth = m_Width;
  8130. m_ReportedHeight = m_Height;
  8131. if (m_Fuji_Width) {
  8132. m_IsFuji = m_Fuji_Width;
  8133. m_ReportedWidth = (m_Fuji_Width-1) / sqrt(0.5);
  8134. m_ReportedHeight = (m_Height-m_Fuji_Width+1)/sqrt(0.5);
  8135. }
  8136. if (m_PixelAspect<1)
  8137. m_ReportedHeight = (uint16_t) (m_Height / m_PixelAspect + 0.5);
  8138. if (m_PixelAspect>1)
  8139. m_ReportedWidth = (uint16_t) (m_Width * m_PixelAspect + 0.5);
  8140. // TODO Mike: m_ReportedH/W is never set back to m_H/W, CHECK!
  8141. TRACEKEYVALS("m_Width","%d",m_Width);
  8142. TRACEKEYVALS("m_Height","%d",m_Height);
  8143. TRACEKEYVALS("m_ReportedWidth","%d",m_ReportedWidth);
  8144. TRACEKEYVALS("m_ReportedHeight","%d",m_ReportedHeight);
  8145. TRACEKEYVALS("PreMult[0]","%f",VALUE(m_PreMultipliers[0]));
  8146. TRACEKEYVALS("PreMult[1]","%f",VALUE(m_PreMultipliers[1]));
  8147. TRACEKEYVALS("PreMult[2]","%f",VALUE(m_PreMultipliers[2]));
  8148. TRACEKEYVALS("PreMult[3]","%f",VALUE(m_PreMultipliers[3]));
  8149. #ifdef TRACE_ORIGIN
  8150. TRACEKEYVALS("PreMult File","%s",m_PreMultipliers[0].File);
  8151. TRACEKEYVALS("PreMult Line","%d",m_PreMultipliers[0].Line);
  8152. #endif
  8153. TRACEKEYVALS("D65Mult[0]","%f",VALUE(m_D65Multipliers[0]));
  8154. TRACEKEYVALS("D65Mult[1]","%f",VALUE(m_D65Multipliers[1]));
  8155. TRACEKEYVALS("D65Mult[2]","%f",VALUE(m_D65Multipliers[2]));
  8156. TRACEKEYVALS("D65Mult[3]","%f",VALUE(m_D65Multipliers[3]));
  8157. #ifdef TRACE_ORIGIN
  8158. TRACEKEYVALS("D65Mult File","%s",m_D65Multipliers[0].File);
  8159. TRACEKEYVALS("D65Mult Line","%d",m_D65Multipliers[0].Line);
  8160. #endif
  8161. TRACEKEYVALS("Colors","%d",m_Colors);
  8162. TRACEKEYVALS("Filters","%x",m_Filters);
  8163. TRACEKEYVALS("Flip","%x",m_Flip);
  8164. // Cache the image after Phase1.
  8165. FREE(m_Image_AfterPhase1);
  8166. m_Image_AfterPhase1 =
  8167. (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8168. merror (m_Image_AfterPhase1, "main()");
  8169. memcpy(m_Image_AfterPhase1,m_Image,m_OutHeight*m_OutWidth*sizeof(*m_Image));
  8170. // Some other stuff to cache.
  8171. m_Filters_AfterPhase1 = m_Filters;
  8172. m_BlackLevel_AfterPhase1 = m_BlackLevel;
  8173. for (int k=0; k<8; k++) m_CBlackLevel_AfterPhase1[k] = m_CBlackLevel[k];
  8174. m_WhiteLevel_AfterPhase1 = m_WhiteLevel;
  8175. m_Width_AfterPhase1 = m_Width;
  8176. m_Height_AfterPhase1 = m_Height;
  8177. m_OutWidth_AfterPhase1 = m_OutWidth;
  8178. m_OutHeight_AfterPhase1 = m_OutHeight;
  8179. return 0;
  8180. }
  8181. ////////////////////////////////////////////////////////////////////////////////
  8182. //
  8183. // RunDcRaw_Phase2
  8184. //
  8185. // Color scaling.
  8186. // Interpolation.
  8187. // Green mixing.
  8188. //
  8189. ////////////////////////////////////////////////////////////////////////////////
  8190. short CLASS RunDcRaw_Phase2(const short NoCache) {
  8191. // Make sure we are starting from the right image.
  8192. if (NoCache) {
  8193. FREE(m_Image_AfterPhase1);
  8194. } else {
  8195. FREE(m_Image);
  8196. m_Width = m_Width_AfterPhase1;
  8197. m_Height = m_Height_AfterPhase1;
  8198. m_OutWidth = m_OutWidth_AfterPhase1;
  8199. m_OutHeight = m_OutHeight_AfterPhase1;
  8200. m_Image =
  8201. (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8202. merror (m_Image, "main()");
  8203. memcpy(m_Image,m_Image_AfterPhase1,m_OutHeight*m_OutWidth*sizeof(*m_Image));
  8204. // Restore some other cached values.
  8205. m_Filters = m_Filters_AfterPhase1;
  8206. m_BlackLevel = m_BlackLevel_AfterPhase1;
  8207. for (int k=0; k<8; k++) m_CBlackLevel[k] = m_CBlackLevel_AfterPhase1[k];
  8208. m_WhiteLevel = m_WhiteLevel_AfterPhase1;
  8209. }
  8210. m_Fuji_Width = m_IsFuji;
  8211. unsigned i = m_CBlackLevel[3];
  8212. for (int c=0; c<3; c++) if (i > m_CBlackLevel[c]) i = m_CBlackLevel[c];
  8213. for (int c=0; c<4; c++) m_CBlackLevel[c] -= i;
  8214. m_BlackLevel += i;
  8215. if (m_UserSetting_BlackPoint >= 0) m_BlackLevel = m_UserSetting_BlackPoint;
  8216. for (int c=0; c<4; c++) m_CBlackLevel[c] += m_BlackLevel;
  8217. if (m_UserSetting_Saturation > 0) m_WhiteLevel = m_UserSetting_Saturation;
  8218. // If m_UserSetting_HalfSize then the BAYER(row,col) macro
  8219. // will map 2X2 pixels of the Bayer array, directly onto one
  8220. // pixel of the image (and the correct color channel) foregoing
  8221. // the need for interpolation and much faster !
  8222. m_Shrink = m_Filters && m_UserSetting_HalfSize;
  8223. TRACEKEYVALS("Shrink","%d",m_Shrink);
  8224. TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
  8225. TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
  8226. TRACEKEYVALS("Colors","%d",m_Colors);
  8227. TRACEKEYVALS("Phase2 begin Width","%d",m_Width);
  8228. TRACEKEYVALS("Phase2 begin Height","%d",m_Height);
  8229. TRACEKEYVALS("Phase2 begin OutWidth","%d",m_OutWidth);
  8230. TRACEKEYVALS("Phase2 begin OutHeight","%d",m_OutHeight);
  8231. // Crop for detail view
  8232. if (m_UserSetting_DetailView == 1 &&
  8233. m_IsFuji == 0 &&
  8234. m_PixelAspect == 1.0f) {
  8235. ptCrop();
  8236. }
  8237. // Copied from earlier to here also.
  8238. // Enables Phase3 to reenter with a different FourColorRGB setting.
  8239. if ((m_UserSetting_Quality == ptInterpolation_VNG4 || m_UserSetting_HalfSize)
  8240. && m_Filters != 0) { // m_Filters==0 <-> 3 channel RAWs
  8241. m_MixGreen = 1;
  8242. } else {
  8243. m_MixGreen = 0;
  8244. }
  8245. if (!m_IsFoveon && m_UserSetting_AdjustMaximum > 0) {
  8246. ptAdjustMaximum(1-m_UserSetting_AdjustMaximum);
  8247. }
  8248. assert (!m_IsFoveon);
  8249. // if (m_IsFoveon ) foveon_interpolate();
  8250. if (m_UserSetting_GreenEquil) {
  8251. TRACEKEYVALS("Green equilibration","%s","");
  8252. green_equilibrate((float)m_UserSetting_GreenEquil/100.0f);
  8253. }
  8254. if (m_UserSetting_HotpixelReduction) {
  8255. TRACEKEYVALS("Hotpixel reduction on bayer","%s","");
  8256. ptHotpixelReductionBayer();
  8257. }
  8258. if (m_UserSetting_CfaLineDn !=0) {
  8259. TRACEKEYVALS("Cfa line denoise","%s","");
  8260. cfa_linedn(0.00002*(float)m_UserSetting_CfaLineDn);
  8261. }
  8262. if (!m_IsFoveon) {
  8263. ptScaleColors();
  8264. }
  8265. if (m_UserSetting_CaCorrect !=0) {
  8266. TRACEKEYVALS("CA correction","%s","");
  8267. CA_correct(m_UserSetting_CaRed,m_UserSetting_CaBlue);
  8268. }
  8269. TRACEKEYVALS("Colors","%d",m_Colors);
  8270. // not 1:1 pipe, use FC marco instead of interpolation
  8271. uint16_t (*TempImage)[4];
  8272. if (m_Shrink && m_Filters != 2) { // -> preinterpolate will set m_Filters = 0 if != 2
  8273. m_OutHeight = (m_Height + 1) / 2;
  8274. m_OutWidth = (m_Width + 1) / 2;
  8275. TempImage = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *TempImage);
  8276. merror (TempImage, "main()");
  8277. #pragma omp parallel for schedule(static)
  8278. for (uint16_t row=0; row < m_Height; row++) {
  8279. for (uint16_t col=0; col < m_Width; col++) {
  8280. TempImage[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][FC(row,col)] =
  8281. m_Image[(row)*m_Width + (col)][FC(row,col)];
  8282. }
  8283. }
  8284. FREE(m_Image);
  8285. m_Image = TempImage;
  8286. }
  8287. // RG1BG2 -> RGB (if not 4 colors needed later on)
  8288. pre_interpolate();
  8289. TRACEKEYVALS("Colors","%d",m_Colors);
  8290. // Interpolation/demosaicing according to one of the algorithms.
  8291. if (m_Filters) {
  8292. if (m_UserSetting_BayerDenoise && !m_UserSetting_HalfSize) {
  8293. if (m_UserSetting_BayerDenoise==1) fbdd(0);
  8294. else if (m_UserSetting_BayerDenoise==2) fbdd(1);
  8295. }
  8296. if (m_Filters == 2) // for 3x3 pattern we fix to VNG
  8297. vng_interpolate();
  8298. else if (m_UserSetting_Quality == ptInterpolation_Linear)
  8299. lin_interpolate();
  8300. else if (m_UserSetting_Quality == ptInterpolation_VNG ||
  8301. m_UserSetting_Quality == ptInterpolation_VNG4)
  8302. vng_interpolate();
  8303. else if (m_UserSetting_Quality == ptInterpolation_PPG)
  8304. ppg_interpolate();
  8305. else if (m_UserSetting_Quality == ptInterpolation_DCB)
  8306. dcb(m_UserSetting_InterpolationPasses, 1);
  8307. else if (m_UserSetting_Quality == ptInterpolation_DCBSoft)
  8308. dcb_interpolate_soft_old(m_UserSetting_InterpolationPasses, 1);
  8309. else if (m_UserSetting_Quality == ptInterpolation_DCBSharp)
  8310. dcb_interpolate_sharp_old(m_UserSetting_InterpolationPasses, 1);
  8311. else if (m_UserSetting_Quality == ptInterpolation_AHD)
  8312. ahd_interpolate();
  8313. else if (m_UserSetting_Quality == ptInterpolation_AHD_mod)
  8314. ahd_interpolate_mod();
  8315. else if (m_UserSetting_Quality == ptInterpolation_VCD)
  8316. vcd_interpolate(12);
  8317. else if (m_UserSetting_Quality == ptInterpolation_LMMSE)
  8318. lmmse_interpolate(1);
  8319. else if (m_UserSetting_Quality == ptInterpolation_AMaZE)
  8320. amaze_demosaic();
  8321. } else {
  8322. if (m_UserSetting_HotpixelReduction && m_UserSetting_HalfSize) {
  8323. TRACEKEYVALS("Hotpixel reduction on RGB","%s","");
  8324. ptHotpixelReduction();
  8325. }
  8326. if (m_UserSetting_BayerDenoise && !m_UserSetting_HalfSize) {
  8327. if (m_UserSetting_BayerDenoise==1) fbdd(0);
  8328. else if (m_UserSetting_BayerDenoise==2) fbdd(1);
  8329. }
  8330. }
  8331. // If 1:1 and no interpolation is chosen show the Bayer pattern.
  8332. TRACEKEYVALS("Interpolation type","%d",m_UserSetting_Quality);
  8333. // Additional photivo stuff. Other halvings on request.
  8334. if (m_UserSetting_HalfSize > 1 ||
  8335. (m_UserSetting_HalfSize == 1 && m_Shrink == 0) || // 3 channel RAWs
  8336. (m_UserSetting_HalfSize == 1 && m_Filters == 2)) { // 3x3 pattern
  8337. short Factor = m_UserSetting_HalfSize - 1;
  8338. if (m_Shrink == 0 || m_Filters == 2) Factor += 1;
  8339. uint16_t NewHeight = m_Height >> Factor;
  8340. uint16_t NewWidth = m_Width >> Factor;
  8341. short Step = 1 << Factor;
  8342. int Average = 2 * Factor;
  8343. uint16_t (*NewImage)[4] =
  8344. (uint16_t (*)[4]) CALLOC(NewWidth*NewHeight,sizeof(*m_Image));
  8345. ptMemoryError(NewImage,__FILE__,__LINE__);
  8346. #pragma omp parallel for schedule(static)
  8347. for (uint16_t Row=0; Row < NewHeight*Step; Row+=Step) {
  8348. for (uint16_t Col=0; Col < NewWidth*Step; Col+=Step) {
  8349. uint32_t PixelValue[4] = {0,0,0,0};
  8350. for (uint8_t sRow=0; sRow < Step; sRow++) {
  8351. for (uint8_t sCol=0; sCol < Step; sCol++) {
  8352. int32_t index = (Row+sRow)*m_Width+Col+sCol;
  8353. for (short c=0; c < 4; c++) {
  8354. PixelValue[c] += m_Image[index][c];
  8355. }
  8356. }
  8357. }
  8358. for (short c=0; c < 4; c++) {
  8359. NewImage[Row/Step*NewWidth+Col/Step][c]
  8360. = PixelValue[c] >> Average;
  8361. }
  8362. }
  8363. }
  8364. FREE(m_Image);
  8365. m_Height = m_OutHeight = NewHeight;
  8366. m_Width = m_OutWidth = NewWidth;
  8367. m_Image = NewImage;
  8368. }
  8369. // Green mixing
  8370. if (m_MixGreen && m_Colors != 3) {
  8371. #pragma omp parallel for schedule(static) default(shared)
  8372. for (uint32_t i=0; i < (uint32_t) m_Height*m_Width; i++)
  8373. m_Image[i][1] = (m_Image[i][1] + m_Image[i][3]) >> 1;
  8374. m_Colors = 3;
  8375. }
  8376. // Median filter.
  8377. if (!m_IsFoveon && m_Colors == 3) {
  8378. if (m_UserSetting_MedianPasses > 0) median_filter_new();
  8379. if (m_UserSetting_ESMedianPasses > 0 && !m_UserSetting_HalfSize) es_median_filter();
  8380. if (m_UserSetting_EeciRefine == 1) refinement();
  8381. }
  8382. // Additional cleaning with hotpixel reduction
  8383. if (m_UserSetting_HotpixelReduction && m_UserSetting_Quality != ptInterpolation_Bayer) {
  8384. ptHotpixelReduction();
  8385. }
  8386. // XXX JDLA Additional steps for Fuji
  8387. // And they don't hurt for others as they are early stopped.
  8388. fuji_rotate();
  8389. stretch();
  8390. // Crop for detail view
  8391. if (m_UserSetting_DetailView == 1 &&
  8392. (m_IsFuji != 0 ||
  8393. m_PixelAspect != 1.0f)) {
  8394. ptCrop();
  8395. }
  8396. // Cache the image after Phase2.
  8397. FREE(m_Image_AfterPhase2);
  8398. m_Image_AfterPhase2 =
  8399. (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8400. merror (m_Image_AfterPhase2, "main()");
  8401. memcpy(m_Image_AfterPhase2,m_Image,m_OutHeight*m_OutWidth*sizeof(*m_Image));
  8402. // Some other stuff to cache.
  8403. m_Filters_AfterPhase2 = m_Filters;
  8404. TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
  8405. TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
  8406. TRACEKEYVALS("Colors","%d",m_Colors);
  8407. TRACEKEYVALS("Filters","%x",m_Filters);
  8408. TRACEKEYVALS("Phase2 end Width","%d",m_Width);
  8409. TRACEKEYVALS("Phase2 end Height","%d",m_Height);
  8410. TRACEKEYVALS("Phase2 end OutWidth","%d",m_OutWidth);
  8411. TRACEKEYVALS("Phase2 end OutHeight","%d",m_OutHeight);
  8412. return 0;
  8413. }
  8414. ////////////////////////////////////////////////////////////////////////////////
  8415. //
  8416. // RunDcRaw_Phase3
  8417. //
  8418. // Highlights
  8419. //
  8420. ////////////////////////////////////////////////////////////////////////////////
  8421. short CLASS RunDcRaw_Phase3(const short NoCache) {
  8422. // Make sure we are starting from the right image.
  8423. if (NoCache) {
  8424. FREE(m_Image_AfterPhase2);
  8425. } else {
  8426. FREE(m_Image);
  8427. m_Image =
  8428. (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8429. merror (m_Image, "main()");
  8430. memcpy(m_Image,m_Image_AfterPhase2,m_OutHeight*m_OutWidth*sizeof(*m_Image));
  8431. // Restore some other cached values.
  8432. m_Filters = m_Filters_AfterPhase2;
  8433. }
  8434. TRACEKEYVALS("CamMult[0]","%f",VALUE(m_CameraMultipliers[0]));
  8435. TRACEKEYVALS("CamMult[1]","%f",VALUE(m_CameraMultipliers[1]));
  8436. TRACEKEYVALS("CamMult[2]","%f",VALUE(m_CameraMultipliers[2]));
  8437. TRACEKEYVALS("CamMult[3]","%f",VALUE(m_CameraMultipliers[3]));
  8438. #ifdef TRACE_ORIGIN
  8439. TRACEKEYVALS("CamMult File","%s",m_CameraMultipliers[0].File);
  8440. TRACEKEYVALS("CamMult Line","%d",m_CameraMultipliers[0].Line);
  8441. #endif
  8442. ptHighlight(m_UserSetting_photivo_ClipMode,
  8443. m_UserSetting_photivo_ClipParameter);
  8444. // Cache the image after Phase3.
  8445. FREE(m_Image_AfterPhase3);
  8446. m_Image_AfterPhase3 =
  8447. (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *m_Image);
  8448. merror (m_Image_AfterPhase3, "main()");
  8449. memcpy(m_Image_AfterPhase3,m_Image,m_OutHeight*m_OutWidth*sizeof(*m_Image));
  8450. // Some other stuff to cache.
  8451. m_Filters_AfterPhase3 = m_Filters;
  8452. return 0;
  8453. }
  8454. ////////////////////////////////////////////////////////////////////////////////
  8455. //
  8456. // BlendHighlights
  8457. // (original from dcraw TODO Refine and analyse)
  8458. //
  8459. ////////////////////////////////////////////////////////////////////////////////
  8460. void CLASS ptBlendHighlights() {
  8461. int ClipLevel=INT_MAX;
  8462. int i;
  8463. int j;
  8464. static const float trans[2][4][4] =
  8465. { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
  8466. { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
  8467. static const float itrans[2][4][4] =
  8468. { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
  8469. { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
  8470. float Cam[2][4], lab[2][4], Sum[2], chratio;
  8471. const int transIdx = m_Colors - 3;
  8472. assert(transIdx > -1);
  8473. if (transIdx > 1) return;
  8474. // to shut up gcc warnings...
  8475. const int localColors = ptMin(static_cast<int>(m_Colors), 4);
  8476. for (short c=0; c<m_Colors; c++) {
  8477. if (ClipLevel > (i = (int)(0xFFFF*VALUE(m_PreMultipliers[c])))) {
  8478. ClipLevel = i;
  8479. }
  8480. }
  8481. for (uint16_t Row=0; Row < m_Height; Row++) {
  8482. for (uint16_t Column=0; Column < m_Width; Column++) {
  8483. short c;
  8484. for (c=0; c<m_Colors; c++) {
  8485. if (m_Image[Row*m_Width+Column][c] > ClipLevel) break;
  8486. }
  8487. if (c == m_Colors) continue; // No clip
  8488. for (c=0; c<m_Colors; c++) {
  8489. Cam[0][c] = m_Image[Row*m_Width+Column][c];
  8490. Cam[1][c] = MIN(Cam[0][c],(float)ClipLevel);
  8491. }
  8492. for (i=0; i < 2; i++) {
  8493. for (c=0; c<m_Colors; c++) {
  8494. for (lab[i][c]=j=0; j < m_Colors; j++) {
  8495. lab[i][c] += trans[transIdx][c][j] * Cam[i][j];
  8496. }
  8497. }
  8498. for (Sum[i]=0,c=1; c < m_Colors; c++) {
  8499. Sum[i] += SQR(lab[i][c]);
  8500. }
  8501. }
  8502. chratio = sqrt(Sum[1]/Sum[0]);
  8503. for (c = 1; c < m_Colors; c++) {
  8504. lab[0][c] *= chratio;
  8505. }
  8506. for (c = 0; (c < localColors); c++) {
  8507. for (Cam[0][c]=j=0; (j < localColors); j++) {
  8508. Cam[0][c] += itrans[transIdx][c][j] * lab[0][j];
  8509. }
  8510. }
  8511. for (c = 0; c < m_Colors; c++) {
  8512. m_Image[Row*m_Width+Column][c] = (uint16_t)(Cam[0][c] / m_Colors);
  8513. }
  8514. }
  8515. }
  8516. }
  8517. ////////////////////////////////////////////////////////////////////////////////
  8518. //
  8519. // Hotpixel reduction
  8520. //
  8521. ////////////////////////////////////////////////////////////////////////////////
  8522. void CLASS ptHotpixelReduction() {
  8523. uint16_t HotpixelThreshold = 0x00ff;
  8524. uint16_t Threshold = (int32_t) ((1.0-m_UserSetting_HotpixelReduction)*0x2fff);
  8525. uint16_t Width = m_OutWidth;
  8526. uint16_t Height = m_OutHeight;
  8527. // bei 1:2 oder kleiner m_Image hat in jedem Punkt RGBG
  8528. // bei 1:1 m_Image hat Bayer Pattern
  8529. // Länge und Breite OutWidth und OutHeight
  8530. // unterschieptiche pixel in unterschieptichen ebenen ansprechen und werte zur luminanz skalieren
  8531. #pragma omp parallel for schedule(static) default(shared)
  8532. for (uint16_t Row=0; Row<Height; Row++) {
  8533. for (uint16_t Col=0; Col<Width; Col++) {
  8534. uint16_t TempValue = 0;
  8535. for (int c=0; c<4; c++) {
  8536. if (m_Image[Row*Width+Col][c] > HotpixelThreshold) {
  8537. if (Row > 1) TempValue = MAX(m_Image[(Row-1)*Width+Col][c],TempValue);
  8538. if (Row < Height-1) TempValue = MAX(m_Image[(Row+1)*Width+Col][c],TempValue);
  8539. if (Col > 1) TempValue = MAX(m_Image[Row*Width+Col-1][c],TempValue);
  8540. if (Col < Width-1) TempValue = MAX(m_Image[Row*Width+Col+1][c],TempValue);
  8541. if (TempValue+Threshold<m_Image[Row*Width+Col][c])
  8542. m_Image[Row*Width+Col][c] = TempValue;
  8543. }
  8544. if (m_Image[Row*Width+Col][c] < 10*HotpixelThreshold) {
  8545. TempValue = 0xffff;
  8546. if (Row > 1) TempValue = MIN(m_Image[(Row-1)*Width+Col][c],TempValue);
  8547. if (Row < Height-1) TempValue = MIN(m_Image[(Row+1)*Width+Col][c],TempValue);
  8548. if (Col > 1) TempValue = MIN(m_Image[Row*Width+Col-1][c],TempValue);
  8549. if (Col < Width-1) TempValue = MIN(m_Image[Row*Width+Col+1][c],TempValue);
  8550. if (TempValue-Threshold>m_Image[Row*Width+Col][c])
  8551. m_Image[Row*Width+Col][c] = TempValue;
  8552. }
  8553. }
  8554. }
  8555. }
  8556. }
  8557. void CLASS ptHotpixelReductionBayer() {
  8558. uint16_t HotpixelThreshold = 0x00ff;
  8559. uint16_t Threshold = (int32_t) ((1.0-m_UserSetting_HotpixelReduction)*0x2fff);
  8560. uint16_t Width = m_OutWidth;
  8561. uint16_t Height = m_OutHeight;
  8562. #pragma omp parallel for schedule(static)
  8563. for (uint16_t Row=0; Row<Height; Row++) {
  8564. for (uint16_t Col=0; Col<Width; Col++) {
  8565. uint16_t TempValue = 0;
  8566. for (int Channel=0; Channel<4; Channel++) {
  8567. if (m_Image[Row*Width+Col][Channel] > HotpixelThreshold) {
  8568. if (Row > 2) TempValue = MAX(m_Image[(Row-2)*Width+Col][Channel],TempValue);
  8569. if (Row < Height-2) TempValue = MAX(m_Image[(Row+2)*Width+Col][Channel],TempValue);
  8570. if (Col > 2) TempValue = MAX(m_Image[Row*Width+Col-2][Channel],TempValue);
  8571. if (Col < Width-2) TempValue = MAX(m_Image[Row*Width+Col+2][Channel],TempValue);
  8572. if (TempValue+Threshold<m_Image[Row*Width+Col][Channel]) {
  8573. for (int c=0; c<4; c++) {
  8574. if (Row > 1) {
  8575. TempValue = MAX(m_Image[(Row-1)*Width+Col][c],TempValue);
  8576. if (Col > 1) TempValue = MAX(m_Image[(Row-1)*Width+Col-1][c],TempValue);
  8577. if (Col < Width-1) TempValue = MAX(m_Image[(Row-1)*Width+Col+1][c],TempValue);
  8578. }
  8579. if (Row < Height-1) {
  8580. TempValue = MAX(m_Image[(Row+1)*Width+Col][c],TempValue);
  8581. if (Col > 1) TempValue = MAX(m_Image[(Row+1)*Width+Col-1][c],TempValue);
  8582. if (Col < Width-1) TempValue = MAX(m_Image[(Row+1)*Width+Col+1][c],TempValue);
  8583. }
  8584. if (Col > 1) TempValue = MAX(m_Image[Row*Width+Col-1][c],TempValue);
  8585. if (Col < Width-1) TempValue = MAX(m_Image[Row*Width+Col+1][c],TempValue);
  8586. }
  8587. if (TempValue+Threshold<m_Image[Row*Width+Col][Channel])
  8588. m_Image[Row*Width+Col][Channel] = TempValue;
  8589. }
  8590. }
  8591. }
  8592. for (int Channel=0; Channel<4; Channel++) {
  8593. if (m_Image[Row*Width+Col][Channel] < 10*HotpixelThreshold) {
  8594. TempValue = 0xffff;
  8595. if (Row > 2) TempValue = MIN(m_Image[(Row-2)*Width+Col][Channel],TempValue);
  8596. if (Row < Height-2) TempValue = MIN(m_Image[(Row+2)*Width+Col][Channel],TempValue);
  8597. if (Col > 2) TempValue = MIN(m_Image[Row*Width+Col-2][Channel],TempValue);
  8598. if (Col < Width-2) TempValue = MIN(m_Image[Row*Width+Col+2][Channel],TempValue);
  8599. if (TempValue-Threshold>m_Image[Row*Width+Col][Channel]) {
  8600. for (int c=0; c<4; c++) {
  8601. if (Row > 1) {
  8602. TempValue = MIN(m_Image[(Row-1)*Width+Col][c],TempValue);
  8603. if (Col > 1) TempValue = MIN(m_Image[(Row-1)*Width+Col-1][c],TempValue);
  8604. if (Col < Width-1) TempValue = MIN(m_Image[(Row-1)*Width+Col+1][c],TempValue);
  8605. }
  8606. if (Row < Height-1) {
  8607. TempValue = MIN(m_Image[(Row+1)*Width+Col][c],TempValue);
  8608. if (Col > 1) TempValue = MIN(m_Image[(Row+1)*Width+Col-1][c],TempValue);
  8609. if (Col < Width-1) TempValue = MIN(m_Image[(Row+1)*Width+Col+1][c],TempValue);
  8610. }
  8611. if (Col > 1) TempValue = MIN(m_Image[Row*Width+Col-1][c],TempValue);
  8612. if (Col < Width-1) TempValue = MIN(m_Image[Row*Width+Col+1][c],TempValue);
  8613. }
  8614. if (TempValue-Threshold>m_Image[Row*Width+Col][Channel])
  8615. m_Image[Row*Width+Col][Channel] = TempValue;
  8616. }
  8617. }
  8618. }
  8619. }
  8620. }
  8621. }
  8622. ////////////////////////////////////////////////////////////////////////////////
  8623. //
  8624. // Crop for detail view
  8625. //
  8626. ////////////////////////////////////////////////////////////////////////////////
  8627. inline uint16_t MultOf6(uint16_t AValue) {
  8628. return ptMax(AValue - (AValue % 6), 0);
  8629. }
  8630. void CLASS ptCrop() {
  8631. assert (m_UserSetting_HalfSize == 0);
  8632. uint16_t (*TempImage)[4];
  8633. uint16_t CropW = m_UserSetting_DetailViewCropW;
  8634. uint16_t CropH = m_UserSetting_DetailViewCropH;
  8635. uint16_t CropX = m_UserSetting_DetailViewCropX;
  8636. uint16_t CropY = m_UserSetting_DetailViewCropY;
  8637. if (m_Filters == 2) { // for 3x3 pattern
  8638. CropW = MultOf6(CropW);
  8639. CropH = MultOf6(CropH);
  8640. CropX = MultOf6(CropX);
  8641. CropY = MultOf6(CropY);
  8642. }
  8643. if (m_Flip & 2) {
  8644. CropX = m_Height - CropX - CropW;
  8645. }
  8646. if (m_Flip & 1) {
  8647. CropY = m_Width - CropY - CropH;
  8648. }
  8649. if (m_Flip & 4) {
  8650. SWAP(CropW, CropH);
  8651. SWAP(CropX, CropY);
  8652. }
  8653. m_OutHeight = CropH;
  8654. m_OutWidth = CropW;
  8655. TempImage = (uint16_t (*)[4]) CALLOC (m_OutHeight*m_OutWidth, sizeof *TempImage);
  8656. merror (TempImage, "Temp for detail view");
  8657. #pragma omp parallel for schedule(static)
  8658. for (uint16_t row=0; row < m_OutHeight; row++) {
  8659. for (uint16_t col=0; col < m_OutWidth; col++) {
  8660. for (short c=0; c<4; c++) {
  8661. TempImage[row *m_OutWidth + col][c] =
  8662. m_Image[(row+CropY)*m_Width + (col+CropX)][c];
  8663. }
  8664. }
  8665. }
  8666. m_Width = m_OutWidth;
  8667. m_Height = m_OutHeight;
  8668. FREE(m_Image);
  8669. m_Image = TempImage;
  8670. TRACEKEYVALS("Phase2 detail view Width","%d",m_Width);
  8671. TRACEKEYVALS("Phase2 detail view Height","%d",m_Height);
  8672. TRACEKEYVALS("Phase2 detail view OutWidth","%d",m_OutWidth);
  8673. TRACEKEYVALS("Phase2 detail view OutHeight","%d",m_OutHeight);
  8674. }
  8675. ////////////////////////////////////////////////////////////////////////////////
  8676. //
  8677. // MedianFilter
  8678. // Repeatepty 3x3 median filter on R-G and B-G channels
  8679. // Repeat : m_UserSetting_MedianPasses
  8680. //
  8681. ////////////////////////////////////////////////////////////////////////////////
  8682. void CLASS ptMedianFilter() {
  8683. int Median[9];
  8684. static const uint8_t opt[] = /* Optimal 9-element median search */
  8685. { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
  8686. 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
  8687. for (short Pass=1; Pass <= m_UserSetting_MedianPasses; Pass++) {
  8688. for (short c=0; c < 3; c+=2) {
  8689. #pragma omp parallel for schedule(static) default(shared)
  8690. for (int32_t i = 0; i< (int32_t)m_Width*m_Height; i++) {
  8691. m_Image[i][3] = m_Image[i][c];
  8692. }
  8693. #pragma omp parallel for schedule(static) default(shared) private(Median)
  8694. for (int32_t n=m_Width; n<m_Width*(m_Height-1); n++) {
  8695. if ((n+1) % m_Width < 2) continue;
  8696. short k=0;
  8697. for (int32_t i = -m_Width; i <= m_Width; i += m_Width) {
  8698. for (int32_t j = i-1; j <= i+1; j++) {
  8699. Median[k++] = m_Image[n+j][3] - m_Image[n+j][1];
  8700. }
  8701. }
  8702. for (unsigned short i=0; i < sizeof opt; i+=2) {
  8703. if (Median[opt[i]] > Median[opt[i+1]]) {
  8704. SWAP (Median[opt[i]] , Median[opt[i+1]]);
  8705. }
  8706. }
  8707. m_Image[n][c] = CLIP(Median[4] + m_Image[n][1]);
  8708. }
  8709. }
  8710. }
  8711. }
  8712. ////////////////////////////////////////////////////////////////////////////////
  8713. //
  8714. // WaveletDenoise
  8715. // (original from dcraw TODO Refine and analyse)
  8716. // Be aware :
  8717. // Changes m_WhiteLevel
  8718. // Changes m_Blacklevel
  8719. //
  8720. ////////////////////////////////////////////////////////////////////////////////
  8721. void CLASS ptWaveletDenoise() {
  8722. static const float Noise[] =
  8723. { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
  8724. int Scale=1;
  8725. int lev, hpass, lpass, wlast, blk[2];
  8726. TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
  8727. TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
  8728. while (m_WhiteLevel << Scale < 0x10000) Scale++;
  8729. m_WhiteLevel <<= --Scale;
  8730. m_BlackLevel <<= Scale;
  8731. for (int c=0; c<4; c++) m_CBlackLevel[c] <<= Scale;
  8732. TRACEKEYVALS("Scale(denoise)","%d",Scale);
  8733. TRACEKEYVALS("BlackLevel","%d",m_BlackLevel);
  8734. TRACEKEYVALS("WhiteLevel","%d",m_WhiteLevel);
  8735. uint32_t Size = m_OutHeight*m_OutWidth;
  8736. float *fImage = (float*)
  8737. MALLOC((Size*3 +m_OutHeight+ m_OutWidth)* sizeof(*fImage));
  8738. merror(fImage,"WaveletDenoise()");
  8739. float* fTemp = fImage + Size*3;
  8740. short NrColors = m_Colors;
  8741. if (NrColors == 3 && m_Filters) NrColors++;
  8742. for (short c=0; c<NrColors; c++) { /* deNoise R,G1,B,G3 individually */
  8743. for (uint32_t i=0; i < Size; i++) {
  8744. fImage[i] = 256 * sqrt((unsigned) (m_Image[i][c] << Scale));
  8745. }
  8746. for (hpass=lev=0; lev < 5; lev++) {
  8747. lpass = Size*((lev & 1)+1);
  8748. for (uint16_t Row=0; Row < m_OutHeight; Row++) {
  8749. hat_transform(fTemp,fImage+hpass+Row*m_OutWidth,1,m_OutWidth,1<<lev);
  8750. for (uint16_t Col=0; Col < m_OutWidth; Col++) {
  8751. fImage[lpass + Row*m_OutWidth + Col] = fTemp[Col] * 0.25;
  8752. }
  8753. }
  8754. for (uint16_t Col=0; Col < m_OutWidth; Col++) {
  8755. hat_transform(fTemp,fImage+lpass+Col,m_OutWidth,m_OutHeight,1<<lev);
  8756. for (uint16_t Row=0; Row < m_OutHeight; Row++) {
  8757. fImage[lpass + Row*m_OutWidth + Col] = fTemp[Row] * 0.25;
  8758. }
  8759. }
  8760. float Threshold = m_UserSetting_DenoiseThreshold * Noise[lev];
  8761. for (uint32_t i=0; i < Size; i++) {
  8762. fImage[hpass+i] -= fImage[lpass+i];
  8763. if (fImage[hpass+i] < -Threshold) {
  8764. fImage[hpass+i] += Threshold;
  8765. } else if (fImage[hpass+i] > Threshold) {
  8766. fImage[hpass+i] -= Threshold;
  8767. } else {
  8768. fImage[hpass+i] = 0;
  8769. }
  8770. if (hpass) {
  8771. fImage[i] += fImage[hpass+i];
  8772. }
  8773. }
  8774. hpass = lpass;
  8775. }
  8776. for (uint32_t i=0; i < Size; i++) {
  8777. m_Image[i][c] = CLIP((int32_t)(SQR(fImage[i]+fImage[lpass+i])/0x10000));
  8778. }
  8779. }
  8780. if (m_Filters && m_Colors == 3) { /* pull G1 and G3 closer together */
  8781. float Multiplier[2];
  8782. for (uint16_t Row=0; Row < 2; Row++) {
  8783. Multiplier[Row] = 0.125 *
  8784. VALUE(m_PreMultipliers[FC(Row+1,0) | 1]) /
  8785. VALUE(m_PreMultipliers[FC(Row,0) | 1]);
  8786. blk[Row] = m_CBlackLevel[FC(Row,0) | 1];
  8787. }
  8788. uint16_t* Window[4];
  8789. for (short i=0; i < 4; i++) {
  8790. Window[i] = (uint16_t *) fImage + m_Width*i;
  8791. }
  8792. wlast = -1;
  8793. for (uint16_t Row=1; Row < m_Height-1; Row++) {
  8794. while (wlast < Row+1) {
  8795. wlast++;
  8796. for (short i=0; i < 4; i++) {
  8797. Window[(i+3) & 3] = Window[i];
  8798. }
  8799. for (uint16_t Col = FC(wlast,1) & 1; Col < m_Width; Col+=2) {
  8800. Window[2][Col] = BAYER(wlast,Col);
  8801. }
  8802. }
  8803. float Threshold = m_UserSetting_DenoiseThreshold/512;
  8804. float Average;
  8805. float Difference;
  8806. for (uint16_t Col = (FC(Row,0) & 1)+1; Col < m_Width-1; Col+=2) {
  8807. Average = ( Window[0][Col-1] + Window[0][Col+1] +
  8808. Window[2][Col-1] + Window[2][Col+1] - blk[~Row & 1]*4 )
  8809. * Multiplier[Row & 1]
  8810. + (Window[1][Col] + blk[Row & 1]) * 0.5;
  8811. Average = Average < 0 ? 0 : sqrt(Average);
  8812. Difference = sqrt(BAYER(Row,Col)) - Average;
  8813. if (Difference < -Threshold) {
  8814. Difference += Threshold;
  8815. } else if (Difference > Threshold) {
  8816. Difference -= Threshold;
  8817. } else {
  8818. Difference = 0;
  8819. }
  8820. BAYER(Row,Col) = CLIP((int32_t)(SQR(Average+Difference) + 0.5));
  8821. }
  8822. }
  8823. }
  8824. FREE(fImage);
  8825. }
  8826. ////////////////////////////////////////////////////////////////////////////////
  8827. //
  8828. // RebuildHighlights
  8829. // (original from dcraw TODO Refine and analyse)
  8830. //
  8831. ////////////////////////////////////////////////////////////////////////////////
  8832. #define SCALE (4 >> m_Shrink)
  8833. void CLASS ptRebuildHighlights(const short highlight) {
  8834. float *map, sum, wgt, grow;
  8835. int hsat[4], count, spread, change, val, i;
  8836. unsigned high, wide, mrow, mcol, row, col, d, y, x;
  8837. uint16_t *pixel;
  8838. static const signed char dir[8][2] =
  8839. { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
  8840. grow = pow (2, 1-highlight);
  8841. for (short c=0;c<m_Colors;c++) hsat[c] = (int)(32000 * VALUE(m_PreMultipliers[c]));
  8842. short kc = 0;
  8843. for (short c=1; c < m_Colors; c++)
  8844. if (VALUE(m_PreMultipliers[kc]) < VALUE(m_PreMultipliers[c])) kc = c;
  8845. high = m_Height / SCALE;
  8846. wide = m_Width / SCALE;
  8847. map = (float *) CALLOC (high*wide, sizeof *map);
  8848. merror (map, "recover_highlights()");
  8849. for (short c=0;c<m_Colors;c++) {
  8850. if (c != kc) {
  8851. memset (map, 0, high*wide*sizeof *map);
  8852. #pragma omp parallel for schedule(static) private(mrow, mcol, sum, wgt, count, pixel, row, col)
  8853. for (mrow=0; mrow < high; mrow++) {
  8854. for (mcol=0; mcol < wide; mcol++) {
  8855. sum = wgt = count = 0;
  8856. for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) {
  8857. for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
  8858. pixel = m_Image[row*m_Width+col];
  8859. if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
  8860. sum += pixel[c];
  8861. wgt += pixel[kc];
  8862. count++;
  8863. }
  8864. }
  8865. if (count == SCALE*SCALE) map[mrow*wide+mcol] = sum / wgt;
  8866. }
  8867. }
  8868. }
  8869. for (spread = (int)(32/grow); spread--; ) {
  8870. #pragma omp parallel for schedule(static) private(mrow, mcol, sum, count, x, y, d)
  8871. for (mrow=0; mrow < high; mrow++) {
  8872. for (mcol=0; mcol < wide; mcol++) {
  8873. if (map[mrow*wide+mcol]) continue;
  8874. sum = count = 0;
  8875. for (d=0; d < 8; d++) {
  8876. y = mrow + dir[d][0];
  8877. x = mcol + dir[d][1];
  8878. if (y < high && x < wide && map[y*wide+x] > 0) {
  8879. sum += (1 + (d & 1)) * map[y*wide+x];
  8880. count += 1 + (d & 1);
  8881. }
  8882. }
  8883. if (count > 3)
  8884. map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
  8885. }
  8886. }
  8887. change = 0;
  8888. #pragma omp parallel for schedule(static) private(i) reduction(||:change)
  8889. for (i=0; i < (int)(high*wide); i++) {
  8890. if (map[i] < 0) {
  8891. map[i] = -map[i];
  8892. change = 1;
  8893. }
  8894. }
  8895. if (!change) break;
  8896. }
  8897. #pragma omp parallel for schedule(static) private(i)
  8898. for (i=0; i < (int)(high*wide); i++) {
  8899. if (map[i] == 0) map[i] = 1;
  8900. }
  8901. #pragma omp parallel for schedule(static) private(mrow, mcol, row, col, pixel, val)
  8902. for (mrow=0; mrow < high; mrow++) {
  8903. for (mcol=0; mcol < wide; mcol++) {
  8904. for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) {
  8905. for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
  8906. pixel = m_Image[row*m_Width+col];
  8907. if (pixel[c] / hsat[c] > 1) {
  8908. val = (int)(pixel[kc] * map[mrow*wide+mcol]);
  8909. if (pixel[c] < val) pixel[c] = CLIP(val);
  8910. }
  8911. }
  8912. }
  8913. }
  8914. }
  8915. }
  8916. }
  8917. FREE (map);
  8918. }
  8919. #undef SCALE
  8920. ////////////////////////////////////////////////////////////////////////////////
  8921. //
  8922. // LabToCam helper function.
  8923. //
  8924. // FIXME
  8925. // At this moment this is verbatim copies of ptImage.cpp. Room for improvement.
  8926. //
  8927. ////////////////////////////////////////////////////////////////////////////////
  8928. void CLASS LabToCam(double Lab[3],uint16_t Cam[4]) {
  8929. if(!ToCamFunctionInited) {
  8930. for(short i=0;i<m_Colors;i++) {
  8931. for (short j=0;j<3;j++) {
  8932. MatrixXYZToCam[i][j] = 0.0;
  8933. for (short k=0;k<3;k++) {
  8934. MatrixXYZToCam[i][j] +=
  8935. m_MatrixSRGBToCamRGB[i][k] * MatrixXYZToRGB[ptSpace_sRGB_D65][k][j];
  8936. }
  8937. }
  8938. }
  8939. ToCamFunctionInited = 1;
  8940. }
  8941. double xyz[3];
  8942. double fx,fy,fz;
  8943. double xr,yr,zr;
  8944. const double epsilon = 216.0/24389.0;
  8945. const double kappa = 24389.0/27.0;
  8946. const double L = Lab[0];
  8947. const double a = Lab[1];
  8948. const double b = Lab[2];
  8949. const double Tmp1 = (L+16.0)/116.0;
  8950. yr = (L<=kappa*epsilon)?
  8951. (L/kappa):(Tmp1*Tmp1*Tmp1);
  8952. fy = (yr<=epsilon) ? ((kappa*yr+16.0)/116.0) : Tmp1;
  8953. fz = fy - b/200.0;
  8954. fx = a/500.0 + fy;
  8955. const double fz3 = fz*fz*fz;
  8956. const double fx3 = fx*fx*fx;
  8957. zr = (fz3<=epsilon) ? ((116.0*fz-16.0)/kappa) : fz3;
  8958. xr = (fx3<=epsilon) ? ((116.0*fx-16.0)/kappa) : fx3;
  8959. xyz[0] = xr*D65Reference[0]*65535.0 - 0.5;
  8960. xyz[1] = yr*D65Reference[1]*65535.0 - 0.5;
  8961. xyz[2] = zr*D65Reference[2]*65535.0 - 0.5;
  8962. // And finally to RGB via the matrix.
  8963. for (short c=0; c<m_Colors; c++) {
  8964. double Value = 0;
  8965. Value += MatrixXYZToCam[c][0] * xyz[0];
  8966. Value += MatrixXYZToCam[c][1] * xyz[1];
  8967. Value += MatrixXYZToCam[c][2] * xyz[2];
  8968. Cam[c] = (uint16_t) CLIP((int32_t)(Value));
  8969. }
  8970. }
  8971. ////////////////////////////////////////////////////////////////////////////////
  8972. //
  8973. // CamToLab helper function.
  8974. //
  8975. ////////////////////////////////////////////////////////////////////////////////
  8976. void CLASS CamToLab(uint16_t Cam[4], double Lab[3]) {
  8977. // Initialize the lookup table for the RGB->LAB function
  8978. // if this would be the first time.
  8979. if (!ToLABFunctionInited) {
  8980. // Remark : we extend the table well beyond r>1.0 for numerical
  8981. // stability purposes. XYZ>1.0 occurs sometimes and this way
  8982. // it stays stable (srgb->lab->srgb correct within 0.02%)
  8983. for (uint32_t i=0; i<0x20000; i++) {
  8984. double r = (double)(i) / 0xffff;
  8985. ToLABFunctionTable[i] = r > 216.0/24389.0 ?
  8986. pow(r,1/3.0) :
  8987. (24389.0/27.0*r + 16.0)/116.0;
  8988. }
  8989. for(short i=0;i<3;i++) {
  8990. for (short j=0;j<m_Colors;j++) {
  8991. MatrixCamToXYZ[i][j] = 0.0;
  8992. for (short k=0;k<3;k++) {
  8993. MatrixCamToXYZ[i][j] +=
  8994. MatrixRGBToXYZ[ptSpace_sRGB_D65][i][k] * m_MatrixCamRGBToSRGB[k][j];
  8995. }
  8996. }
  8997. }
  8998. ToLABFunctionInited = 1;
  8999. }
  9000. // First go to XYZ
  9001. double xyz[3] = {0.5,0.5,0.5};
  9002. for (short Color = 0; Color < m_Colors; Color++) {
  9003. xyz[0] += MatrixCamToXYZ[0][Color] * Cam[Color];
  9004. xyz[1] += MatrixCamToXYZ[1][Color] * Cam[Color];
  9005. xyz[2] += MatrixCamToXYZ[2][Color] * Cam[Color];
  9006. }
  9007. // Reference White
  9008. xyz[0] /= D65Reference[0];
  9009. xyz[1] /= D65Reference[1];
  9010. xyz[2] /= D65Reference[2];
  9011. // Then to Lab
  9012. xyz[0] = ToLABFunctionTable[ (int32_t) MAX(0.0,xyz[0]) ];
  9013. xyz[1] = ToLABFunctionTable[ (int32_t) MAX(0.0,xyz[1]) ];
  9014. xyz[2] = ToLABFunctionTable[ (int32_t) MAX(0.0,xyz[2]) ];
  9015. // L in 0 , a in 1, b in 2
  9016. Lab[0] = 116.0 * xyz[1] - 16.0;
  9017. Lab[1] = 500.0*(xyz[0]-xyz[1]);
  9018. Lab[2] = 200.0*(xyz[1]-xyz[2]);
  9019. }
  9020. //==============================================================================
  9021. TImage8RawData ptDcRaw::thumbnail() {
  9022. m_Thumb.clear();
  9023. if(m_InputFile && m_LoadRawFunction) {
  9024. fseek (m_InputFile, m_ThumbOffset, SEEK_SET);
  9025. (this->*m_WriteThumb)();
  9026. }
  9027. return m_Thumb;
  9028. }