/* * This file is part of Chalk * * Copyright (c) 2006 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_exif_value.h" #include #include namespace { void set16Bit (unsigned char *data, ExifValue::ByteOrder order, const TQ_UINT16* value) { switch (order) { case ExifValue::BYTE_ORDER_MOTOROLA: data[0] = (unsigned char) (*value >> 8); data[1] = (unsigned char) *value; break; case ExifValue::BYTE_ORDER_INTEL: data[0] = (unsigned char) *value; data[1] = (unsigned char) (*value >> 8); break; } } void get16Bit (const unsigned char *data, ExifValue::ByteOrder order, TQ_UINT16* value) { switch (order) { case ExifValue::BYTE_ORDER_MOTOROLA: *value = ((data[0] << 8) | data[1]); break; case ExifValue::BYTE_ORDER_INTEL: *value = ((data[1] << 8) | data[0]); break; } } void get32Bit (const unsigned char *data, ExifValue::ByteOrder order, TQ_UINT32* value) { switch (order) { case ExifValue::BYTE_ORDER_MOTOROLA: *value = ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); break; case ExifValue::BYTE_ORDER_INTEL: *value = ((data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]); } } void set32Bit(unsigned char *data, ExifValue::ByteOrder order, const TQ_UINT32* value) { switch (order) { case ExifValue::BYTE_ORDER_MOTOROLA: data[0] = (unsigned char) (*value >> 24); data[1] = (unsigned char) (*value >> 16); data[2] = (unsigned char) (*value >> 8); data[3] = (unsigned char) *value; break; case ExifValue::BYTE_ORDER_INTEL: data[3] = (unsigned char) (*value >> 24); data[2] = (unsigned char) (*value >> 16); data[1] = (unsigned char) (*value >> 8); data[0] = (unsigned char) *value; break; } } void get64Bit (const unsigned char *data, ExifValue::ByteOrder order, TQ_UINT64* value) { switch (order) { case ExifValue::BYTE_ORDER_MOTOROLA: *value = (((TQ_UINT64)data[0] << 56) | ((TQ_UINT64)data[1] << 48) | ((TQ_UINT64)data[2] << 40) | ((TQ_UINT64)data[3] << 32) | ((TQ_UINT64)data[4] << 24) | ((TQ_UINT64)data[5] << 16) | ((TQ_UINT64)data[6] << 8) | (TQ_UINT64)data[7]); break; case ExifValue::BYTE_ORDER_INTEL: *value = (((TQ_UINT64)data[7] << 56) | ((TQ_UINT64)data[6] << 48) | ((TQ_UINT64)data[5] << 40) | ((TQ_UINT64)data[4] << 32) | ((TQ_UINT64)data[3] << 24) | ((TQ_UINT64)data[2] << 16) | ((TQ_UINT64)data[1] << 8) | (TQ_UINT64)data[0]); } } void set64Bit(unsigned char *data, ExifValue::ByteOrder order, const TQ_UINT64* value) { switch (order) { case ExifValue::BYTE_ORDER_MOTOROLA: data[0] = (unsigned char) (*value >> 56); data[1] = (unsigned char) (*value >> 48); data[2] = (unsigned char) (*value >> 40); data[3] = (unsigned char) (*value >> 32); data[4] = (unsigned char) (*value >> 24); data[5] = (unsigned char) (*value >> 16); data[6] = (unsigned char) (*value >> 8); data[7] = (unsigned char) *value; break; case ExifValue::BYTE_ORDER_INTEL: data[7] = (unsigned char) (*value >> 56); data[6] = (unsigned char) (*value >> 48); data[5] = (unsigned char) (*value >> 40); data[4] = (unsigned char) (*value >> 32); data[3] = (unsigned char) (*value >> 24); data[2] = (unsigned char) (*value >> 16); data[1] = (unsigned char) (*value >> 8); data[0] = (unsigned char) *value; break; } } } ExifValue::ExifValue(ExifType ntype, unsigned char *data, unsigned int size, int ifd, uint ncomponents, ExifValue::ByteOrder order ) : m_ifd(ifd), m_type(ntype), m_components(ncomponents), m_value(0) { allocData(); setValue(data, size, order); } void ExifValue::allocData() { if( type() != EXIF_TYPE_ASCII && type() != EXIF_TYPE_UNDEFINED) { m_value = new ExifNumber[components()]; } else if ( type() == EXIF_TYPE_ASCII ) { m_value = new TQString(); } else if ( type() == EXIF_TYPE_UNDEFINED) { m_value = new UByteArray(); } } bool ExifValue::load(const TQDomElement& elmt) { TQString attr; if( (attr = elmt.attribute("ifd")).isNull() ) return false; m_ifd = attr.toInt(); if( (attr = elmt.attribute("components")).isNull() ) return false; m_components = attr.toInt(); if( (attr = elmt.attribute("type")).isNull() ) return false; m_type = (ExifValue::ExifType)attr.toInt(); allocData(); switch(type()) { case EXIF_TYPE_BYTE: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (TQ_UINT8)0); } else { setValue(i, (TQ_UINT8) attr.toUInt()); } } break; case EXIF_TYPE_ASCII: setAsAscii( elmt.attribute("value" ) ); break; case EXIF_TYPE_SHORT: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (TQ_UINT16)0); } else { setValue(i, (TQ_UINT16) attr.toUInt()); } } break; case EXIF_TYPE_LONG: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (TQ_UINT32)0); } else { setValue(i, (TQ_UINT32) attr.toUInt()); } } break; case EXIF_TYPE_RATIONAL: for(uint i = 0; i < components(); i++) { KisExifRational r; if( (attr = elmt.attribute(TQString("numerator%1").tqarg(i) ) ).isNull() ) { r.numerator = (TQ_UINT32)0; } else { r.numerator = (TQ_UINT32) attr.toUInt(); } if( (attr = elmt.attribute(TQString("denominator%1").tqarg(i) ) ).isNull() ) { r.denominator = (TQ_UINT32)0; } else { r.denominator = (TQ_UINT32) attr.toUInt(); } setValue(i, r); } break; case EXIF_TYPE_SBYTE: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (TQ_INT8)0); } else { setValue(i, (TQ_INT8) attr.toInt()); } } break; case EXIF_TYPE_UNDEFINED: { TQString instr = elmt.attribute("value"); TQByteArray out; TQByteArray in = instr.utf8(); KCodecs::base64Decode( in, out); out.resize(out.size() - 2 ); setAsUndefined((uchar*)out.data(), out.size() ); } break; case EXIF_TYPE_SSHORT: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (TQ_INT16)0); } else { setValue(i, (TQ_INT16) attr.toInt()); } } break; case EXIF_TYPE_SLONG: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (TQ_INT32)0); } else { setValue(i, (TQ_INT32) attr.toInt()); } } break; case EXIF_TYPE_SRATIONAL: for(uint i = 0; i < components(); i++) { KisExifSRational r; if( (attr = elmt.attribute(TQString("numerator%1").tqarg(i) ) ).isNull() ) { r.numerator = (TQ_INT32)0; } else { r.numerator = (TQ_INT32) attr.toInt(); } if( (attr = elmt.attribute(TQString("denominator%1").tqarg(i) ) ).isNull() ) { r.denominator = (TQ_UINT32)0; } else { r.denominator = (TQ_UINT32) attr.toInt(); } setValue(i, r); } break; case EXIF_TYPE_FLOAT: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (float)0); } else { setValue(i, (float) attr.toFloat()); } } break; case EXIF_TYPE_DOUBLE: for(uint i = 0; i < components(); i++) { if( (attr = elmt.attribute(TQString("value%1").tqarg(i) ) ).isNull() ) { setValue(i, (double)0); } else { setValue(i, (double) attr.toDouble()); } } break; case EXIF_TYPE_UNKNOW: break; } return true; } TQDomElement ExifValue::save(TQDomDocument& doc) { TQDomElement elmt = doc.createElement("ExifValue"); elmt.setAttribute("ifd", ifd()); elmt.setAttribute("components", components() ); elmt.setAttribute("type", type() ); switch(type()) { case EXIF_TYPE_BYTE: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asByte( i ) ); break; case EXIF_TYPE_ASCII: elmt.setAttribute("value", asAscii() ); break; case EXIF_TYPE_SHORT: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asShort( i ) ); break; case EXIF_TYPE_LONG: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asLong( i ) ); break; case EXIF_TYPE_RATIONAL: for(uint i = 0; i < components(); i++) { KisExifRational r = asRational(i); elmt.setAttribute(TQString("numerator%1").tqarg(i), r.numerator ); elmt.setAttribute(TQString("denominator%1").tqarg(i), r.denominator ); } break; case EXIF_TYPE_SBYTE: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asSByte( i ) ); break; case EXIF_TYPE_UNDEFINED: { UByteArray value = asUndefined(); TQByteArray data; data.setRawData((char*)value.data(), value.size()); TQByteArray tqencodedData; KCodecs::base64Encode( data, tqencodedData ); data.resetRawData( (char*)value.data(), value.size()); elmt.setAttribute("value", TQString(tqencodedData)); } break; case EXIF_TYPE_SSHORT: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asSShort( i ) ); break; case EXIF_TYPE_SLONG: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asSLong( i ) ); break; case EXIF_TYPE_SRATIONAL: for(uint i = 0; i < components(); i++) { KisExifSRational r = asSRational(i); elmt.setAttribute(TQString("numerator%1").tqarg(i), r.numerator ); elmt.setAttribute(TQString("denominator%1").tqarg(i), r.denominator ); } break; case EXIF_TYPE_FLOAT: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asFloat( i ) ); break; case EXIF_TYPE_DOUBLE: for(uint i = 0; i < components(); i++) elmt.setAttribute(TQString("value%1").tqarg(i), asDouble( i ) ); break; case EXIF_TYPE_UNKNOW: break; } return elmt; } void ExifValue::setValue(const unsigned char *data, unsigned int size, ExifValue::ByteOrder order) { switch(type()) { case EXIF_TYPE_BYTE: if( size == components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { n.m_byte = data[i]; setAsExifNumber( i, n); } } break; case EXIF_TYPE_ASCII: setAsAscii((char*) data); break; case EXIF_TYPE_SHORT: if( size == 2*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get16Bit( data + 2 * i, order, &n.m_short); setAsExifNumber( i, n); } } break; case EXIF_TYPE_LONG: if( size == 4*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get32Bit( data + 4 * i, order, &n.m_long); setAsExifNumber( i, n); } } break; case EXIF_TYPE_RATIONAL: if( size == 8*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get32Bit( data + 8 * i, order, &n.m_rational.numerator); get32Bit( data + 8 * i + 4, order, &n.m_rational.denominator); setAsExifNumber( i, n); } } break; case EXIF_TYPE_SBYTE: if( size == components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { n.m_sbyte = ((TQ_INT8*)data)[i]; setAsExifNumber( i, n); } } break; case EXIF_TYPE_UNDEFINED: setAsUndefined(data, size); break; case EXIF_TYPE_SSHORT: if( size == 2*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get16Bit( data + 2 * i, order, (TQ_UINT16*)&n.m_sshort); setAsExifNumber( i, n); } } break; case EXIF_TYPE_SLONG: if( size == 4*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get32Bit( data + 4 * i, order, (TQ_UINT32*)&n.m_slong); setAsExifNumber( i, n); } } break; case EXIF_TYPE_SRATIONAL: if( size == 8*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get32Bit( data + 8 * i, order, (TQ_UINT32*)&n.m_srational.numerator); get32Bit( data + 8 * i + 4, order, (TQ_UINT32*)&n.m_srational.denominator); setAsExifNumber( i, n); } } break; case EXIF_TYPE_FLOAT: if( size == 4*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get32Bit( data + 4 * i, order, (TQ_UINT32*)&n.m_float); setAsExifNumber( i, n); } } break; case EXIF_TYPE_DOUBLE: if( size == 8*components() ) { ExifNumber n; for(uint i = 0; i < components(); i++) { get64Bit( data + 8 * i, order, (TQ_UINT64*)&n.m_double); setAsExifNumber( i, n); } } break; case EXIF_TYPE_UNKNOW: break; } } void ExifValue::convertToData(unsigned char ** data, unsigned int* size, ExifValue::ByteOrder order) { switch(type()) { case EXIF_TYPE_BYTE: *size = components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { (*data)[i] = asExifNumber(i).m_byte; } return; case EXIF_TYPE_ASCII: { TQString str = asAscii(); *size = str.length(); *data = new uchar[ *size ]; uchar* ptr = *data; memcpy(ptr, str.ascii(), (*size)*sizeof(uchar)); } return; break; case EXIF_TYPE_SHORT: { *size = 2*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { TQ_UINT16 aenms = asExifNumber(i).m_short; set16Bit( (*data) + 2 * i, order, &aenms); } return; } case EXIF_TYPE_LONG: { *size = 4*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { TQ_UINT32 aenml = asExifNumber(i).m_long; set32Bit( (*data) + 4 * i, order, &aenml); } return; } case EXIF_TYPE_RATIONAL: *size = 8*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { ExifNumber n = asExifNumber(i); set32Bit( (*data) + 8 * i, order, &n.m_rational.numerator); set32Bit( (*data) + 8 * i + 4, order, &n.m_rational.denominator); } return; case EXIF_TYPE_SBYTE: *size = components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { *(((TQ_INT8*)*data) + i) = asExifNumber(i).m_sbyte; } return; case EXIF_TYPE_UNDEFINED: { UByteArray array = asUndefined(); *size = array.size(); *data = new uchar[*size]; memcpy( *data, array.data(), (*size)*sizeof(unsigned char)); } return; case EXIF_TYPE_SSHORT: *size = 2*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { TQ_INT16 aenmss = asExifNumber(i).m_sshort; set16Bit( (*data) + 2 * i, order, (TQ_UINT16*)&aenmss); } return; case EXIF_TYPE_SLONG: *size = 4*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { TQ_INT32 aenmsl = asExifNumber(i).m_slong; set32Bit( (*data) + 4 * i, order, (TQ_UINT32*)&aenmsl); } return; case EXIF_TYPE_SRATIONAL: *size = 8*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { ExifNumber n = asExifNumber(i); TQ_INT32 aenmsr_numerator = asExifNumber(i).m_srational.numerator; TQ_INT32 aenmsr_denominator = asExifNumber(i).m_srational.denominator; set32Bit( (*data) + 4 * i, order, (TQ_UINT32*)&aenmsr_numerator); set32Bit( (*data) + 4 * i + 4, order, (TQ_UINT32*)&aenmsr_denominator); } return; case EXIF_TYPE_FLOAT: *size = 4*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { float aenmf = asExifNumber(i).m_float; set32Bit( (*data) + 4 * i, order, (TQ_UINT32*)&aenmf); } return; case EXIF_TYPE_DOUBLE: *size = 8*components(); *data = new uchar[*size]; for(uint i = 0; i < components(); i++) { double aenmd = asExifNumber(i).m_double; set64Bit( (*data) + 4 * i, order, (TQ_UINT64*)&aenmd); } return; case EXIF_TYPE_UNKNOW: break; } } TQString ExifValue::toString() { switch(type()) { case EXIF_TYPE_ASCII: return asAscii(); case EXIF_TYPE_UNDEFINED: { TQString undefined = "undefined"; UByteArray array = asUndefined(); for(uint i = 0; i < components(); i++) { undefined += "\\" + TQString().setNum( array[i] ); } return undefined; } default: { TQString str = ""; for(uint i = 0; i < components(); i++) { str += toString(i); } return str; } } } TQString ExifValue::toString(uint i) { switch(type()) { case EXIF_TYPE_BYTE: return TQString("%1 ").tqarg( asExifNumber( i ).m_byte ); case EXIF_TYPE_SHORT: return TQString("%1 ").tqarg( asExifNumber( i ).m_short ); case EXIF_TYPE_LONG: return TQString("%1 ").tqarg( asExifNumber( i ).m_long ); case EXIF_TYPE_RATIONAL: return TQString("%1 / %2 ").tqarg( asExifNumber( i ).m_rational.numerator ).tqarg( asExifNumber( i ).m_rational.denominator ); case EXIF_TYPE_SBYTE: return TQString("%1 ").tqarg( asExifNumber( i ).m_sbyte ); case EXIF_TYPE_SSHORT: return TQString("%1 ").tqarg( asExifNumber( i ).m_sshort ); case EXIF_TYPE_SLONG: return TQString("%1 ").tqarg( asExifNumber( i ).m_slong ); case EXIF_TYPE_SRATIONAL: return TQString("%1 / %2 ").tqarg( asExifNumber( i ).m_srational.numerator ).tqarg( asExifNumber( i ).m_srational.denominator ); case EXIF_TYPE_FLOAT: return TQString("%1 ").tqarg( asExifNumber( i ).m_float ); case EXIF_TYPE_DOUBLE: return TQString("%1 ").tqarg( asExifNumber( i ).m_double ); default: return "unknow "; } }