/Sources/ptDcRaw.cpp
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
Large files files are truncated, but you can click here to view the full file
- /*******************************************************************************
- **
- ** Photivo
- **
- ** Copyright (C) 2008,2009 Jos De Laender <jos.de_laender@telenet.be>
- ** Copyright (C) 2009-2012 Michael Munzert <mail@mm-log.com>
- ** Copyright (C) 2011 Bernd Schoeler <brjohn@brother-john.net>
- **
- ** This file is part of Photivo.
- **
- ** Photivo is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License version 3
- ** as published by the Free Software Foundation.
- **
- ** Photivo is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with Photivo. If not, see <http://www.gnu.org/licenses/>.
- **
- *******************************************************************************/
- /*
- ** This is basically the translation into a more or less C++ object of
- ** dcraw.c -- Dave Coffin's raw photo decoder
- ** Copyright 1997-2008 by Dave Coffin, dcoffin a cybercom o net
- **
- *******************************************************************************/
-
- #include "ptDcRaw.h"
-
- #include "ptDefines.h"
- #include "ptError.h"
- #include "ptConstants.h"
- #include "ptCalloc.h"
-
- #include <cassert>
-
- #define NO_JASPER
- #ifndef NO_JASPER
- #include <jasper/jasper.h>
- #endif
-
- // Macro fix for explicit fread returnvalue check.
- #define ptfread(ptr,size,n,stream) \
- { \
- size_t RV = fread(ptr,size,n,stream); \
- if (RV != (size_t) n) assert(!ferror(stream)); \
- }
- #define ptfwrite(ptr,size,n,stream) \
- { \
- size_t RV = fwrite(ptr,size,n,stream); \
- assert(RV == (size_t) n); \
- }
- #define ptfscanf(file,format,arg) \
- { \
- int RV = fscanf(file,format,arg); \
- assert (RV == 1); \
- }
- #define ptfgets(str,num,file) \
- { \
- char* RV = fgets(str,num,file); \
- assert (RV); \
- }
-
- inline void VAppend(TImage8RawData &AVector, char* AArray, const int ALength) {
- char* hEnd = AArray + ALength * sizeof(char);
- AVector.insert(AVector.end(), AArray, hEnd);
- }
-
- // The class.
- #define CLASS ptDcRaw::
- CLASS ptDcRaw() {
- //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
-
- // This were the original global variables initialized.
- // Now moved into constructor.
- // All m_UserSetting* are obviously ,uh, usersettings
- // that were done via the command line parameters.
- m_UserSetting_ShotSelect=0;
- m_UserSetting_MaxMultiplier=0;
- m_UserSetting_Multiplier[0]=0;
- m_UserSetting_Multiplier[1]=0;
- m_UserSetting_Multiplier[2]=0;
- m_UserSetting_Multiplier[3]=0;
- m_UserSetting_HalfSize=0;
- m_UserSetting_HotpixelReduction=0;
- m_UserSetting_BayerDenoise=0;
- m_UserSetting_CfaLineDn=0;
- m_UserSetting_GreenEquil=0;
- m_UserSetting_CaCorrect=0;
- m_UserSetting_CaRed=0;
- m_UserSetting_CaBlue=0;
- m_UserSetting_AutoWb=0;
- m_UserSetting_CameraWb=0;
- m_UserSetting_CameraMatrix=-1;
- m_UserSetting_GreyBox[0] = 0;
- m_UserSetting_GreyBox[1] = 0;
- m_UserSetting_GreyBox[2] = 0xFFFF;
- m_UserSetting_GreyBox[3] = 0xFFFF;
- m_UserSetting_photivo_ClipMode = ptClipMode_Clip;
- m_UserSetting_photivo_ClipParameter = 0;
- m_UserSetting_Quality = 3;
- m_UserSetting_BlackPoint = -1;
- m_UserSetting_Saturation = -1;
- m_UserSetting_InputFileName = NULL;
- m_UserSetting_DetailView = 0;
- m_UserSetting_DetailViewCropX = 0;
- m_UserSetting_DetailViewCropY = 0;
- m_UserSetting_DetailViewCropW = 0;
- m_UserSetting_DetailViewCropH = 0;
- m_UserSetting_BadPixelsFileName = NULL;
- m_UserSetting_DarkFrameFileName = NULL;
- m_UserSetting_AdjustMaximum = 0;
- m_UserSetting_DenoiseThreshold = 0;
- m_UserSetting_InterpolationPasses = 0;
- m_UserSetting_MedianPasses = 0;
- m_UserSetting_ESMedianPasses = 0;
-
-
- // Safety settings to have NULL on uninitialized images.
- m_Image = NULL;
- m_Image_AfterPhase1 = NULL;
- m_Image_AfterPhase2 = NULL;
- m_Image_AfterPhase3 = NULL;
- m_Image_AfterPhase4 = NULL;
-
- // Some other pointers that are in a dynamic environment better NULL.
- m_MetaData = NULL;
- m_InputFile = NULL;
-
- m_Thumb.clear();
- ResetNonUserSettings();
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Destructor
- // Deallocate everything dynamic.
- //
- ////////////////////////////////////////////////////////////////////////////////
-
- CLASS ~ptDcRaw() {
-
- //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,__PRETTY_FUNCTION__);
-
- FREE(m_UserSetting_InputFileName);
- FREE(m_UserSetting_BadPixelsFileName);
- FREE(m_UserSetting_DarkFrameFileName);
- FREE(m_Image);
- FREE(m_Image_AfterPhase1);
- FREE(m_Image_AfterPhase2);
- FREE(m_Image_AfterPhase3);
- FCLOSE(m_InputFile);
- FREE(m_MetaData);
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // ResetNonUserSettings
- // Reset all variables except user settings.
- // This is for second entry support.
- //
- ////////////////////////////////////////////////////////////////////////////////
-
- void CLASS ResetNonUserSettings() {
- // Safety settings to have NULL on uninitialized images.
- // And freeing the underlying memory (which was long time a leak !)
- // FREE(NULL) is safe, so the beginsituation is fine too.
- // FREE implies setting of the pointer to NULL
- FREE(m_Image);
- FREE(m_Image_AfterPhase1);
- FREE(m_Image_AfterPhase2);
- FREE(m_Image_AfterPhase3);
- FREE(m_Image_AfterPhase4);
-
- // Some other pointers that are in a dynamic environment better NULL.
- // Same remarks as above.
- FREE(m_MetaData);
- FCLOSE(m_InputFile);
-
- // This was originally in the identify code, but which is called
- // anyway in the beginning. So this is simply global initialization like
- // anything else.
-
- m_Tiff_Flip = m_Flip = -1; /* 0 is valid, so -1 is unknown */
- m_Filters = (unsigned)(-1); // hack not to change dcraw.
- m_RawHeight = m_RawWidth = m_Fuji_Width = m_IsFuji = fuji_layout = cr2_slice[0] = 0;
- m_WhiteLevel = m_Height = m_Width = m_TopMargin = m_LeftMargin = 0;
- m_ColorDescriptor[0] = m_Description[0] = m_Artist[0] = m_CameraMake[0] = m_CameraModel[0] = m_CameraModelBis[0] = 0;
- m_IsoSpeed = m_Shutter = m_Aperture = m_FocalLength = unique_id = 0;
- m_Tiff_NrIFDs = 0;
- memset (m_Tiff_IFD, 0, sizeof m_Tiff_IFD);
- memset (white, 0, sizeof white);
- m_ThumbOffset = m_ThumbLength = m_ThumbWidth = m_ThumbHeight = 0;
- m_LoadRawFunction = m_ThumbLoadRawFunction = 0;
- m_WriteThumb = &CLASS jpeg_thumb;
- m_Data_Offset = m_MetaLength = m_Tiff_bps = m_Tiff_Compress = 0;
- m_Kodak_cbpp = zero_after_ff = m_DNG_Version = m_Load_Flags = 0;
- m_TimeStamp = m_ShotOrder = m_Tiff_Samples = m_BlackLevel = m_IsFoveon = 0;
- for (int k=0; k<8; k++) m_CBlackLevel[k] = 0;
- m_MixGreen = m_ProfileLength = data_error = m_ZeroIsBad = 0;
- m_PixelAspect = m_IsRaw = m_RawColor = 1; m_RawColorPhotivo = 0;
- m_TileWidth = m_TileLength = 0;
- m_Raw_Image = 0;
- memset (m_Mask, 0, sizeof m_Mask);
- for (int i=0; i < 4; i++) {
- short c;
- ASSIGN(m_CameraMultipliers[i], i == 1);
- ASSIGN(m_PreMultipliers[i], i < 3);
- ASSIGN(m_D65Multipliers[i], i < 3);
- for (c=0; c<3; c++) m_cmatrix[c][i] = 0;
- for (c=0; c<3; c++) m_MatrixCamRGBToSRGB[c][i] = c == i;
- }
- m_Colors = 3;
- for (int i=0; i < 0x10000; i++) m_Curve[i] = i;
-
- m_Gamma[0] = 0.45;
- m_Gamma[1] = 4.50;
- m_Gamma[2] = 0;
- m_Gamma[3] = 0;
- m_Gamma[4] = 0;
- m_Gamma[5] = 0;
-
- m_getbithuff_bitbuf=0;
- m_getbithuff_reset=0;
- m_getbithuff_vbits=0;
- m_ph1_bithuffbitbuf=0;
- m_ph1_bithuffvbits=0;
- for (int i = 0; i < 0x4000; i++) m_pana_bits_buf[i] = 0;
- m_pana_bits_vbits = 0;
- for (int i = 0; i < 4096; i++) jpeg_buffer[i] = 0;
- for (int i = 0; i < 128; i++) m_sony_decrypt_pad[i] = 0;
- m_sony_decrypt_p = 0;
- for (int i = 0; i < 1024; i++) m_foveon_decoder_huff[i] = 0;
-
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 3; j++) {
- MatrixXYZToCam[i][j] = 0.0;
- }
- }
-
- ToCamFunctionInited = 0;
- for (int i = 0; i < 0x20000; i++) ToLABFunctionTable[i] = 0.0;
- ToLABFunctionInited = 0;
-
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 4; j++) {
- MatrixCamToXYZ[i][j] = 0.0;
- }
- }
-
- }
-
- /*
- In order to inline this calculation, I make the risky
- assumption that all filter patterns can be described
- by a repeating pattern of eight rows and two columns
-
- Do not use the FC or BAYER macros with the Leaf CatchLight,
- because its pattern is 16x16, not 2x8.
-
- Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
-
- PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
- 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
-
- 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
- 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M
- 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C
- 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
- 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
- 4 C Y C Y C Y 4 Y C Y C Y C
- PowerShot A5 5 G M G M G M 5 G M G M G M
- 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
- 7 M G M G M G 7 M G M G M G
- 0 1 2 3 4 5
- 0 C Y C Y C Y
- 1 G M G M G M
- 2 C Y C Y C Y
- 3 M G M G M G
-
- All RGB cameras use one of these Bayer grids:
-
- 0x16161616: 0x61616161: 0x49494949: 0x94949494:
-
- 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
- 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
- 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
- 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
- 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
- */
-
- #define RAW(row,col) \
- m_Raw_Image[(row)*m_RawWidth+(col)]
-
- #define FC(row,col) \
- (m_Filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
-
- #define BAYER(row,col) \
- m_Image[(row)*m_Width + (col)][FC(row,col)]
- // old: m_Image[((row) >> m_Shrink)*m_OutWidth + ((col) >> m_Shrink)][FC(row,col)]
-
- #define BAYER2(row,col) \
- m_Image[(row)*m_Width + (col)][fcol(row,col)]
-
- int CLASS fcol (int row, int col)
- {
- static const char filter[16][16] =
- { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
- { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
- { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
- { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
- { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
- { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
- { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
- { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
- { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
- { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
- { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
- { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
- { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
- { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
- { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
- { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
- static const char filter2[6][6] =
- { { 1,1,0,1,1,2 },
- { 1,1,2,1,1,0 },
- { 2,0,1,0,2,1 },
- { 1,1,2,1,1,0 },
- { 1,1,0,1,1,2 },
- { 0,2,1,2,0,1 } };
-
- if (m_Filters == 1) return filter[(row+m_TopMargin)&15][(col+m_LeftMargin)&15];
- if (m_Filters == 2) return filter2[(row+6) % 6][(col+6) % 6];
- return FC(row,col);
- }
-
- #ifndef __GLIBC__
- char* CLASS my_memmem (char *haystack, size_t haystacklen,
- char *neepte, size_t neeptelen)
- {
- char *c;
- for (c = haystack; c <= haystack + haystacklen - neeptelen; c++)
- if (!memcmp (c, neepte, neeptelen))
- return c;
- return 0;
- }
- #define memmem my_memmem
- #endif
-
- float rgb_cam[3][4];
- const double xyz_rgb[3][3] = { /* XYZ from RGB */
- { 0.412453, 0.357580, 0.180423 },
- { 0.212671, 0.715160, 0.072169 },
- { 0.019334, 0.119193, 0.950227 } };
- const float d65_white[3] = { 0.950456, 1, 1.088754 };
-
- // Now everything importent is set up, so we can include external demosaicers
- #include "dcb/dcb_demosaicing.c"
- #include "dcb/dcb_demosaicing_old.c"
- #include "vcd/ahd_interpolate_mod.c"
- #include "vcd/ahd_partial_interpolate.c"
- #include "vcd/refinement.c"
- #include "vcd/vcd_interpolate.c"
- #include "vcd/es_median_filter.c"
- #include "vcd/median_filter_new.c"
- #include "perfectraw/lmmse_interpolate.c"
- #include "rawtherapee/amaze_interpolate.c"
- #include "rawtherapee/cfa_line_dn.c"
- #include "rawtherapee/ca_correct.c"
- #include "rawtherapee/green_equil.c"
-
- void CLASS merror (void *ptr, const char *where)
- {
- if (ptr) return;
- fprintf (stderr,_("%s: Out of memory in %s\n"), m_UserSetting_InputFileName, where);
- longjmp (m_Failure, 1);
- }
-
- void CLASS derror()
- {
- if (!data_error) {
- fprintf (stderr, "%s: ", m_UserSetting_InputFileName);
- if (feof(m_InputFile))
- fprintf (stderr,_("Unexpected end of file\n"));
- else
- //fprintf (stderr,_("Corrupt data near 0x%lx\n"), (int64_t) ftell(m_InputFile));
- fprintf (stderr,_("Corrupt data near 0x%lx\n"), (long unsigned int) ftell(m_InputFile));
- }
- data_error++;
- }
-
- uint16_t CLASS sget2 (uint8_t *s)
- {
- if (m_ByteOrder == 0x4949) /* "II" means little-endian */
- return s[0] | s[1] << 8;
- else /* "MM" means big-endian */
- return s[0] << 8 | s[1];
- }
-
- uint16_t CLASS get2()
- {
- uint8_t str[2] = { 0xff,0xff };
- ptfread (str, 1, 2, m_InputFile);
- return sget2(str);
- }
-
- unsigned CLASS sget4 (uint8_t *s)
- {
- if (m_ByteOrder == 0x4949)
- return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
- else
- return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
- }
- #define sget4(s) sget4((uint8_t *)s)
-
- unsigned CLASS get4()
- {
- uint8_t str[4] = { 0xff,0xff,0xff,0xff };
- ptfread (str, 1, 4, m_InputFile);
- return sget4(str);
- }
-
- unsigned CLASS getint (int type)
- {
- return type == 3 ? get2() : get4();
- }
-
- float CLASS int_to_float (int i)
- {
- union { int i; float f; } u;
- u.i = i;
- return u.f;
- }
-
- double CLASS getreal (int type)
- {
- union { char c[8]; double d; } u;
- int i, rev;
-
- switch (type) {
- case 3: return (unsigned short) get2();
- case 4: return (unsigned int) get4();
- case 5: u.d = (unsigned int) get4();
- return u.d / (unsigned int) get4();
- case 8: return (signed short) get2();
- case 9: return (signed int) get4();
- case 10: u.d = (signed int) get4();
- return u.d / (signed int) get4();
- case 11: return int_to_float (get4());
- case 12:
- rev = 7 * ((m_ByteOrder == 0x4949) == (ntohs(0x1234) == 0x1234));
- for (i=0; i < 8; i++)
- u.c[i ^ rev] = fgetc(m_InputFile);
- return u.d;
- default: return fgetc(m_InputFile);
- }
- }
-
- void CLASS read_shorts (uint16_t *pixel, int count)
- {
- if (fread (pixel, 2, count, m_InputFile) < (size_t) count) derror();
- if ((m_ByteOrder == 0x4949) == (ntohs(0x1234) == 0x1234))
- swab ((char *)pixel, (char *)pixel, count*2);
- }
-
- /* -> 1438
- void CLASS canon_black (double dark[2], int nblack)
- {
- int c, diff, row, col;
-
- if (!nblack) return;
- for (c=0; c<2; c++) dark[c] /= nblack >> 1;
- if ((diff = (int)(dark[0] - dark[1])))
- for (row=0; row < m_Height; row++)
- for (col=1; col < m_Width; col+=2)
- BAYER(row,col) += diff;
- dark[1] += diff;
- m_BlackLevel = (unsigned)((dark[0] + dark[1] + 1) / 2);
- }
- */
-
- void CLASS canon_600_fixed_wb (int temp)
- {
- static const short mul[4][5] = {
- { 667, 358,397,565,452 },
- { 731, 390,367,499,517 },
- { 1119, 396,348,448,537 },
- { 1399, 485,431,508,688 } };
- int lo, hi, i;
- float frac=0;
-
- for (lo=4; --lo; )
- if (*mul[lo] <= temp) break;
- for (hi=0; hi < 3; hi++)
- if (*mul[hi] >= temp) break;
- if (lo != hi)
- frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
- for (i=1; i < 5; i++)
- ASSIGN(m_D65Multipliers[i-1],1/(frac * mul[hi][i] + (1-frac) * mul[lo][i]));
- }
-
- /* Return values: 0 = white 1 = near white 2 = not white */
- int CLASS canon_600_color (int ratio[2], int mar)
- {
- int clipped=0, target, miss;
-
- if (flash_used) {
- if (ratio[1] < -104)
- { ratio[1] = -104; clipped = 1; }
- if (ratio[1] > 12)
- { ratio[1] = 12; clipped = 1; }
- } else {
- if (ratio[1] < -264 || ratio[1] > 461) return 2;
- if (ratio[1] < -50)
- { ratio[1] = -50; clipped = 1; }
- if (ratio[1] > 307)
- { ratio[1] = 307; clipped = 1; }
- }
- target = flash_used || ratio[1] < 197
- ? -38 - (398 * ratio[1] >> 10)
- : -123 + (48 * ratio[1] >> 10);
- if (target - mar <= ratio[0] &&
- target + 20 >= ratio[0] && !clipped) return 0;
- miss = target - ratio[0];
- if (abs(miss) >= mar*4) return 2;
- if (miss < -20) miss = -20;
- if (miss > mar) miss = mar;
- ratio[0] = target - miss;
- return 1;
- }
-
- void CLASS canon_600_auto_wb()
- {
- int mar, row, col, i, j, st, count[] = { 0,0 };
- int test[8], total[2][8], ratio[2][2], stat[2];
-
- memset (&total, 0, sizeof total);
- i = int ( canon_ev + 0.5 );
- if (i < 10) mar = 150;
- else if (i > 12) mar = 20;
- else mar = 280 - 20 * i;
- if (flash_used) mar = 80;
- for (row=14; row < m_Height-14; row+=4)
- for (col=10; col < m_Width; col+=2) {
- for (i=0; i < 8; i++)
- test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
- BAYER(row+(i >> 1),col+(i & 1));
- for (i=0; i < 8; i++)
- if (test[i] < 150 || test[i] > 1500) goto next;
- for (i=0; i < 4; i++)
- if (abs(test[i] - test[i+4]) > 50) goto next;
- for (i=0; i < 2; i++) {
- for (j=0; j < 4; j+=2)
- ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
- stat[i] = canon_600_color (ratio[i], mar);
- }
- if ((st = stat[0] | stat[1]) > 1) goto next;
- for (i=0; i < 2; i++)
- if (stat[i])
- for (j=0; j < 2; j++)
- test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
- for (i=0; i < 8; i++)
- total[st][i] += test[i];
- count[st]++;
- next: ;
- }
- if (count[0] | count[1]) {
- st = count[0]*200 < count[1];
- for (i=0; i < 4; i++)
- ASSIGN(m_D65Multipliers[i], 1.0 / (total[st][i] + total[st][i+4]));
- }
- }
-
- void CLASS canon_600_coeff()
- {
- static const short table[6][12] = {
- { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
- { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 },
- { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 },
- { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 },
- { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
- { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } };
- int t=0, i, c;
- float mc, yc;
-
- mc = VALUE(m_D65Multipliers[1]) / VALUE(m_D65Multipliers[2]);
- yc = VALUE(m_D65Multipliers[3]) / VALUE(m_D65Multipliers[2]);
- if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
- if (mc > 1.28 && mc <= 2) {
- if (yc < 0.8789) t=3;
- else if (yc <= 2) t=4;
- }
- if (flash_used) t=5;
- for (m_RawColor = i=0; i < 3; i++)
- for (c=0; c < m_Colors; c++)
- m_MatrixCamRGBToSRGB[i][c] = table[t][i*4 + c] / 1024.0;
- }
-
- void CLASS canon_600_load_raw()
- {
- uint8_t data[1120], *dp;
- uint16_t *pix;
- int irow, row;
-
- for (irow=row=0; irow < m_Height; irow++) {
- if (fread (data, 1, 1120, m_InputFile) < 1120) derror();
- pix = m_Raw_Image + row*m_RawWidth;
- for (dp=data; dp < data+1120; dp+=10, pix+=8) {
- pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
- pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
- pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
- pix[3] = (dp[4] << 2) + (dp[1] & 3);
- pix[4] = (dp[5] << 2) + (dp[9] & 3);
- pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
- pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
- pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
- }
- if ((row+=2) > m_Height) row = 1;
- }
- }
-
- void CLASS canon_600_correct()
- {
- int row, col, val;
- static const short mul[4][2] =
- { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
-
- for (row=0; row < m_Height; row++)
- for (col=0; col < m_Width; col++) {
- if ((val = BAYER(row,col) - m_BlackLevel) < 0) val = 0;
- val = val * mul[row & 3][col & 1] >> 9;
- BAYER(row,col) = val;
- }
- canon_600_fixed_wb(1311);
- canon_600_auto_wb();
- canon_600_coeff();
- m_WhiteLevel = (0x3ff - m_BlackLevel) * 1109 >> 9;
- m_BlackLevel = 0;
- }
-
- int CLASS canon_s2is()
- {
- unsigned row;
-
- for (row=0; row < 100; row++) {
- fseek (m_InputFile, row*3340 + 3284, SEEK_SET);
- if (getc(m_InputFile) > 15) return 1;
- }
- return 0;
- }
-
- /*
- getbits(-1) initializes the buffer
- getbits(n) where 0 <= n <= 25 returns an n-bit integer
- */
- unsigned CLASS getbithuff(int nbits,uint16_t *huff)
- {
- // unsigned c;
- int c;
-
- if (nbits == -1)
- return m_getbithuff_bitbuf = m_getbithuff_vbits = m_getbithuff_reset = 0;
- if (nbits == 0 || m_getbithuff_vbits < 0) return 0;
- while (!m_getbithuff_reset && m_getbithuff_vbits < nbits && (c = fgetc(m_InputFile)) != EOF &&
- !(m_getbithuff_reset = zero_after_ff && c == 0xff && fgetc(m_InputFile))) {
- m_getbithuff_bitbuf = (m_getbithuff_bitbuf << 8) + (uint8_t) c;
- m_getbithuff_vbits += 8;
- }
- c = m_getbithuff_bitbuf << (32-m_getbithuff_vbits) >> (32-nbits);
- if (huff) {
- m_getbithuff_vbits -= huff[c] >> 8;
- c = (uint8_t) huff[c];
- } else
- m_getbithuff_vbits -= nbits;
- if (m_getbithuff_vbits < 0) derror();
- return c;
- }
-
- #define getbits(n) getbithuff(n,0)
- #define gethuff(h) getbithuff(*h,h+1)
-
- /*
- Construct a decode tree according the specification in *source.
- The first 16 bytes specify how many codes should be 1-bit, 2-bit
- 3-bit, etc. Bytes after that are the leaf values.
-
- For example, if the source is
-
- { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
- 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
-
- then the code is
-
- 00 0x04
- 010 0x03
- 011 0x05
- 100 0x06
- 101 0x02
- 1100 0x07
- 1101 0x01
- 11100 0x08
- 11101 0x09
- 11110 0x00
- 111110 0x0a
- 1111110 0x0b
- 1111111 0xff
- */
- uint16_t * CLASS make_decoder_ref (const uint8_t **source)
- {
- int max, len, h, i, j;
- const uint8_t *count;
- uint16_t *huff;
-
- count = (*source += 16) - 17;
- for (max=16; max && !count[max]; max--) {} ;
- huff = (uint16_t *) CALLOC (1 + (1 << max), sizeof *huff);
- merror (huff, "make_decoder()");
- huff[0] = max;
- for (h=len=1; len <= max; len++)
- for (i=0; i < count[len]; i++, ++*source)
- for (j=0; j < 1 << (max-len); j++)
- if (h <= 1 << max)
- huff[h++] = len << 8 | **source;
- return huff;
- }
-
-
- uint16_t * CLASS make_decoder (const uint8_t *source)
- {
- return make_decoder_ref (&source);
- }
-
- void CLASS crw_init_tables (unsigned table, uint16_t *huff[2])
- {
- static const uint8_t first_tree[3][29] = {
- { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
- 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
- { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
- 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
- { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
- 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
- };
- static const uint8_t second_tree[3][180] = {
- { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
- 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
- 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
- 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
- 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
- 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
- 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
- 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
- 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
- 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
- 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
- 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
- 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
- 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
- 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
- { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
- 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
- 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
- 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
- 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
- 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
- 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
- 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
- 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
- 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
- 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
- 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
- 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
- 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
- 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
- { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
- 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
- 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
- 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
- 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
- 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
- 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
- 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
- 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
- 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
- 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
- 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
- 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
- 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
- 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
- };
- if (table > 2) table = 2;
- huff[0] = make_decoder ( first_tree[table]);
- huff[1] = make_decoder (second_tree[table]);
- }
-
- /*
- Return 0 if the image starts with compressed data,
- 1 if it starts with uncompressed low-order bits.
-
- In Canon compressed data, 0xff is always followed by 0x00.
- */
- int CLASS canon_has_lowbits()
- {
- uint8_t test[0x4000];
- int ret=1, i;
-
- fseek (m_InputFile, 0, SEEK_SET);
- ptfread (test, 1, sizeof test, m_InputFile);
- for (i=540; i < (int)(sizeof test) - 1; i++)
- if (test[i] == 0xff) {
- if (test[i+1]) return 1;
- ret=0;
- }
- return ret;
- }
-
- void CLASS canon_load_raw()
- {
- uint16_t *pixel, *prow, *huff[2];
- int nblocks, lowbits, i, c, row, r, save, val;
- int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
-
- crw_init_tables (m_Tiff_Compress,huff);
- lowbits = canon_has_lowbits();
- if (!lowbits) m_WhiteLevel = 0x3ff;
- fseek (m_InputFile, 540 + lowbits*m_RawHeight*m_RawWidth/4, SEEK_SET);
- zero_after_ff = 1;
- getbits(-1);
- for (row=0; row < m_RawHeight; row+=8) {
- pixel = m_Raw_Image + row*m_RawWidth;
- nblocks = MIN (8, m_RawHeight-row) * m_RawWidth >> 6;
- for (block=0; block < nblocks; block++) {
- memset (diffbuf, 0, sizeof diffbuf);
- for (i=0; i < 64; i++ ) {
- leaf = gethuff(huff[i>0]);
- if (leaf == 0 && i) break;
- if (leaf == 0xff) continue;
- i += leaf >> 4;
- len = leaf & 15;
- if (len == 0) continue;
- diff = getbits(len);
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- if (i < 64) diffbuf[i] = diff;
- }
- diffbuf[0] += carry;
- carry = diffbuf[0];
- for (i=0; i < 64; i++ ) {
- if (pnum++ % m_RawWidth == 0)
- base[0] = base[1] = 512;
- if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
- derror();
- }
- }
- if (lowbits) {
- save = ftell(m_InputFile);
- fseek (m_InputFile, 26 + row*m_RawWidth/4, SEEK_SET);
- for (prow=pixel, i=0; i < m_RawWidth*2; i++) {
- c = fgetc(m_InputFile);
- for (r=0; r < 8; r+=2, prow++) {
- val = (*prow << 2) + ((c >> r) & 3);
- if (m_RawWidth == 2672 && val < 512) val += 2;
- *prow = val;
- }
- }
- fseek (m_InputFile, save, SEEK_SET);
- }
- }
- FREE(huff[0]);
- FREE(huff[1]);
- }
-
- /*
- Not a full implementation of Lossless JPEG, just
- enough to decode Canon, Kodak and Adobe DNG images.
- */
- struct jhead {
- int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
- uint16_t *huff[6], *free[4], *row;
- };
-
- int CLASS ljpeg_start (struct jhead *jh, int info_only)
- {
- int c, tag, len;
- uint8_t data[0x10000];
- const uint8_t *dp;
-
- memset (jh, 0, sizeof *jh);
- jh->restart = INT_MAX;
- ptfread (data, 2, 1, m_InputFile);
- if (data[1] != 0xd8) return 0;
- do {
- ptfread (data, 2, 2, m_InputFile);
- tag = data[0] << 8 | data[1];
- len = (data[2] << 8 | data[3]) - 2;
- if (tag <= 0xff00) return 0;
- ptfread (data, 1, len, m_InputFile);
- switch (tag) {
- case 0xffc3:
- jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
- case 0xffc0:
- jh->bits = data[0];
- jh->high = data[1] << 8 | data[2];
- jh->wide = data[3] << 8 | data[4];
- jh->clrs = data[5] + jh->sraw;
- if (len == 9 && !m_DNG_Version) getc(m_InputFile);
- break;
- case 0xffc4:
- if (info_only) break;
- for (dp = data; dp < data+len && (c = *dp++) < 4; )
- jh->free[c] = jh->huff[c] = make_decoder_ref (&dp);
- break;
- case 0xffda:
- jh->psv = data[1+data[0]*2];
- jh->bits -= data[3+data[0]*2] & 15;
- break;
- case 0xffdd:
- jh->restart = data[0] << 8 | data[1];
- }
- } while (tag != 0xffda);
- if (info_only) return 1;
- for (c=0;c<5;c++) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c];
- if (jh->sraw) {
- for (c=0;c<4;c++) jh->huff[2+c] = jh->huff[1];
- for (c=0;c<(jh->sraw);c++) jh->huff[1+c] = jh->huff[0];
- }
- jh->row = (uint16_t *) CALLOC (jh->wide*jh->clrs, 4);
- merror (jh->row, "ljpeg_start()");
- return zero_after_ff = 1;
- }
-
- void CLASS ljpeg_end (struct jhead *jh)
- {
- int c;
- for(c=0;c<4;c++) if (jh->free[c]) FREE (jh->free[c]);
- FREE (jh->row);
- }
-
- int CLASS ljpeg_diff (uint16_t *huff)
- {
- int len, diff;
-
- len = gethuff(huff);
-
- if (len == 16 && (!m_DNG_Version || m_DNG_Version >= 0x1010000))
- return -32768;
- diff = getbits(len);
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - 1;
- return diff;
- }
-
- uint16_t * CLASS ljpeg_row (int jrow, struct jhead *jh)
- {
- int col, c, diff, pred, spred=0;
- uint16_t mark=0, *row[3];
-
- if (jrow * jh->wide % jh->restart == 0) {
- for (c=0;c<6;c++) jh->vpred[c] = 1 << (jh->bits-1);
- if (jrow) {
- fseek(m_InputFile,-2,SEEK_CUR);
- do mark = (mark << 8) + (c = fgetc(m_InputFile));
- while (c != EOF && mark >> 4 != 0xffd);
- }
- getbits(-1);
- }
- for (c=0; c<3; c++) row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
- for (col=0; col < jh->wide; col++)
- for (c=0; c < jh->clrs; c++) {
- diff = ljpeg_diff (jh->huff[c]);
- if (jh->sraw && c <= jh->sraw && (col | c))
- pred = spred;
- else if (col) pred = row[0][-jh->clrs];
- else pred = (jh->vpred[c] += diff) - diff;
- if (jrow && col) switch (jh->psv) {
- case 1: break;
- case 2: pred = row[1][0]; break;
- case 3: pred = row[1][-jh->clrs]; break;
- case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break;
- case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break;
- case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break;
- case 7: pred = (pred + row[1][0]) >> 1; break;
- default: pred = 0;
- }
- if ((**row = pred + diff) >> jh->bits) derror();
- if (c <= jh->sraw) spred = **row;
- row[0]++; row[1]++;
- }
- return row[2];
- }
-
- void CLASS lossless_jpeg_load_raw()
- {
- int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
- struct jhead jh;
- uint16_t *rp;
-
- if (!ljpeg_start (&jh, 0)) return;
- jwide = jh.wide * jh.clrs;
-
- TRACEKEYVALS("jh.high","%d",jh.high);
- TRACEKEYVALS("jwide","%d",jwide);
- for (jrow=0; jrow < jh.high; jrow++) {
- rp = ljpeg_row (jrow, &jh);
- if (m_Load_Flags & 1)
- row = jrow & 1 ? m_Height-1-jrow/2 : jrow/2;
- for (jcol=0; jcol < jwide; jcol++) {
- val = m_Curve[*rp++];
- if (cr2_slice[0]) {
- jidx = jrow*jwide + jcol;
- i = jidx / (cr2_slice[1]*jh.high);
- if ((j = i >= cr2_slice[0]))
- i = cr2_slice[0];
- jidx -= i * (cr2_slice[1]*jh.high);
- row = jidx / cr2_slice[1+j];
- col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
- }
- if (m_RawWidth == 3984 && (col -= 2) < 0)
- col += (row--,m_RawWidth);
- if (row >= 0) RAW(row,col) = val;
- if (++col >= m_RawWidth)
- col = (row++,0);
- }
- }
- ljpeg_end(&jh);
- // printf("TIEDELIE dark[0]:%f dark[1]:%f nblack:%d\n",dark[0],dark[1],nblack);
- }
-
- void CLASS canon_sraw_load_raw()
- {
- struct jhead jh;
- short *rp=0, (*ip)[4];
- int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
- int v[3]={0,0,0}, ver, hue;
- char *cp;
-
- if (!ljpeg_start (&jh, 0)) return;
- jwide = (jh.wide >>= 1) * jh.clrs;
-
- for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
- scol = ecol;
- ecol += cr2_slice[1] * 2 / jh.clrs;
- if (!cr2_slice[0] || ecol > m_RawWidth-1) ecol = m_RawWidth & -2;
- for (row=0; row < m_Height; row += (jh.clrs >> 1) - 1) {
- ip = (short (*)[4]) m_Image + row*m_Width;
- for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
- if ((jcol %= jwide) == 0)
- rp = (short *) ljpeg_row (jrow++, &jh);
- if (col >= m_Width) continue;
- for (c=0; c< (jh.clrs-2); c++)
- ip[col + (c >> 1)*m_Width + (c & 1)][0] = rp[jcol+c];
- ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
- ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
- }
- }
- }
- for (cp=m_CameraModelBis; *cp && !isdigit(*cp); cp++) {};
- sscanf (cp, "%d.%d.%d", v, v+1, v+2);
- ver = (v[0]*1000 + v[1])*1000 + v[2];
- hue = (jh.sraw+1) << 2;
- if (unique_id >= 0x80000281 || (unique_id == 0x80000218 && ver > 1000006))
- hue = jh.sraw << 1;
- ip = (short (*)[4]) m_Image;
- rp = ip[0];
- for (row=0; row < m_Height; row++, ip+=m_Width) {
- if (row & (jh.sraw >> 1))
- for (col=0; col < m_Width; col+=2)
- for (c=1; c < 3; c++)
- if (row == m_Height-1) {
- ip[col][c] = ip[col-m_Width][c];
- } else {
- ip[col][c] = (ip[col-m_Width][c] + ip[col+m_Width][c] + 1) >> 1;
- }
- for (col=1; col < m_Width; col+=2)
- for (c=1; c < 3; c++)
- if (col == m_Width-1)
- ip[col][c] = ip[col-1][c];
- else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
- }
- for ( ; rp < ip[0]; rp+=4) {
- if (unique_id == 0x80000218 ||
- unique_id == 0x80000250 ||
- unique_id == 0x80000261 ||
- unique_id == 0x80000281 ||
- unique_id == 0x80000287) {
- rp[1] = (rp[1] << 2) + hue;
- rp[2] = (rp[2] << 2) + hue;
- pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14);
- pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
- pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
- } else {
- if (unique_id < 0x80000218) rp[0] -= 512;
- pix[0] = rp[0] + rp[2];
- pix[2] = rp[0] + rp[1];
- pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12);
- }
- for (c=0;c<3;c++) rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
- }
- ljpeg_end(&jh);
- m_WhiteLevel = 0x3fff;
- }
-
- void CLASS adobe_copy_pixel (unsigned row, unsigned col, uint16_t **rp)
- {
- int c;
-
- if (m_IsRaw == 2 && m_UserSetting_ShotSelect) (*rp)++;
- if (m_Raw_Image) {
- if (row < m_RawHeight && col < m_RawWidth)
- RAW(row,col) = m_Curve[**rp];
- *rp += m_IsRaw;
- } else {
- if (row < m_Height && col < m_Width)
- for (c=0; c < (int32_t)m_Tiff_Samples; c++)
- m_Image[row*m_Width+col][c] = m_Curve[(*rp)[c]];
- *rp += m_Tiff_Samples;
- }
- if (m_IsRaw == 2 && m_UserSetting_ShotSelect) (*rp)--;
- }
-
- void CLASS lossless_dng_load_raw()
- {
- unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
- struct jhead jh;
- uint16_t *rp;
-
- while (trow < m_RawHeight) {
- save = ftell(m_InputFile);
- if (m_TileLength < INT_MAX)
- fseek (m_InputFile, get4(), SEEK_SET);
- if (!ljpeg_start (&jh, 0)) break;
- jwide = jh.wide;
- if (m_Filters) jwide *= jh.clrs;
- jwide /= m_IsRaw;
- for (row=col=jrow=0; jrow < (unsigned) jh.high; jrow++) {
- rp = ljpeg_row (jrow, &jh);
- for (jcol=0; jcol < jwide; jcol++) {
- adobe_copy_pixel (trow+row, tcol+col, &rp);
- if (++col >= m_TileWidth || col >= m_RawWidth)
- row += 1 + (col = 0);
- }
- }
- fseek (m_InputFile, save+4, SEEK_SET);
- if ((tcol += m_TileWidth) >= m_RawWidth)
- trow += m_TileLength + (tcol = 0);
- ljpeg_end(&jh);
- }
- }
-
- void CLASS packed_dng_load_raw()
- {
- uint16_t *pixel, *rp;
- // int row, col;
- unsigned row, col;
-
- pixel = (uint16_t *) CALLOC (m_RawWidth * m_Tiff_Samples, sizeof *pixel);
- merror (pixel, "packed_dng_load_raw()");
- for (row=0; row < m_RawHeight; row++) {
- if (m_Tiff_bps == 16)
- read_shorts (pixel, m_RawWidth * m_Tiff_Samples);
- else {
- getbits(-1);
- for (col=0; col < m_RawWidth * m_Tiff_Samples; col++)
- pixel[col] = getbits(m_Tiff_bps);
- }
- for (rp=pixel, col=0; col < m_RawWidth; col++)
- adobe_copy_pixel (row, col, &rp);
- }
- FREE (pixel);
- }
-
- void CLASS pentax_load_raw()
- {
- uint16_t bit[2][15], huff[4097];
- int dep, row, col, diff, c, i;
- uint16_t vpred[2][2] = {{0,0},{0,0}}, hpred[2];
-
- fseek (m_InputFile, meta_offset, SEEK_SET);
- dep = (get2() + 12) & 15;
- fseek (m_InputFile, 12, SEEK_CUR);
- for(c=0;c<dep;c++) bit[0][c] = get2();
- for(c=0;c<dep;c++) bit[1][c] = fgetc(m_InputFile);
- for(c=0;c<dep;c++)
- for (i=bit[0][c]; i <= ((bit[0][c]+(4096 >> bit[1][c])-1) & 4095); )
- huff[++i] = bit[1][c] << 8 | c;
- huff[0] = 12;
- fseek (m_InputFile, m_Data_Offset, SEEK_SET);
- getbits(-1);
- for (row=0; row < m_RawHeight; row++)
- for (col=0; col < m_RawWidth; col++) {
- diff = ljpeg_diff (huff);
- if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
- else hpred[col & 1] += diff;
- RAW(row,col) = hpred[col & 1];
- if (hpred[col & 1] >> m_Tiff_bps) derror();
- }
- }
-
- void CLASS nikon_load_raw()
- {
- static const uint8_t nikon_tree[][32] = {
- { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
- 5,4,3,6,2,7,1,0,8,9,11,10,12 },
- { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */
- 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
- { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */
- 5,4,6,3,7,2,8,1,9,0,10,11,12 },
- { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */
- 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
- { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */
- 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
- { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
- 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
- uint16_t *huff, ver0, ver1, vpred[2][2], hpred[2], csize;
- int i, min, max, step=0, tree=0, split=0, row, col, len, shl, diff;
-
- fseek (m_InputFile, meta_offset, SEEK_SET);
- ver0 = fgetc(m_InputFile);
- ver1 = fgetc(m_InputFile);
- if (ver0 == 0x49 || ver1 == 0x58)
- fseek (m_InputFile, 2110, SEEK_CUR);
- if (ver0 == 0x46) tree = 2;
- if (m_Tiff_bps == 14) tree += 3;
- read_shorts (vpred[0], 4);
- max = 1 << m_Tiff_bps & 0x7fff;
- if ((csize = get2()) > 1)
- step = max / (csize-1);
- if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
- for (i=0; i < csize; i++)
- m_Curve[i*step] = get2();
- for (i=0; i < max; i++)
- m_Curve[i] = ( m_Curve[i-i%step]*(step-i%step) +
- m_Curve[i-i%step+step]*(i%step) ) / step;
- fseek (m_InputFile, meta_offset+562, SEEK_SET);
- split = get2();
- } else if (ver0 != 0x46 && csize <= 0x4001)
- read_shorts (m_Curve, max=csize);
- while (m_Curve[max-2] == m_Curve[max-1]) max--;
- huff = make_decoder(nikon_tree[tree]);
- fseek (m_InputFile, m_Data_Offset, SEEK_SET);
- getbits(-1);
- for (min=row=0; row < m_Height; row++) {
- if (split && row == split) {
- FREE(huff);
- huff = make_decoder(nikon_tree[tree+1]);
- max += (min = 16) << 1;
- }
- for (col=0; col < m_RawWidth; col++) {
- i = gethuff(huff);
- len = i & 15;
- shl = i >> 4;
- diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
- if ((diff & (1 << (len-1))) == 0)
- diff -= (1 << len) - !shl;
- if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
- else hpred[col & 1] += diff;
- if ((uint16_t)(hpred[col & 1] + min) >= max) derror();
- RAW(row,col) = m_Curve[LIM((int16_t)hpred[col & 1],(int16_t)0,(int16_t)0x3fff)];
- }
- }
- FREE(huff);
- }
-
- /*
- Returns 1 for a Coolpix 995, 0 for anything else.
- */
- int CLASS nikon_e995()
- {
- int i, histo[256];
- const uint8_t often[] = { 0x00, 0x55, 0xaa, 0xff };
-
- memset (histo, 0, sizeof histo);
- fseek (m_InputFile, -2000, SEEK_END);
- for (i=0; i < 2000; i++)
- histo[fgetc(m_InputFile)]++;
- for (i=0; i < 4; i++)
- if (histo[often[i]] < 200)
- return 0;
- return 1;
- }
-
- /*
- Returns 1 for a Coolpix 2100, 0 for anything else.
- */
- int CLASS nikon_e2100()
- {
- uint8_t t[12];
- int i;
-
- fseek (m_InputFile, 0, SEEK_SET);
- for (i=0; i < 1024; i++) {
- ptfread (t, 1, 12, m_InputFile);
- if (((t[2] & t[4] & t[7] & t[9]) >> 4
- & t[1] & t[6] & t[8] & t[11] & 3) != 3)
- return 0;
- }
- return 1;
- }
-
- void CLASS nikon_3700()
- {
- int bits; // i;
- uint8_t dp[24];
- static const struct {
- int bits;
- char make[12], model[15];
- } table[] = {
- { 0x00, "PENTAX", "Optio 33WR" },
- { 0x03, "NIKON", "E3200" },
- { 0x32, "NIKON", "E3700" },
- { 0x33, "OLYMPUS", "C740UZ" } };
-
- fseek (m_InputFile, 3072, SEEK_SET);
- ptfread (dp, 1, 24, m_InputFile);
- bits = (dp[8] & 3) << 4 | (dp[20] & 3);
- for (unsigned i=0; i < sizeof table / sizeof *table; i++)
- if (bits == table[i].bits) {
- strcpy (m_CameraMake, table[i].make );
- strcpy (m_CameraModel, table[i].model);
- }
- }
-
- /*
- Separates a Minolta DiMAGE Z2 from a Nikon E4300.
- */
- int CLASS minolta_z2()
- {
- unsigned i,nz;
- char tail[424];
-
- fseek (m_InputFile, (long)(-sizeof tail), SEEK_END);
- ptfread (tail, 1, sizeof tail, m_InputFile);
- for (nz=i=0; i < sizeof tail; i++)
- if (tail[i]) nz++;
- return nz > 20;
- }
-
- //void CLASS jpeg_thumb ();
-
- void CLASS ppm_thumb ()
- /* Remember: This function is modified to write the raws thumbnail to the
- m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
- */
- {
- char *thumb;
- m_ThumbLength = m_ThumbWidth*m_ThumbHeight*3;
- thumb = (char *) MALLOC (m_ThumbLength);
- merror (thumb, "ppm_thumb()");
- //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
- QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
- VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
- ptfread (thumb, 1, m_ThumbLength, m_InputFile);
- VAppend(m_Thumb, thumb, m_ThumbLength);
- FREE (thumb);
- }
-
- void CLASS ppm16_thumb()
- {
- int i;
- char *thumb;
- m_ThumbLength = m_ThumbWidth*m_ThumbHeight*3;
- thumb = (char *) CALLOC (m_ThumbLength,2);
- merror (thumb, "ppm16_thumb()");
- read_shorts ((uint16_t *) thumb, m_ThumbLength);
- for (i=0; i < (int32_t)m_ThumbLength; i++)
- thumb[i] = ((uint16_t *) thumb)[i] >> 8;
- QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
- VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
- //fprintf (ofp, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
- //fwrite (thumb, 1, m_ThumbLength, ofp);
- VAppend(m_Thumb, thumb, m_ThumbLength);
- FREE (thumb);
- }
-
- void CLASS layer_thumb ()
- /* Remember: This function is modified to write the raws thumbnail to the
- m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
- */
- // TODO: Tests needed: What format is this? Can it be read by QPixmap?
- {
- // int i, c;
- int c;
- char *thumb, map[][4] = { "012","102" };
-
- m_Colors = m_ThumbMisc >> 5 & 7;
- m_ThumbLength = m_ThumbWidth*m_ThumbHeight;
- thumb = (char *) CALLOC (m_Colors, m_ThumbLength);
- merror (thumb, "layer_thumb()");
- //fprintf (m_OutputFile, "P%d\n%d %d\n255\n", 5 + (m_Colors >> 1), m_ThumbWidth, m_ThumbHeight);
- QString dummy = QString("P%1\n%2 %3\n255\n")
- .arg(5 + (m_Colors >> 1)).arg(m_ThumbWidth).arg(m_ThumbHeight);
- VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
- ptfread (thumb, m_ThumbLength, m_Colors, m_InputFile);
- for (unsigned i=0; i < m_ThumbLength; i++) {
- for (c=0; c < m_Colors; c++) {
- //putc (thumb[i+m_ThumbLength*(map[m_ThumbMisc >> 8][c]-'0')], m_OutputFile);
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
- m_Thumb.push_back(thumb[i+m_ThumbLength*(map[m_ThumbMisc >> 8][c]-'0')]);
- #pragma GCC diagnostic pop
- }
- }
- FREE (thumb);
- }
-
- void CLASS rollei_thumb ()
- /* Remember: This function is modified to write the raws thumbnail to the
- m_Thumb instead of a file on disk. Always access thumbnails via DcRaw::thumbnail()!
- */
- // TODO: Tests needed: What format is this? Can it be read by QPixmap?
- {
- unsigned i;
- uint16_t *thumb;
-
- m_ThumbLength = m_ThumbWidth * m_ThumbHeight;
- thumb = (uint16_t *) CALLOC (m_ThumbLength, 2);
- merror (thumb, "rollei_thumb()");
- //fprintf (m_OutputFile, "P6\n%d %d\n255\n", m_ThumbWidth, m_ThumbHeight);
- QString dummy = QString("P6\n%1 %2\n255\n").arg(m_ThumbWidth).arg(m_ThumbHeight);
- VAppend(m_Thumb, dummy.toLocal8Bit().data(), dummy.length());
- read_shorts (thumb, m_ThumbLength);
- for (i=0; i < m_ThumbLength; i++) {
- //putc (thumb[i] << 3, m_OutputFile);
- //putc (thumb[i] >> 5 << 2, m_OutputFile);
- //putc (thumb[i] >> 11 << 3, m_OutputFile);
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
- m_Thumb.push_back(thumb[i] << 3);
- m_Thumb.push_back(thumb[i] >> 5 << 2);
- m_Thumb.push_back(thumb[i] >> 11 << 3);
- #pragma GCC diagnostic pop
- }
- FREE (thumb);
- }
-
- void CLASS rollei_load_raw()
- {
- uint8_t pixel[10];
- unsigned iten=0, isix, i, buffer=0, todo[16];
-
- isix = m_RawWidth * m_RawHeight * 5 / 8;
- while (fread (pixel, 1, 10, m_InputFile) == 10) {
- for (i=0; i < 10; i+=2) {
- todo[i] = iten++;
- todo[i+1] = pixel[i] << 8 | pixel[i+1];
- buffer = pixel[i] >> 2 | buffer << 6;
- }
- for ( ; i < 16; i+=2) {
- todo[i] = isix++;
- todo[i+1] = buffer >> (14-i)*5;
- }
- for (i=0; i < 16; i+=2)
- m_Raw_Image[todo[i]] = (todo[i+1] & 0x3ff);
- }
- m_WhiteLevel = 0x3ff;
- }
-
- int CLASS raw (unsigned row, unsigned col)
- {
- return (row < m_RawHeight && col < m_RawWidth) ? RAW(row,col) : 0;
- }
-
- void CLASS phase_one_flat_field (int is_float, int nc)
- {
- uint16_t head[8];
- unsigned wide, y, x, c, rend, cend, row, col;
- float *mrow, num, mult[4];
-
- read_shorts (head, 8);
- wide = head[2] / head[4];
- mrow = (float *) CALLOC (nc*wide, sizeof *mrow);
- merror (mrow, "phase_one_flat_field()");
- for (y=0; y < (unsigned) (head[3] / head[5]); y++) {
- for (x=0; x < wide; x++)
- for (c=0; c < (unsigned) nc; c+=2) {
- num = is_float ? getreal(11) : get2()/32768.0;
- if (y==0) mrow[c*wide+x] = num;
- else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
- }
- if (y==0) continue;
- rend = head[1] + y*head[5];
- for (row = rend-head[5]; row < m_RawHeight && row < rend; row++) {
- for (x=1; x < wide; x++) {
- for (c=0; c < (unsigned) nc; c+=2) {
- mult[c] = mrow[c*wide+x-1];
- mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
- }
- cend = head[0] + x*head[4];
- for (col = cend-head[4]; col < m_RawWidth && col < cend; col++) {
- c = nc > 2 ? FC(row-m_TopMargin,col-m_LeftMargin) : 0;
- if (!(c & 1)) {
- c = unsigned(RAW(row,col) * mult[c]);
- RAW(row,col) = MIN((int32_t)c,65535);
- }
- for (c=0; c < (unsigned) nc; c+=2)
- mult[c] += mult[c+1];
- }
- }
- for (x=0; x < wide; x++)
- for (c=0; c < (unsigned) nc; c+=2)
- mrow[c*wide+x] += mrow[(c+1)*wide+x];
- }
- }
- FREE (mrow);
- }
-
- void CLASS phase_one_correct()
- {
- unsigned entries, tag, data, save, col, row, type;
- int len, i, j, k, cip, val[4], dev[4], sum, max;
- int head[9], diff, mindiff=INT_MAX, off_412=0;
- static const signed char dir[12][2] =
- { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
- {-2,-2}, {-2,2}, {2,-2}, {2,2} };
- float poly[8], num, cfrac, frac, mult[2], *yval[2];
- uint16_t *xval[2];
-
- if (m_UserSetting_HalfSize || !m_MetaLength) return;
- TRACEKEYVALS("Phase One correction","%s","");
- fseek (m_InputFile, meta_offset, SEEK_SET);
- m_ByteOrder = get2();
- fseek (m_InputFile, 6, SEEK_CUR);
- fseek (m_InputFile, meta_offset+get4(), SEEK_SET);
- entries = get4(); get4();
- while (entries--) {
- tag = get4();
- len = get4();
- data = get4();
- save = ftell(m_InputFile);
- fseek (m_InputFile, meta_offset+data, SEEK_SET);
- if (tag == 0x419) { /* Polynomial curve */
- for (get4(), i=0; i < 8; i++)
- poly[i] = getreal(11);
…
Large files files are truncated, but you can click here to view the full file