int Entries_der<T>::write( FILE *file ) const
{
  if( data_was_loaded ) {
    fprintf( stderr, "tried to write data that was loaded at instantiation, "
	     "which is not allowed\n" );
    return 1;
  }
  
  /* First, write the type to file */
  pure_cfr_entry_type_t type = get_entry_type( );
  size_t num_written = fwrite( &type, sizeof( pure_cfr_entry_type_t ), 1, file );
  if( num_written != 1 ) {
    fprintf( stderr, "error while writing dump type [%d]\n", type );
    return 1;
  }

  /* Dump entries */
  num_written = fwrite( entries, sizeof( T ), total_num_entries, file );
  if( num_written != total_num_entries ) {
    fprintf( stderr, "error while writing; only wrote %jd of %jd entries\n",
	     ( intmax_t ) num_written, ( intmax_t ) total_num_entries );
    return 1;
  }  
  
  return 0;
}
int Entries_der<T>::load( FILE *file )
{
  if( data_was_loaded ) {
    fprintf( stderr, "tried to load from file on top of loaded data at "
	     "instantiation, which is not allowed\n" );
    return 1;
  }
  
  /* First, load the type and double-check that it matches */
  pure_cfr_entry_type_t type;
  size_t num_read = fread( &type,
			   sizeof( pure_cfr_entry_type_t ),
			   1,
			   file );
  if( num_read != 1 ) {
    fprintf( stderr, "failed to read entry type\n" );
    return 1;
  }
  pure_cfr_entry_type_t this_type = get_entry_type( );
  if( type != this_type ) {
    fprintf( stderr, "type [%d] found, but expected type [%d]\n",
	     type, this_type );
    return 1;
  }

  /* Now load the entries */
  num_read = fread( entries, sizeof( T ), total_num_entries, file );
  if( num_read != total_num_entries ) {
    fprintf( stderr, "error while loading; only read %jd of %jd entries\n",
	     ( intmax_t ) num_read, ( intmax_t ) total_num_entries );
    return 1;
  }  
  
  return 0;
}
Beispiel #3
0
// entry value
static string get_value(tiff_handle_t &tiff_handle, uint32_t ifd_entry_offset) {
    // entry type and entry count
    const uint16_t entry_type = get_entry_type(tiff_handle, ifd_entry_offset);

    // value
    std::string output;
    switch(entry_type) {
    case EXIF_BYTE:
        return get_exif_byte(tiff_handle, ifd_entry_offset);
    case EXIF_ASCII:
        return get_exif_ascii(tiff_handle, ifd_entry_offset);
    case EXIF_SHORT:
        return get_exif_short(tiff_handle, ifd_entry_offset);
    case EXIF_LONG:
        return get_exif_long(tiff_handle, ifd_entry_offset);
    case EXIF_RATIONAL:
        return get_exif_rational(tiff_handle, ifd_entry_offset);
    case EXIF_UNDEFINED:
        return get_exif_undefined(tiff_handle, ifd_entry_offset);
    case EXIF_SLONG:
        return get_exif_slong(tiff_handle, ifd_entry_offset);
    case EXIF_SRATIONAL:
        return get_exif_srational(tiff_handle, ifd_entry_offset);
    default:
        // NOTE: in future, we may wish to log the invalid entry_type to diagnostics
        //       when in full diagnostics mode.

        // the type is not valid, so use best-effort and return value for UNDEFINED type
        return get_exif_undefined(tiff_handle, ifd_entry_offset);
    }
}
Beispiel #4
0
void read_data(FILE *inf, wave_object_t *obj) {
    double xt, yt, zt;
    double it, jt, kt;
    double st, tt;
    size_t num_pts;

    size_t i;
    size_t j;
    size_t type_pos;
    size_t next_space;
    char tmp;
    size_t cur_vert = 0;
    size_t cur_norm = 0;
    size_t cur_text = 0;
    size_t cur_face = 0;
    char in_buffer[512] = "";
    size_t blen = 0;
    char *fgs = NULL;
    enum obj_entry_type obj_type;
    int end = 0;
    size_t pt_cnt = 0;

    char *end_ptr;
    size_t vert;
    size_t text;
    size_t norm;
            
    // Assume no faces will ever have more than 20 points
    char *pts[20];
    size_t cur_pt = 0;
    int in_word = 0;
    char *num_start;
    char *num_end;
    
    
    // Save original file positon
    fpos_t original_pos;
    fgetpos(inf, &original_pos);

    // Go to the beginnning
    rewind(inf);

    do {
        fgs = fgets(in_buffer, 512, inf);
        if (fgs == NULL) continue;
        blen = strlen(in_buffer);
        in_buffer[blen-1] = '\0';
        --blen;
        if (in_buffer[blen-1] == '\r') {
            in_buffer[blen-1] ='\0';
            --blen;
        }
        obj_type = get_entry_type(in_buffer);

        switch (obj_type) {
        case vertex:
            // Find the 'v' and skip it and the white space after it
            num_start = strchr(in_buffer, 'v')+1;

            xt = strtod(num_start, &num_end);
            yt = strtod(num_end, &num_end);
            zt = strtod(num_end, &num_end);

            obj->verts[cur_vert][0] = (RtFloat)xt;
            obj->verts[cur_vert][1] = (RtFloat)yt;
            obj->verts[cur_vert][2] = (RtFloat)zt;
            
            ++cur_vert;
            break;

        case normal:
            // Find the 'n' and skip it and the white space after it
            num_start = strchr(in_buffer, 'n')+1;

            it = strtod(num_start, &num_end);
            jt = strtod(num_end, &num_end);
            kt = strtod(num_end, &num_end);

            obj->norms[cur_norm][0] = it;
            obj->norms[cur_norm][1] = jt;
            obj->norms[cur_norm][2] = kt;

            ++cur_norm;
            
            break;

        case text_coord:
            // Find the "vt" and skip it and the white space after it
            num_start = strchr(in_buffer, 'v')+2;

            st = strtod(num_start, &num_end);
            tt = strtod(num_end, &num_end);

            obj->text_coords[cur_text].s = st;
            obj->text_coords[cur_text].t = tt;

            ++cur_text;

            break;

        case face:
            // Find the 'f' and skip it and the white space after it
            i = strchr(in_buffer, 'f')  - in_buffer + 1;
            while (isspace(in_buffer[i])) ++i;

            end = 0;
            pt_cnt = 0;
            
            cur_pt = 0;
            in_word = 0;
            while (in_buffer[i] != '\0') {
                if (!isspace(in_buffer[i]) && in_word == 1) {
                    in_word = 1;
                }
                if (!isspace(in_buffer[i]) && in_word == 0) {
                    pts[cur_pt++] = in_buffer+i;
                    in_word = 1;
                    pt_cnt++;
                }
                if (isspace(in_buffer[i]) && in_word == 1) {
                    in_word = 0;
                    in_buffer[i] = '\0';
                }
                if (isspace(in_buffer[i]) && in_word == 0) {
                    in_word = 0;
                    in_buffer[i] = '\0';
                }
                ++i;
            }
            obj->faces[cur_face].size = pt_cnt;
            obj->faces[cur_face].verts = malloc(sizeof(size_t)*pt_cnt);
            obj->faces[cur_face].norms = malloc(sizeof(size_t)*pt_cnt);
            obj->faces[cur_face].texts = malloc(sizeof(size_t)*pt_cnt);

            for (j=0; j<pt_cnt; ++j) {
                vert = strtoul(pts[j], &end_ptr, 10);
                text = strtoul(end_ptr+1, &end_ptr, 10);
                norm = strtoul(end_ptr+1, &end_ptr, 10);
                if (vert) vert -= 1;
                if (norm) norm -= 1;
                if (text) text -= 1;
                obj->faces[cur_face].verts[j] = vert;
                obj->faces[cur_face].norms[j] = norm;
                obj->faces[cur_face].texts[j] = text;
            }
            if (pt_cnt>obj->largest_face) {
                obj->largest_face = pt_cnt;
            }
            ++cur_face;
            
            break;

        case object:
            break;

        default:
            break;
        }
            
    } while (!feof(inf));

    // Return to original position
    fsetpos(inf, &original_pos);
}
Beispiel #5
0
void preprocess(FILE* inf, wave_object_t *obj) {
    /*
      Scan through the file and count the number of vertices, texture
      coordinates, normals and faces
    */
    // Save original position in file
    size_t nv=0;
    size_t nn=0;
    size_t nt=0;
    size_t nf=0;
    size_t no = 0;
    char in_buffer[512] = "";
    size_t blen = 0;
    
    fpos_t original_pos;
    fgetpos(inf, &original_pos);

    // Go to the beginnning
    rewind(inf);

    while (!feof(inf)) {
        char *fgs = fgets(in_buffer, 512, inf);
        if (fgs == NULL) continue;
        blen = strlen(in_buffer);
        in_buffer[blen-1] = '\0';
        --blen;
        if (in_buffer[blen-1] == '\r') {
            in_buffer[blen-1] ='\0';
            --blen;
        }
        if (blen == 0) continue;
        enum obj_entry_type obj_type = get_entry_type(in_buffer);

        switch (obj_type) {
        case vertex:
            ++nv;
            break;
        case normal:
            ++nn;
            break;
        case text_coord:
            ++nt;
            break;
        case face:
            ++nf;
            break;
        case object:
            ++no;
            read_object_type(in_buffer, obj);
            break;
        default:
            break;
        }
    }
    obj->num_verts = nv;
    obj->verts = malloc(sizeof(RtPoint) * nv);
    
    obj->num_norms = nn;
    obj->norms = malloc(sizeof(RtPoint) * nn);
    
    obj->num_texts = nt;
    obj->text_coords = malloc(sizeof(text_coord_t) * nt);
    
    obj->num_faces = nf;
    obj->faces = malloc(sizeof(face_t) * nf);

    // Return to original position
    fsetpos(inf, &original_pos);
}
Beispiel #6
0
char *FileReq(char *dir, const char *ext, char *result)
{
	static char *cwd = NULL;
	static s32 cursor_pos = 1;
	static s32 first_visible;
	static s32 num_items = 0;
	DIR *dirstream;
	struct dirent *direntry;
	static s32 row;
	char tmp_string[41];
	u32 keys;

	if (dir)
		ChDir(dir);

	cwd = GetCwd();

	for (;;) {
		keys = key_read();

		video_clear();

		if (keys & KEY_SELECT) {
			FREE_LIST();
			key_reset();
			return NULL;
		}

		if (num_items == 0) {
			dirstream = opendir(cwd);
			if (dirstream == NULL) {
				port_printf(0, 20, "error opening directory");
				return NULL;
			}
			// read directory entries
			while ((direntry = readdir(dirstream))) {
				s32 type = get_entry_type(cwd, direntry->d_name);

				// this is a very ugly way of only accepting a certain extension
				if ((type == 0 && strcmp(direntry->d_name, ".")) ||
				     check_ext(direntry->d_name) ||
				    (ext && (strlen(direntry->d_name) > 4 &&0 == strncasecmp(direntry->d_name + (strlen(direntry->d_name) - strlen(ext)), ext, strlen(ext))))) {
					// Hide ".." if at Unix root dir. Don't display Unix hidden files (.file).
					if ((!strcmp(direntry->d_name, "..") && strcmp(cwd, "/")) || direntry->d_name[0] != '.')
					{
						filereq_dir_items[num_items].name = (char *)malloc(strlen(direntry->d_name) + 1);
						strcpy(filereq_dir_items[num_items].name, direntry->d_name);
						filereq_dir_items[num_items].type = type;
						num_items++;
						if (num_items > 1024) break;
					}
				}
			}
			closedir(dirstream);

			sort_dir(filereq_dir_items, num_items);
			cursor_pos = 0;
			first_visible = 0;
		}

		// display current directory
		int len = strlen(cwd);

		if (len > 40) {
			strcpy(tmp_string, "..");
			strcat(tmp_string, cwd + len - 38);
			port_printf(0, MENU_Y, tmp_string);
		} else
			port_printf(0, MENU_Y, cwd);

		if (keys & KEY_DOWN) { //down
			if (++cursor_pos >= num_items) {
				cursor_pos = 0;
				first_visible = 0;
			}
			if ((cursor_pos - first_visible) >= MENU_HEIGHT) first_visible++;
		} else if (keys & KEY_UP) { // up
			if (--cursor_pos < 0) {
				cursor_pos = num_items - 1;
				first_visible = cursor_pos - MENU_HEIGHT + 1;
				if (first_visible < 0) first_visible = 0;
			}
			if (cursor_pos < first_visible) first_visible--;
		} else if (keys & KEY_LEFT) { //left
			if (cursor_pos >= 10) cursor_pos -= 10;
			else cursor_pos = 0;
			if (cursor_pos < first_visible) first_visible = cursor_pos;
		} else if (keys & KEY_RIGHT) { //right
			if (cursor_pos < (num_items - 11)) cursor_pos += 10;
			else cursor_pos = num_items - 1;
			if ((cursor_pos - first_visible) >= MENU_HEIGHT)
				first_visible = cursor_pos - (MENU_HEIGHT - 1);
		} else if (keys & KEY_A) { // button 1
			// directory selected
			if (filereq_dir_items[cursor_pos].type == 0) {
				strcat(cwd, "/");
				strcat(cwd, filereq_dir_items[cursor_pos].name);

				ChDir(cwd);
				cwd = GetCwd();

				FREE_LIST();
				key_reset();
			} else {
				sprintf(result, "%s/%s", cwd, filereq_dir_items[cursor_pos].name);
				if (dir)
					strcpy(dir, cwd);

				video_clear();
				port_printf(16 * 8, 120, "LOADING");
				video_flip();

				FREE_LIST();
				key_reset();
				return result;
			}
		} else if (keys & KEY_B) {
			cursor_pos = 0;
			first_visible = 0;
			key_reset();
		}

		// display directory contents
		row = 0;
		while (row < num_items && row < MENU_HEIGHT) {
			if (row == (cursor_pos - first_visible)) {
				// draw cursor
				port_printf(MENU_X + 16, MENU_LS + (10 * row), "-->");
			}

			if (filereq_dir_items[row + first_visible].type == 0)
				port_printf(MENU_X, MENU_LS + (10 * row), "DIR");
			int len = strlen(filereq_dir_items[row + first_visible].name);
			if (len > 32) {
				snprintf(tmp_string, 16, "%s", filereq_dir_items[row + first_visible].name);
				strcat(tmp_string, "..");
				strcat(tmp_string, &filereq_dir_items[row + first_visible].name[len - 15]);
			} else
			snprintf(tmp_string, 33, "%s", filereq_dir_items[row + first_visible].name);
			port_printf(MENU_X + (8 * 5), MENU_LS + (10 * row), tmp_string);
			row++;
		}
		while (row < MENU_HEIGHT)
			row++;

		video_flip();
		timer_delay(75);

		if (keys & (KEY_A | KEY_B | KEY_X | KEY_Y | KEY_L | KEY_R |
			    KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN))
			timer_delay(50);
	}

	return NULL;
}
Beispiel #7
0
void entry_reader::parse_entry(ifd_type_t ifd_type, tiff_handle_t &tiff_handle,
			       size_t ifd_entry_offset, entry_list_t &entries) {
/** 
 * parse_ifd_entry() parses one entry and places it into entries.
 * Throws exif_failure_exception if the exif data state is determined to be invalid
 * such that further entry parsing would be invalid.
 * @Throws exif_failure_exception_t
 */

    // check now that the 12 entry bytes are available
    if (ifd_entry_offset + 12 > tiff_handle.sbuf->bufsize) {
	// no space for entry record
	return;
    }

    // entry tag
    const uint16_t entry_tag = get_entry_tag(tiff_handle, ifd_entry_offset);
#ifdef DEBUG
    const uint16_t zentry_type = get_entry_type(tiff_handle, ifd_entry_offset);
    uint32_t zcount = get_entry_count(tiff_handle, ifd_entry_offset);
    uint32_t zoffset = get_data_offset(tiff_handle, ifd_entry_offset);
    cout << "exif_entry.parse_entry entry tag: " << entry_tag << ", entry type: " << zentry_type << " entry count: " << zcount << ", entry offset: " << zoffset;
#endif

    // add entry or parse entry's nested IFD, based on entry_tag
#ifdef DEBUG
    cout << "exif_entry.parse_entry IFD type: " << (int)ifd_type << "\n";
#endif
    switch (ifd_type) {
    case IFD0_TIFF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
    case IFD1_TIFF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
        uint32_t forwarded_ifd_offset;
        switch (entry_tag) {
	case 0x0100: add_entry(ifd_type, "ImageWidth", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0101: add_entry(ifd_type, "ImageLength", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0102: add_entry(ifd_type, "BitsPerSample", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0103: add_entry(ifd_type, "Compression", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0106: add_entry(ifd_type, "PhotometricInterpreation", tiff_handle, ifd_entry_offset, entries); break;
	case 0x010e: add_entry(ifd_type, "ImageDescription", tiff_handle, ifd_entry_offset, entries); break;
	case 0x010f: add_entry(ifd_type, "Make", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0110: add_entry(ifd_type, "Model", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0111: add_entry(ifd_type, "StripOffsets", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0112: add_entry(ifd_type, "Orientation", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0115: add_entry(ifd_type, "SamplesPerPixel", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0116: add_entry(ifd_type, "RowsPerStrip", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0117: add_entry(ifd_type, "StripByteCounts", tiff_handle, ifd_entry_offset, entries); break;
	case 0x011a: add_entry(ifd_type, "XResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0x011b: add_entry(ifd_type, "YResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0x011c: add_entry(ifd_type, "PlanarConfiguration", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0128: add_entry(ifd_type, "ResolutionUnit", tiff_handle, ifd_entry_offset, entries); break;
	case 0x012d: add_entry(ifd_type, "TransferFunction", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0131: add_entry(ifd_type, "Software", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0132: add_entry(ifd_type, "DateTime", tiff_handle, ifd_entry_offset, entries); break;
	case 0x013b: add_entry(ifd_type, "Artist", tiff_handle, ifd_entry_offset, entries); break;
	case 0x013e: add_entry(ifd_type, "WhitePoint", tiff_handle, ifd_entry_offset, entries); break;
	case 0x013f: add_entry(ifd_type, "PrimaryChromaticities", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0201: add_entry(ifd_type, "JPEGInterchangeFormat", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0202: add_entry(ifd_type, "JPEGInterchangeFormatLength", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0211: add_entry(ifd_type, "YCbCrCoefficients", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0212: add_entry(ifd_type, "YCbCrSubSampling", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0213: add_entry(ifd_type, "YCbCrPositioning", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0214: add_entry(ifd_type, "ReferenceBlackWhite", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8298: add_entry(ifd_type, "Copyright", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8769: // EXIF tag
            forwarded_ifd_offset = get_ifd_offset(tiff_handle, ifd_entry_offset);
            if (ifd_type == IFD0_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8769 IFD0_tiff to IFD0_EXIF: ifd_entry_offset: " << ifd_entry_offset << " forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD0_EXIF, tiff_handle, forwarded_ifd_offset, entries);
            } else if (ifd_type == IFD1_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8769 IFD1_tiff to IFD1_EXIF: ifd_entry_offset:" << ifd_entry_offset << " forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD1_EXIF, tiff_handle, forwarded_ifd_offset, entries);
            } else {
		assert(0);
            }
            break;
	case 0x8825: // GPS tag
            forwarded_ifd_offset = get_ifd_offset(tiff_handle, ifd_entry_offset);
            if (ifd_type == IFD0_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8825 IFD0_tiff to IFD0_GPS: forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD0_GPS, tiff_handle, forwarded_ifd_offset, entries);
            } else if (ifd_type == IFD1_TIFF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries case8825 IFD1_tiff to IFD1_GPS: forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD1_GPS, tiff_handle, forwarded_ifd_offset, entries);
            } else {
		assert(0);
            }
            break;
	default:
            add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;
    case IFD0_EXIF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
    case IFD1_EXIF:	// see table Tag Support Levels(1) for 0th IFD TIFF Tags
        switch (entry_tag) {
	case 0x829a: add_entry(ifd_type, "ExposureTime", tiff_handle, ifd_entry_offset, entries); break;
	case 0x829d: add_entry(ifd_type, "FNumber", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8822: add_entry(ifd_type, "ExposureProgram", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8824: add_entry(ifd_type, "SpectralSensitivity", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8827: add_entry(ifd_type, "PhotographicSensitivity", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8828: add_entry(ifd_type, "OECF", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8830: add_entry(ifd_type, "SensitivityType", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8831: add_entry(ifd_type, "StandardOutputSensitivity", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8832: add_entry(ifd_type, "RecommendedExposureIndex", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8833: add_entry(ifd_type, "ISOSpeed", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8834: add_entry(ifd_type, "ISOSpeedLatitudeyyy", tiff_handle, ifd_entry_offset, entries); break;
	case 0x8835: add_entry(ifd_type, "IOSpeedLatitudezzz", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9000: add_entry(ifd_type, "ExifVersion", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9003: add_entry(ifd_type, "DateTimeOriginal", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9004: add_entry(ifd_type, "DateTimeDigitized", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9101: add_entry(ifd_type, "ComponentsConfiguration", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9102: add_entry(ifd_type, "CompressedBitsPerPixel", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9201: add_entry(ifd_type, "ShutterSpeedValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9202: add_entry(ifd_type, "ApertureValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9203: add_entry(ifd_type, "BrightnessValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9204: add_entry(ifd_type, "ExposureBiasValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9205: add_entry(ifd_type, "MaxApertureValue", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9206: add_entry(ifd_type, "SubjectDistance", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9207: add_entry(ifd_type, "MeteringMode", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9208: add_entry(ifd_type, "LightSource", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9209: add_entry(ifd_type, "Flash", tiff_handle, ifd_entry_offset, entries); break;
	case 0x920a: add_entry(ifd_type, "FocalLength", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9214: add_entry(ifd_type, "SubjectArea", tiff_handle, ifd_entry_offset, entries); break;
	case 0x927c: add_maker_note_entry(ifd_type, "MakerNote", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9286: add_entry(ifd_type, "UserComment", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9290: add_entry(ifd_type, "SubSecTime", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9291: add_entry(ifd_type, "SubSecTimeOriginal", tiff_handle, ifd_entry_offset, entries); break;
	case 0x9292: add_entry(ifd_type, "SubSecTimeDigitized", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa000: add_entry(ifd_type, "FlashpixVersion", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa001: add_entry(ifd_type, "ColorSpace", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa002: add_entry(ifd_type, "PixelXDimension", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa003: add_entry(ifd_type, "PixelYDimension", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa004: add_entry(ifd_type, "RelatedSoundFile", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa005: // Interoperability tag
            forwarded_ifd_offset = get_ifd_offset(tiff_handle, ifd_entry_offset);
            if (ifd_type == IFD0_EXIF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries casea005 IFD0_EXIF to IFD0_INTEROP: ifd_entry_offset: " << ifd_entry_offset << ", forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD0_INTEROPERABILITY, tiff_handle, forwarded_ifd_offset, entries);
            } else if (ifd_type == IFD1_EXIF) {
#ifdef DEBUG
                cout << "exif_entry.parse_ifd_entries casea005 IFD1_EXIF to IFD1_INTEROP: forwarded_ifd_offset " << forwarded_ifd_offset << "\n";
#endif
		entry_reader::parse_ifd_entries(IFD1_INTEROPERABILITY, tiff_handle, forwarded_ifd_offset, entries);
            } else {
		assert(0);
            }
            break;
	case 0xa20b: add_entry(ifd_type, "FlashEnergy", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa20c: add_entry(ifd_type, "SpatialFrequencyResponse", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa20e: add_entry(ifd_type, "FocalPlaneXResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa20f: add_entry(ifd_type, "FocalPlaneYResolution", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa210: add_entry(ifd_type, "FocalPlaneResolutionUnit", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa214: add_entry(ifd_type, "SubjectLocation", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa215: add_entry(ifd_type, "ExposureIndex", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa217: add_entry(ifd_type, "SensingMethod", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa300: add_entry(ifd_type, "FileSource", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa301: add_entry(ifd_type, "SceneType", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa302: add_entry(ifd_type, "CFAPattern", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa401: add_entry(ifd_type, "CustomRendered", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa402: add_entry(ifd_type, "ExposureMode", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa403: add_entry(ifd_type, "WhiteBalance", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa404: add_entry(ifd_type, "DigitalZoomRatio", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa405: add_entry(ifd_type, "FocalLengthIn35mmFilm", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa406: add_entry(ifd_type, "SceneCaptureType", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa407: add_entry(ifd_type, "GainControl", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa408: add_entry(ifd_type, "Contrast", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa409: add_entry(ifd_type, "Saturation", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa40a: add_entry(ifd_type, "Sharpness", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa40b: add_entry(ifd_type, "DeviceSettingDescription", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa40c: add_entry(ifd_type, "SubjectDistanceRange", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa420: add_entry(ifd_type, "ImageUniqueID", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa430: add_entry(ifd_type, "CameraOwnerName", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa431: add_entry(ifd_type, "BodySerialNumber", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa432: add_entry(ifd_type, "LensSpecification", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa433: add_entry(ifd_type, "LensMake", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa434: add_entry(ifd_type, "LensModel", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa435: add_entry(ifd_type, "LensSerialNumber", tiff_handle, ifd_entry_offset, entries); break;
	case 0xa500: add_entry(ifd_type, "Gamma", tiff_handle, ifd_entry_offset, entries); break;
	default:
            add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;
    case IFD0_GPS:
    case IFD1_GPS:
        switch (entry_tag) {
	case 0x0000: add_entry(ifd_type, "GPSVersionID", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0001: add_entry(ifd_type, "GPSLatitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0002: add_entry(ifd_type, "GPSLatitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0003: add_entry(ifd_type, "GPSLongitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0004: add_entry(ifd_type, "GPSLongitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0005: add_entry(ifd_type, "GPSAltitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0006: add_entry(ifd_type, "GPSAltitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0007: add_entry(ifd_type, "GPSTimeStamp", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0008: add_entry(ifd_type, "GPSSatellites", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0009: add_entry(ifd_type, "GPSStatus", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000a: add_entry(ifd_type, "GPSMeasureMode", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000b: add_entry(ifd_type, "GPSDOP", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000c: add_entry(ifd_type, "GPSSpeedRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000d: add_entry(ifd_type, "GPSSpeed", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000e: add_entry(ifd_type, "GPSTrackRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x000f: add_entry(ifd_type, "GPSTrack", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0010: add_entry(ifd_type, "GPSImgDirectionRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0011: add_entry(ifd_type, "GPSImgDirection", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0012: add_entry(ifd_type, "GPSMapDatum", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0013: add_entry(ifd_type, "GPSDestLatitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0014: add_entry(ifd_type, "GPSDestLatitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0015: add_entry(ifd_type, "GPSDestLongitudeRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0016: add_entry(ifd_type, "GPSDestLongitude", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0017: add_entry(ifd_type, "GPSDestBearingRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0018: add_entry(ifd_type, "GPSDestBearing", tiff_handle, ifd_entry_offset, entries); break;
	case 0x0019: add_entry(ifd_type, "GPSDestDistanceRef", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001a: add_entry(ifd_type, "GPSDestDistance", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001b: add_entry(ifd_type, "GPSProcessingMethod", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001c: add_entry(ifd_type, "GPSAreaInformation", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001d: add_entry(ifd_type, "GPSDateStamp", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001e: add_entry(ifd_type, "GPSDifferential", tiff_handle, ifd_entry_offset, entries); break;
	case 0x001f: add_entry(ifd_type, "GPSHPositioningError", tiff_handle, ifd_entry_offset, entries); break;
	default:
            add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;
    case IFD0_INTEROPERABILITY:
    case IFD1_INTEROPERABILITY:
        switch (entry_tag) {
	case 0x0001: add_entry(ifd_type, "InteroperabilityIndex", tiff_handle, ifd_entry_offset, entries); break;
	default:
            // do nothing by default; the following catch-all was recording huge amounts of redundant data
            //add_generic_entry(ifd_type, tiff_handle, ifd_entry_offset, entries);
            break;
        }
        break;

    default:
        // not a valid type
        cout << "exif_entry.parse_entry invalid entry tag: " << entry_tag << "\n";
        assert(0);
    }
}