/*
------------------------------------------------------------------------------
denef - Decode NEF image files
Copyright (C) 2000 Daniel Stephens (daniel@cheeseplant.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
------------------------------------------------------------------------------
*/

#include <iostream.h>

#include "metacam.h"

static const char *rcsid="$Id: ifdentry.cc,v 1.3 2000/09/18 07:51:43 daniel Exp $";

vector<tiffUNSIGNED>
IFDEntry::Get_UVALUES() const 
{
    vector<tiffUNSIGNED> v;
    if (type == tBYTE) {
	file.Seek(offset);
	for (unsigned int i=0; i<values; ++i)
	    v.push_back(file.Get_UByte());
    } else if (type == tSHORT) {
	file.Seek(offset);
	for (unsigned int i=0; i<values; ++i)
	    v.push_back(file.Get_UShort());
    } else if (type == tLONG) {
	file.Seek(offset);
	for (unsigned int i=0; i<values; ++i)
	    v.push_back(file.Get_ULong());
    } 
    return v;
}

vector<tiffSIGNED> 
IFDEntry::Get_SVALUES() const 
{
    vector<tiffSIGNED> v;
    if (type == tSBYTE) {
	file.Seek(offset);
	for (unsigned int i=0; i<values; ++i)
	    v.push_back(file.Get_SByte());
    } else if (type == tSSHORT) {
	file.Seek(offset);
	for (unsigned int i=0; i<values; ++i)
	    v.push_back(file.Get_SShort());
    } else if (type == tSLONG) {
	file.Seek(offset);
	for (unsigned int i=0; i<values; ++i)
	    v.push_back(file.Get_SLong());
    } 
    return v;
}

vector<tiffRATIONAL> 
IFDEntry::Get_RATIONALS() const 
{
    vector<tiffRATIONAL> v;
    if (type != tRATIONAL) {return v;}
    file.Seek(offset);
    for (unsigned int i=0; i<values; ++i) {
	tiffUNSIGNED n = file.Get_ULong();
	tiffUNSIGNED d = file.Get_ULong();
	v.push_back(tiffRATIONAL(n,d));
    }
    return v;
}

vector<tiffSRATIONAL> 
IFDEntry::Get_SRATIONALS() const 
{
    vector<tiffSRATIONAL> v;
    if (type != tSRATIONAL) {return v;}
    file.Seek(offset);
    for (unsigned int i=0; i<values; ++i) {
	tiffSIGNED n = file.Get_SLong();
	tiffSIGNED d = file.Get_SLong();
	v.push_back(tiffSRATIONAL(n,d));
    }
    return v;
}

vector<string> 
IFDEntry::Get_STRINGS() const 
{
    vector<string> v;
    if (type != tASCII) {return v;}
    char tmpbuf[1024];
    file.Seek(offset);
    file.Get_Data((unsigned char *)tmpbuf, values);
    tmpbuf[values] = 0;
    v.push_back(string(tmpbuf));
    return v;
}

vector<unsigned char> 
IFDEntry::Get_OPAQUE() const 
{
    vector<unsigned char> v;
    if (type != tUNDEFINED) {return v;}
    int toget=values;
    file.Seek(offset);
    while (toget > 0) {
	unsigned char tmpbuf[1024];
	int g = toget;
	if (g>1024) g=1024;
	file.Get_Data((unsigned char *)tmpbuf, g);
	for (int i=0; i<g; ++i) {
	    v.push_back(tmpbuf[i]);
	}
	toget -= g;
    }
    return v;
}

int 
IFDEntry::Type_Length(unsigned short type)
{
    switch (type) {
    case tBYTE:      return 1; /* BYTE */
    case tASCII:     return 1; /* ASCII */
    case tSHORT:     return 2; /* SHORT */
    case tLONG:      return 4; /* LONG */
    case tRATIONAL:  return 8; /* RATIONAL */
    case tSBYTE:     return 1; /* SBYTE */
    case tUNDEFINED: return 1; /* UNDEFINED */
    case tSSHORT:    return 2; /* SSHORT */
    case tSLONG:     return 4; /* SLONG */
    case tSRATIONAL: return 8; /* SRATIONAL */
    case tFLOAT:     return 4; /* FLOAT */
    case tDOUBLE:    return 8; /* DOUBLE */
    };
    cerr << "WARNING: Unknown field type " << type << endl;
    return 0;
}

static const char *hexdigit="0123456789ABCDEF";

void
IFDEntry::Output_Value(ostream &os) const
{
    switch (type) {
    case 2:
    {
	vector<string> v = Get_STRINGS();
	vector<string>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << "\"" << (*iter) << "\",";
	}
	return;
    }
    case 1:
    case 3:
    case 4:
    {
	vector<tiffUNSIGNED> v = Get_UVALUES();
	vector<tiffUNSIGNED>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    case 5:
    {
	vector<tiffRATIONAL> v = Get_RATIONALS();
	vector<tiffRATIONAL>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    case 7:
    {
	vector<unsigned char> v = Get_OPAQUE();
	vector<unsigned char>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    unsigned char c=(*iter);
	    os << hexdigit[(c >> 4) & 0x0f] << hexdigit[c&0x0F] << " ";
	}
	return;
    }
    case 6:
    case 8:
    case 9:
    {
	vector<tiffSIGNED> v = Get_SVALUES();
	vector<tiffSIGNED>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    case 10:
    {
	vector<tiffSRATIONAL> v = Get_SRATIONALS();
	vector<tiffSRATIONAL>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    }
    // 11 FLOAT
    // 12 DOUBLE
}
