1 /***************************************************
2  nikon_curve.c - read Nikon NTC/NCV files
3 
4  Copyright 2004-2007 by Shawn Freeman, Udi Fuchs
5 
6  This program reads in a Nikon NTC/NCV file,
7  interperates it's tone curve, and writes out a
8  simple ASCII file containing a table of interpolation
9  values. See the header file for more information.
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License version 2
13  as published by the Free Software Foundation. You should have received
14  a copy of the license along with this program.
15 
16 ****************************************************/
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <math.h>
22 #include <errno.h>
23 #include <stdarg.h> /* For variable argument lists */
24 #include "SimpleNikonCurve.h"
25 
26 #ifdef __WITH_UFRAW__
27     #include "uf_glib.h"
28     #include "ufraw.h"
29 #else
30     #define MAX(a,b) ((a) > (b) ? (a) : (b))
31     #define MIN(a,b) ((a) < (b) ? (a) : (b))
32     #define g_fopen fopen
33 #endif
34 
35 /*************************************************
36  * Internal static data
37  *************************************************/
38 
39 //file offsets for the different data in different file types
40 static const int FileOffsets[2][4] = {
41     {NTC_PATCH_OFFSET,NTC_BOX_DATA, NTC_NUM_ANCHOR_POINTS, NTC_ANCHOR_DATA_START},
42     {NCV_PATCH_OFFSET,NCV_BOX_DATA, NCV_NUM_ANCHOR_POINTS, NCV_ANCHOR_DATA_START},
43 };
44 
45 //file header indicating ntc file
46 static const unsigned char NTCFileHeader[] = {0x9d,0xdc,0x7d,0x00,0x65,0xd4,
47 			0x11,0xd1,0x91,0x94,0x44,0x45,0x53,0x54,0x00,0x00};
48 
49 //file header indicating an ncv file
50 static const unsigned char NCVFileHeader[] = {0x40,0xa9,0x86,0x7a,0x1b,0xe9,
51 			0xd2,0x11,0xa9,0x0a,0x00,0xaa,0x00,0xb1,0xc1,0xb7};
52 
53 //This is an additional header chunk at the beginning of the file
54 //There are some similarities between the headers, but not enough to fully crack.
55 //This does not appear to change.
56 static const unsigned char NCVSecondFileHeader[] = {0x01,0x32,0xa4,0x76,0xa2,
57 			0x17,0xd4,0x11,0xa9,0x0a,0x00,0xaa,0x00,0xb1,0xc1,
58 			0xb7,0x01,0x00,0x05,0x00,0x00,0x00,0x01};
59 
60 //This is the terminator of an NCV file. Again there are some similarites
61 //to other sections, but not enough for to crack what it means. However,
62 //it does not appear to change.
63 static const unsigned char NCVFileTerminator[] = {0x45,0xd3,0x0d,0x77,0xa3,0x6e,
64 			0x1e,0x4e,0xa4,0xbe,0xcf,0xc1,0x8e,0xb5,0xb7,0x47,
65 			0x01,0x00,0x05,0x00,0x00,0x00,0x01 };
66 
67 //File section header. Only a one byte difference between this and an NTC file header
68 static const unsigned char FileSectionHeader[] = {0x9d,0xdc,0x7d,0x03,0x65,0xd4,
69 			0x11,0xd1,0x91,0x94,0x44,0x45,0x53,0x54,0x00,0x00};
70 //file type header array
71 static const unsigned char *FileTypeHeaders[NUM_FILE_TYPES] = {
72     NTCFileHeader,
73     NCVFileHeader,
74 };
75 
76 /**STANDALONE**/
77 #ifdef _STAND_ALONE_
78 
79 //filenames
80 char exportFilename[1024];
81 char nikonFilename[1024];
82 
83 unsigned int standalone_samplingRes = 65536;
84 unsigned int standalone_outputRes = 256;
85 unsigned int program_mode = CURVE_MODE;
86 
87 /*******************************************
88 ProcessArgs:
89     Convenient function for processing the args
90     for the test runner.
91 ********************************************/
ProcessArgs(int num_args,char * args[])92 int ProcessArgs(int num_args, char *args[])
93 {
94     exportFilename[0] = '\0';
95     nikonFilename[0] = '\0';
96 
97     int i;
98     for(i = 0; i < num_args; i++)
99     {
100 	if (strcmp(args[i],"-h") == 0 || strcmp(args[i],"-H") == 0 || num_args <= 1)
101 	{
102 	    printf("NikonCurveGenerator %s %s\n",NC_VERSION, NC_DATE);
103 	    printf("Written by Shawn Freeman\n");
104 	    printf("Thanks go out to Udi Fuchs, UFRaw, and GIMP :)\n\n");
105 	    printf("Usage:\n");
106 	    printf("-nef   Specify an NEF file to get tone curve data from.\n\n");
107 
108 	    //signal that processing cannot occur
109 	    return NC_ERROR;
110 	}
111 	else if (strcmp(args[i],"-nef") == 0)
112 	{
113 	    i++;
114 	    program_mode = NEF_MODE;
115 	    strncpy(nikonFilename, args[i], 1023);
116 	    nikonFilename[1023] = '\0';
117 	}
118 	//don't load argument 0
119 	else if (i != 0)
120 	{
121 	    //consider this the file name to load
122 	    strncpy(nikonFilename, args[i], 1023);
123 	    nikonFilename[1023] = '\0';
124 	}
125     }
126 
127     if (strlen(exportFilename) == 0)
128     {
129 	//set it to have a default output file name
130 	strncpy(exportFilename, nikonFilename, 1023);
131 	exportFilename[1023] = '\0';
132         int StrLen = strlen(exportFilename);
133         for (short i=strlen(exportFilename);exportFilename[i] != '.'; i--) {
134           exportFilename[i]=0;
135         }
136 	strncat(exportFilename, "anchors", 1023);
137 	exportFilename[1023] = '\0';
138     }
139 
140     return NC_SUCCESS;
141 }
142 #endif //End STAND_ALONE
143 
144 /************************************************************
145 nc_message_handler:
146     The Nikon Curve message handler. Udi Fuchs created this
147 to make the error hanpting consistent acros the code.
148 
149   code - Message code
150   message - The message
151 **************************************************************/
nc_message(int code,char * format,...)152 void nc_message(int code, char *format, ...)
153 {
154     char message[256];
155     va_list ap;
156     va_start(ap, format);
157 
158     vsnprintf(message, 255, format, ap);
159     message[255] = '\0';
160     va_end(ap);
161 
162 #ifdef _STAND_ALONE_    //if we're running standalone mode
163 
164     code = code;
165     fprintf(stderr, message);
166     fflush(stderr);
167 
168 #else
169 
170 #ifdef __WITH_UFRAW__    //and if compiling with UFRAW
171 
172     if (code==NC_SET_ERROR)
173     {
174 	ufraw_message(UFRAW_SET_ERROR, message);
175     }
176     else
177     {
178 	ufraw_message(code, message);
179     }
180 
181 #else    //else, just print out the errors normally
182 
183     code = code;
184     g_printerr("%s", message);
185 
186 #endif //End WITH_UFRAW
187 
188 #endif //End STAND_ALONE
189 }
190 
191 // #define _DEBUG
DEBUG_PRINT(char * format,...)192 void DEBUG_PRINT(char *format, ...)
193 {
194 #ifdef _DEBUG
195     va_list ap;
196     va_start(ap, format);
197     vfprintf(stderr, format, ap);
198     fflush(stderr);
199     va_end(ap);
200 #else
201     format = format;
202 #endif
203 }
204 
205 /* nc_merror(): Handle memory allocaltion errors */
nc_merror(void * ptr,char * where)206 void nc_merror(void *ptr, char *where)
207 {
208     if (ptr) return;
209 #ifdef __WITH_UFRAW__
210     g_error("Out of memory in %s\n", where);
211 #else
212     fprintf(stderr, "Out of memory in %s\n", where);
213     exit(1);
214 #endif
215 }
216 
217 // Assert something at compile time (must use this inside a function);
218 // works because compilers won't let us declare negative-length arrays.
219 #define STATIC_ASSERT(cond) \
220     { (void)((int (*)(char failed_static_assertion[(cond)?1:-1]))0); }
221 
222 /***********************************************************************
223 isBigEndian:
224 	Determines if the machine we are running on is big endian or not.
225 ************************************************************************/
isBigEndian()226 int isBigEndian()
227 {
228     STATIC_ASSERT(sizeof(short)==2);
229     short x;
230     unsigned char EndianTest[2] = { 1, 0 };
231 
232     x = *(short *) EndianTest;
233 
234     return (x!=1);
235 }
236 
237 /***********************************************************************
238 ShortVal:
239 	Convert short int (16 bit) from little endian to machine endianess.
240 ************************************************************************/
ShortVal(short s)241 short ShortVal(short s)
242 {
243     STATIC_ASSERT(sizeof(short)==2);
244     if (isBigEndian()) {
245 	unsigned char b1, b2;
246 
247 	b1 = s & 255;
248 	b2 = (s >> 8) & 255;
249 
250 	return (b1 << 8) + b2;
251     } else
252 	return s;
253 }
254 
255 /***********************************************************************
256 LongVal:
257 	Convert long int (32 bit) from little endian to machine endianess.
258 ************************************************************************/
LongVal(int i)259 int LongVal(int i)
260 {
261     STATIC_ASSERT(sizeof(int)==4);
262     if (isBigEndian()) {
263 	unsigned char b1, b2, b3, b4;
264 
265 	b1 = i & 255;
266 	b2 = ( i >> 8 ) & 255;
267 	b3 = ( i>>16 ) & 255;
268 	b4 = ( i>>24 ) & 255;
269 
270 	return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;
271     } else
272 	return i;
273 }
274 
275 /***********************************************************************
276 FloatVal:
277 	Convert float from little endian to machine endianess.
278 ************************************************************************/
FloatVal(float f)279 float FloatVal(float f)
280 {
281     STATIC_ASSERT(sizeof(float)==4);
282     if (isBigEndian()) {
283 	union {
284 	    float f;
285 	    unsigned char b[4];
286 	} dat1, dat2;
287 
288 	dat1.f = f;
289 	dat2.b[0] = dat1.b[3];
290 	dat2.b[1] = dat1.b[2];
291 	dat2.b[2] = dat1.b[1];
292 	dat2.b[3] = dat1.b[0];
293 	return dat2.f;
294     } else
295 	return f;
296 }
297 
298 /***********************************************************************
299 DoubleVal:
300 	Convert double from little endian to machine endianess.
301 ************************************************************************/
DoubleVal(double d)302 double DoubleVal(double d)
303 {
304     STATIC_ASSERT(sizeof(double)==8);
305     if (isBigEndian()) {
306 	union {
307 	    double d;
308 	    unsigned char b[8];
309 	} dat1, dat2;
310 
311 	dat1.d = d;
312 	dat2.b[0] = dat1.b[7];
313 	dat2.b[1] = dat1.b[6];
314 	dat2.b[2] = dat1.b[5];
315 	dat2.b[3] = dat1.b[4];
316 	dat2.b[4] = dat1.b[3];
317 	dat2.b[5] = dat1.b[2];
318 	dat2.b[6] = dat1.b[1];
319 	dat2.b[7] = dat1.b[0];
320 	return dat2.d;
321     } else
322 	return d;
323 }
324 
325 /*********************************************
326 GetNikonFileType:
327     Gets the nikon file type by comparing file
328     headers.
329 
330   file - The file to check.
331 **********************************************/
GetNikonFileType(FILE * file)332 int GetNikonFileType(FILE *file)
333 {
334     unsigned char buff[HEADER_SIZE];
335     int i = 0, j = 0;
336     int found = 1;
337 
338     fread(buff,HEADER_SIZE,1,file);
339 
340     for(i = 0; i < NUM_FILE_TYPES; i++)
341     {
342 	found = 1;
343 	for(j = 0; j < HEADER_SIZE; j++)
344 	{
345 	    if (buff[j] != FileTypeHeaders[i][j])
346 	    {
347 	        found = 0;
348 	        break;
349 	    }
350 	}
351 
352 	if (found)
353 	{
354 	    //return the file type
355 	    return i;
356 	}
357     }
358 	nc_message(NC_SET_ERROR, "Error, no compatible file types found!\n");
359     return -1;
360 }
361 
362 /*********************************************
363 LoadNikonCurve:
364     Loads all curves from a Nikon ntc or ncv file.
365 
366     fileName    - The filename.
367     curve        - Pointer to curve struct to hold the data.
368     resolution    - How many data points to sample from the curve.
369 **********************************************/
LoadNikonData(char * fileName,NikonData * data)370 int LoadNikonData(char *fileName, NikonData *data)
371 {
372     FILE *input = NULL;
373     int offset = 0;
374     CurveData *curve = NULL;
375 
376     if (fileName == NULL || strlen(fileName) == 0)
377     {
378 	nc_message(NC_SET_ERROR,
379 	            "Error, input filename cannot be NULL or empty!\n");
380 	return NC_ERROR;
381     }
382 
383     DEBUG_PRINT("DEBUG: OPENING FILE: %s\n",fileName);
384 
385     //open file for reading only!
386     input = g_fopen(fileName,"rb");
387 
388     //make sure we have a valid file
389     if (input == NULL)
390     {
391 	nc_message(NC_SET_ERROR, "Error opening '%s': %s\n",
392 	        fileName, strerror(errno));
393 	return NC_ERROR;
394     }
395 
396     //init the curve;
397     memset(data,0,sizeof(NikonData));
398 
399     //get the file type
400     data->m_fileType = GetNikonFileType(input);
401     // set file seek positions for curve tones depending of file type
402     // todo: is it possible to find one common rule?
403     long curveFilePos[4][4] = {
404 	{FileOffsets[data->m_fileType][BOX_DATA], SEEK_SET, FileOffsets[data->m_fileType][ANCHOR_DATA], SEEK_SET},
405 	{NEXT_SECTION_BOX_DATA_OFFSET, SEEK_CUR, NUM_POINTS_TO_ANCHOR_OFFSET, SEEK_CUR},
406 	{NEXT_SECTION_BOX_DATA_OFFSET, SEEK_CUR, NUM_POINTS_TO_ANCHOR_OFFSET, SEEK_CUR},
407 	{NEXT_SECTION_BOX_DATA_OFFSET, SEEK_CUR, NUM_POINTS_TO_ANCHOR_OFFSET, SEEK_CUR}
408     };
409 
410     //make sure we have a good file type
411     if (data->m_fileType == -1)
412 	return NC_ERROR;
413 
414     //advance file pointer to necessary data section
415     fseek(input,offset,SEEK_SET);
416 
417     //Conevenience and opt if compiler doesn't already do it
418     curve = &data->curves[0];
419 
420     //set curve type
421     curve->m_curveType = TONE_CURVE;
422 
423     //read patch version
424     fseek(input,FileOffsets[data->m_fileType][PATCH_DATA],SEEK_SET);
425     fread(&data->m_patch_version,sizeof(unsigned short),1,input);
426     data->m_patch_version = ShortVal(data->m_patch_version);
427 
428     // read all tone curves data follow from here
429     int i;
430     for(i = 0; i < NUM_CURVE_TYPES; i++)
431     {
432 	curve = &data->curves[i];
433 
434 	//set curve type
435 	curve->m_curveType = i;
436 
437 	//get box data
438 	fseek(input, curveFilePos[i][0], curveFilePos[i][1]);
439 
440 	fread(&curve->m_min_x,sizeof(double),1,input);
441 	curve->m_min_x = DoubleVal(curve->m_min_x);
442 
443 	fread(&curve->m_max_x,sizeof(double),1,input);
444 	curve->m_max_x = DoubleVal(curve->m_max_x);
445 
446 	fread(&curve->m_gamma,sizeof(double),1,input);
447 	curve->m_gamma = DoubleVal(curve->m_gamma);
448 
449 	fread(&curve->m_min_y,sizeof(double),1,input);
450 	curve->m_min_y = DoubleVal(curve->m_min_y);
451 
452 	fread(&curve->m_max_y,sizeof(double),1,input);
453 	curve->m_max_y = DoubleVal(curve->m_max_y);
454 
455 	//get number of anchors (always located after box data)
456 	fread(&curve->m_numAnchors,1,1,input);
457 
458 	// It seems that if there is no curve then the 62 bytes in the buffer
459 	// are either all 0x00 (D70) or 0xFF (D2H).
460 	// We therefore switch these values with the default values.
461 	if (curve->m_min_x==1.0) {
462 	    curve->m_min_x = 0.0;
463 	    DEBUG_PRINT("DEBUG: NEF X MIN -> %e (changed)\n",curve->m_min_x);
464 	}
465 	if (curve->m_max_x==0.0) {
466 	    curve->m_max_x = 1.0;
467 	    DEBUG_PRINT("DEBUG: NEF X MAX -> %e (changed)\n",curve->m_max_x);
468 	}
469 	if (curve->m_min_y==1.0) {
470 	    curve->m_min_y = 0.0;
471 	    DEBUG_PRINT("DEBUG: NEF Y MIN -> %e (changed)\n",curve->m_min_y);
472 	}
473 	if (curve->m_max_y==0.0) {
474 	    curve->m_max_y = 1.0;
475 	    DEBUG_PRINT("DEBUG: NEF Y MAX -> %e (changed)\n",curve->m_max_y);
476 	}
477 	if (curve->m_gamma==0.0 || curve->m_gamma==255.0+255.0/256.0) {
478 	    curve->m_gamma = 1.0;
479 	    DEBUG_PRINT("DEBUG: NEF GAMMA -> %e (changed)\n",curve->m_gamma);
480 	}
481 	if (curve->m_numAnchors==255) {
482 	    curve->m_numAnchors = 0;
483 	    DEBUG_PRINT("DEBUG: NEF NUMBER OF ANCHORS -> %u (changed)\n",
484 		    curve->m_numAnchors);
485 	}
486 	if (curve->m_numAnchors > NIKON_MAX_ANCHORS) {
487 	    curve->m_numAnchors = NIKON_MAX_ANCHORS;
488 	    DEBUG_PRINT("DEBUG: NEF NUMBER OF ANCHORS -> %u (changed)\n",
489 		    curve->m_numAnchors);
490 	}
491 	//Move to start of the anchor data
492 	fseek(input, curveFilePos[i][2], curveFilePos[i][3]);
493 
494 	//read in the anchor points
495 	int rs = fread(curve->m_anchors, sizeof(CurveAnchorPoint),
496 		curve->m_numAnchors, input);
497 	if (curve->m_numAnchors != rs) {
498 	    nc_message(NC_SET_ERROR, "Error reading all anchor points\n");
499 	    return NC_ERROR;
500 	}
501 
502 	int j;
503 	for (j = 0; j < curve->m_numAnchors; j++)
504 	{
505 	    curve->m_anchors[j].x = DoubleVal(curve->m_anchors[j].x);
506 	    curve->m_anchors[j].y = DoubleVal(curve->m_anchors[j].y);
507 	}
508 
509 	DEBUG_PRINT("DEBUG: Loading Data:\n");
510 	DEBUG_PRINT("DEBUG: CURVE_TYPE: %u \n",curve->m_curveType);
511 	DEBUG_PRINT("DEBUG: BOX->MIN_X: %f\n",curve->m_min_x);
512 	DEBUG_PRINT("DEBUG: BOX->MAX_X: %f\n",curve->m_max_x);
513 	DEBUG_PRINT("DEBUG: BOX->GAMMA: %f\n",curve->m_gamma);
514 	DEBUG_PRINT("DEBUG: BOX->MIN_Y: %f\n",curve->m_min_y);
515 	DEBUG_PRINT("DEBUG: BOX->MAX_Y: %f\n",curve->m_max_x);
516 
517 #ifdef _DEBUG
518 	int i_dbg;
519 	for(i_dbg = 0; i_dbg < curve->m_numAnchors; i_dbg++)
520 	{
521 	    DEBUG_PRINT("DEBUG: ANCHOR X,Y: %f,%f\n",
522 		    curve->m_anchors[i_dbg].x,curve->m_anchors[i_dbg].y);
523 	}
524 	DEBUG_PRINT("\n");
525 #endif
526 
527         // We expect only tone curves, no R,G,B
528         if (i) {
529           if (curve->m_numAnchors != 2) {
530             printf("XXX JDLA : Not foreseen at %d processing %s\n",
531                    __LINE__,nikonFilename);
532             exit(EXIT_FAILURE);
533           }
534 	  if (curve->m_anchors[0].x != 0.0 || curve->m_anchors[0].y != 0.0) {
535             printf("XXX JDLA : Not foreseen at %d processing %s\n",
536                    __LINE__,nikonFilename);
537             exit(EXIT_FAILURE);
538           }
539 	  if (curve->m_anchors[1].x != 1.0 || curve->m_anchors[1].y != 1.0) {
540             printf("XXX JDLA : Not foreseen at %d processing %s\n",
541                    __LINE__,nikonFilename);
542             exit(EXIT_FAILURE);
543           }
544         } else {
545 	  if (curve->m_min_x < 0.0 || curve->m_max_x > 1.0) {
546             printf("XXX JDLA : Not foreseen at %d processing %s\n"
547                    "=> m_min_x : %f m_max_x : %f\n",
548                    __LINE__,nikonFilename,curve->m_min_x,curve->m_max_x);
549             exit(EXIT_FAILURE);
550           }
551 	  if (curve->m_min_y < 0.0 || curve->m_max_y > 1.0) {
552             printf("XXX JDLA : Not foreseen at %d processing %s\n",
553                    __LINE__,nikonFilename);
554             exit(EXIT_FAILURE);
555           }
556           // Write the output, gammaing the anchor points.
557           FILE *OutFile = fopen(exportFilename,"w");
558 	  for(short k = 0; k < curve->m_numAnchors; k++) {
559 	    fprintf(OutFile,
560                     "%f %f\n",
561 	 	    curve->m_anchors[k].x,
562                     pow(curve->m_anchors[k].y,1/curve->m_gamma));
563 	  }
564           fclose(OutFile);
565         }
566 
567     }
568     fclose(input);
569     return NC_SUCCESS;
570 }
571 
572 /****************************************
573 ConvertNikonCurveData:
574     The main driver. Takes a filename and
575     processes the curve, if possible.
576 
577     fileName    -    The file to process.
578 *****************************************/
ConvertNikonCurveData(char * inFileName,char * outFileName,unsigned int samplingRes,unsigned int outputRes)579 int ConvertNikonCurveData(char *inFileName, char *outFileName,
580     unsigned int samplingRes, unsigned int outputRes)
581 {
582     //Load the curve data from the ncv/ntc file
583     NikonData data;
584     char tmpstr[1024];
585 
586     if ( samplingRes <= 1 || outputRes <= 1 || samplingRes > MAX_RESOLUTION
587 	    || outputRes > MAX_RESOLUTION )
588     {
589 	nc_message(NC_SET_ERROR, "Error, sampling and output resolution"
590 	            "must be 1 <= res <= %u\n", MAX_RESOLUTION);
591 	return NC_ERROR;
592     }
593 
594     //loads all the curve data. Does not allocate sample arrays.
595     if (LoadNikonData(inFileName, &data) != NC_SUCCESS)
596     {
597 	return NC_ERROR;
598     }
599 
600     return NC_SUCCESS;
601 }
602 
603 /*****************************************************
604 FindTIFFOffset:
605     Moves the file pointer to the location
606     indicated by the TAG-TYPE pairing. This is meant just
607     as a helper function for this code. Uses elsewhere
608     may be limited.
609 
610     file    - Nikon File ptr
611     num_entries - Number of entries to search through
612     tiff_tag - The tiff tag to match.
613     tiff_type - The tiff type to match.
614 *******************************************************/
FindTIFFOffset(FILE * file,unsigned short num_entries,unsigned short tiff_tag,unsigned short tiff_type)615 int FindTIFFOffset(FILE *file, unsigned short num_entries, unsigned short tiff_tag, unsigned short tiff_type)
616 {
617     unsigned short tag = 0;
618     unsigned short type = 0;
619     unsigned int offset = 0;
620 
621     int i;
622     for(i = 0; i < num_entries; i++)
623     {
624 	//get tag 2 bytes
625 	tag = (fgetc(file)<<8)|fgetc(file);
626 	if (tag == tiff_tag)
627 	{
628 	    //get type 2 bytes
629 	    type = (fgetc(file)<<8)|fgetc(file);
630 	    if (type == tiff_type)    //Type for length of field
631 	    {
632 	        //get length (4 bytes)
633 	        offset = (fgetc(file)<<24)|(fgetc(file)<<16)|(fgetc(file)<<8)|fgetc(file);
634 	        //get value\offset 4 bytes
635 	        offset = (fgetc(file)<<24)|(fgetc(file)<<16)|(fgetc(file)<<8)|fgetc(file);
636 	        fseek(file,offset,SEEK_SET);
637 	        return 1; //true;
638 	    }
639 	}
640 	else
641 	{
642 	    //advance to next entry
643 	    fseek(file,10,SEEK_CUR);
644 	}
645     }
646     return 0; //false;
647 }
648 
649 /*******************************************************
650 RipNikonNEFData:
651     Gets Nikon NEF data. For now, this is just the tone
652     curve data.
653 
654     infile -	The input file
655     curve  -	data structure to hold data in.
656     sample_p -	pointer to the curve sample reference.
657 		can be NULL if curve sample is not needed.
658 ********************************************************/
RipNikonNEFData(char * infile,CurveData * data,CurveSample ** sample_p)659 int RipNikonNEFData(char *infile, CurveData *data, CurveSample **sample_p)
660 {
661     unsigned short byte_order = 0;
662     unsigned short num_entries = 0;
663     unsigned short version = 0;
664     unsigned int offset = 0;
665 
666     //open the file
667     FILE *file = g_fopen(infile,"rb");
668 
669     //make sure we have a valid file
670     if (file == NULL)
671     {
672 	nc_message(NC_SET_ERROR, "Error opening '%s': %s\n",
673 	        infile, strerror(errno));
674 	return NC_ERROR;
675     }
676 
677     //gets the byte order
678     fread(&byte_order,2,1,file);
679     byte_order = ShortVal(byte_order);
680     if (byte_order != 0x4d4d)
681     {
682 	//Must be in motorola format if it came from a NIKON
683 	nc_message(NC_SET_ERROR,
684 	    "NEF file data format is Intel. Data format should be Motorola.\n");
685 	return NC_ERROR;
686     }
687 
688     //get the version
689     //fread(&version,2,1,file);
690     version = (fgetc(file)<<8)|fgetc(file);
691     if (version != 0x002a)
692     {
693 	//must be 42 or not a valid TIFF
694 	nc_message(NC_SET_ERROR,
695 	    "NEF file version is %u. Version should be 42.\n",version);
696 	return NC_ERROR;
697     }
698 
699     //get offset to first IFD
700     offset = (fgetc(file)<<24)|(fgetc(file)<<16)|(fgetc(file)<<8)|fgetc(file);
701     //go to the IFD
702     fseek(file,offset,SEEK_SET);
703     //get number of entries
704     num_entries = (fgetc(file)<<8)|fgetc(file);
705 
706     //move file pointer to exif offset
707     if (!FindTIFFOffset(file,num_entries,TIFF_TAG_EXIF_OFFSET,TIFF_TYPE_LONG))
708     {
709 	nc_message(NC_SET_ERROR,
710 	    "NEF data entry could not be found with tag %u and type %u.\n",
711 	    TIFF_TAG_EXIF_OFFSET, TIFF_TYPE_LONG);
712 	return NC_ERROR;
713     }
714 
715     //get number of entries
716     num_entries = (fgetc(file)<<8)|fgetc(file);
717 
718     //move file pointer to maker note offset
719     if (!FindTIFFOffset(file,num_entries,TIFF_TAG_MAKER_NOTE_OFFSET,TIFF_TYPE_UNDEFINED))
720     {
721 	nc_message(NC_SET_ERROR,
722 	    "NEF data entry could not be found with tag %u and type %u.\n",
723 	    TIFF_TAG_MAKER_NOTE_OFFSET, TIFF_TYPE_UNDEFINED);
724 	return NC_ERROR;
725     }
726 
727     //////////////////////////////////////////////////////////////////////////
728     //NOTE: At this point, this section of the file acts almost like another
729     //      file header. Skip the first bytes, (which just say nikon with a
730     //      few bytes at the end. Offsets from here on in are from the start
731     //      of this section, not the start of the file.
732     //////////////////////////////////////////////////////////////////////////
733 
734     //Check the name. If it isn't Nikon then we can't do anything with this file.
735     char name[6];
736     fread(name,6,1,file);
737     if (strcmp(name,"Nikon") != 0)
738     {
739 	nc_message(NC_SET_ERROR,
740 	    "NEF string identifier is %s. Should be: Nikon.\n",name);
741 	return NC_ERROR;
742     }
743     fseek(file,4,SEEK_CUR);
744 
745     //save the current file location, as all other offsets for this section run off this.
746     unsigned long pos = ftell(file);
747 
748     //get byte order (use a regular fread)
749     fread(&byte_order,2,1,file);
750     byte_order = ShortVal(byte_order);
751     if (byte_order != 0x4d4d)
752     {
753 	//Must be in motorola format or not from a Nikon
754 	nc_message(NC_SET_ERROR,
755 	    "NEF secondary file data format is Intel. "
756 	    "Data format should be Motorola.\n");
757 	return NC_ERROR;
758     }
759 
760     //get version
761     version = (fgetc(file)<<8)|fgetc(file);
762     if (version != 0x002a)
763     {
764 	nc_message(NC_SET_ERROR,
765 	    "NEF secondary file version is %u. Version should be 42.\n",
766 	    version);
767 	return NC_ERROR;
768     }
769 
770     //get offset to first IFD
771     offset = (fgetc(file)<<24)| (fgetc(file)<<16)|(fgetc(file)<<8)|fgetc(file);
772     //go to the IFD (these offsets are NOT from the start of the file,
773     //just the start of the section).
774     fseek(file,pos+offset,SEEK_SET);
775     //get number of entries
776     num_entries = (fgetc(file)<<8)|fgetc(file);
777 
778     //move file position to tone curve data
779     if (!FindTIFFOffset(file,num_entries,TIFF_TAG_CURVE_OFFSET,TIFF_TYPE_UNDEFINED))
780     {
781 	nc_message(NC_SET_ERROR,
782 	    "NEF data entry could not be found with tag %u and type %u.\n",
783 	    TIFF_TAG_CURVE_OFFSET, TIFF_TYPE_UNDEFINED);
784 	return NC_ERROR;
785     }
786 
787     offset = ftell(file);
788     return RipNikonNEFCurve(file, offset+pos, data, sample_p);
789 }
790 
791 
792 /*******************************************************
793 RipNikonNEFCurve:
794     The actual retriever for the curve data from the NEF
795     file.
796 
797     file   - The input file.
798     infile - Offset to retrieve the data
799     curve  - data structure to hold curve in.
800     sample_p -	pointer to the curve sample reference.
801 		can be NULL if curve sample is not needed.
802 ********************************************************/
RipNikonNEFCurve(FILE * file,int offset,CurveData * data,CurveSample ** sample_p)803 int RipNikonNEFCurve(FILE *file, int offset, CurveData *data,
804 	CurveSample **sample_p)
805 {
806     int i;
807 
808     //seek to the offset of the data. Skip first two bytes (section isn't needed).
809     fseek(file, offset+2, SEEK_SET);
810 
811     memset(data,0,sizeof(CurveData));
812     /////////////////////////////////////////////////
813     //GET CURVE DATA
814     /////////////////////////////////////////////////
815     //get box data and gamma
816     data->m_min_x = (double)fgetc(file)/255.0;
817     data->m_max_x = (double)fgetc(file)/255.0;
818     data->m_min_y = (double)fgetc(file)/255.0;
819     data->m_max_y = (double)fgetc(file)/255.0;
820     //16-bit fixed point.
821     data->m_gamma = (double)fgetc(file) + ((double)fgetc(file)/256.0);
822 
823     //DEBUG_PRINT("DEBUG: NEF SECTION SIZE -> %u\n",data->section_size);
824     DEBUG_PRINT("DEBUG: NEF X MIN -> %e\n",data->m_min_x);
825     DEBUG_PRINT("DEBUG: NEF X MAX -> %e\n",data->m_max_x);
826     DEBUG_PRINT("DEBUG: NEF Y MIN -> %e\n",data->m_min_y);
827     DEBUG_PRINT("DEBUG: NEF Y MAX -> %e\n",data->m_max_y);
828     //DEBUG_PRINT("DEBUG: NEF GAMMA (16-bit fixed point) -> %e\n",(data->m_gamma>>8)+(data->m_gamma&0x00ff)/256.0);
829     DEBUG_PRINT("DEBUG: NEF GAMMA -> %e\n",data->m_gamma);
830     // It seems that if there is no curve then the 62 bytes in the buffer
831     // are either all 0x00 (D70) or 0xFF (D2H).
832     // We therefore switch these values with the default values.
833     if (data->m_min_x==1.0) {
834 	data->m_min_x = 0.0;
835 	DEBUG_PRINT("DEBUG: NEF X MIN -> %e (changed)\n",data->m_min_x);
836     }
837     if (data->m_max_x==0.0) {
838 	data->m_max_x = 1.0;
839 	DEBUG_PRINT("DEBUG: NEF X MAX -> %e (changed)\n",data->m_max_x);
840     }
841     if (data->m_min_y==1.0) {
842 	data->m_min_y = 0.0;
843 	DEBUG_PRINT("DEBUG: NEF Y MIN -> %e (changed)\n",data->m_min_y);
844     }
845     if (data->m_max_y==0.0) {
846 	data->m_max_y = 1.0;
847 	DEBUG_PRINT("DEBUG: NEF Y MAX -> %e (changed)\n",data->m_max_y);
848     }
849     if (data->m_gamma==0.0 || data->m_gamma==255.0+255.0/256.0) {
850 	data->m_gamma = 1.0;
851 	DEBUG_PRINT("DEBUG: NEF GAMMA -> %e (changed)\n",data->m_gamma);
852     }
853 
854     //get number of anchor points (there should be at least 2
855     fread(&data->m_numAnchors,1,1,file);
856     DEBUG_PRINT("DEBUG: NEF NUMBER OF ANCHORS -> %u\n",data->m_numAnchors);
857     if (data->m_numAnchors==255) {
858 	data->m_numAnchors = 0;
859 	DEBUG_PRINT("DEBUG: NEF NUMBER OF ANCHORS -> %u (changed)\n",
860 		data->m_numAnchors);
861     }
862     if (data->m_numAnchors > NIKON_MAX_ANCHORS) {
863 	data->m_numAnchors = NIKON_MAX_ANCHORS;
864 	DEBUG_PRINT("DEBUG: NEF NUMBER OF ANCHORS -> %u (changed)\n",
865 		data->m_numAnchors);
866     }
867 
868     //convert data to doubles
869     for(i = 0; i < data->m_numAnchors; i++)
870     {
871 	//get anchor points
872 	data->m_anchors[i].x = (double)fgetc(file)/255.0;
873 	data->m_anchors[i].y = (double)fgetc(file)/255.0;
874     }
875 
876     //The total number of points possible is 25 (50 bytes).
877     //At this point we subtract the number of bytes read for points from the max (50+1)
878     fseek(file,(51 - data->m_numAnchors*2),SEEK_CUR);
879 
880     //get data (always 4096 entries, 1 byte apiece)
881     DEBUG_PRINT("DEBUG: NEF data OFFSET -> %ld\n",ftell(file));
882 
883     return NC_SUCCESS;
884 }
885 
886 /*******************************
887 main:
888     Uh....no comment. :)
889 ********************************/
890 #ifdef _STAND_ALONE_
891 
main(int argc,char * argv[])892 int main(int argc, char* argv[])
893 {
894     //make sure we can continue processing
895     if (ProcessArgs(argc,argv) == NC_SUCCESS)
896     {
897 
898 	//if we are in NEF mode, rip the curve out of the RAW file
899 	if (program_mode == NEF_MODE)
900 	{
901 	    NikonData data;
902 
903 	    //intiialze the structure to zero
904 	    memset(&data,0,sizeof(NikonData));
905 
906 	    if (RipNikonNEFData(nikonFilename, &data.curves[TONE_CURVE], NULL)
907 	            != NC_SUCCESS)
908 	    {
909 	        return NC_ERROR;
910 	    }
911 
912 	}
913 	//else, process a nikon curve file
914 	else
915 	{
916 	    //do the deed
917 	    ConvertNikonCurveData(nikonFilename,exportFilename,
918 	        standalone_samplingRes, standalone_outputRes);
919 	}
920     }
921     return NC_SUCCESS;
922 }
923 #endif
924