author | alwin <alwin> | 2004-11-06 02:55:45 (UTC) |
---|---|---|
committer | alwin <alwin> | 2004-11-06 02:55:45 (UTC) |
commit | a93a0ee1fce8b2fb7abac475a97dac8001aed8e0 (patch) (side-by-side diff) | |
tree | 21890174b801d6b14c67740596316847d05ffffe | |
parent | 466245b561abe1514ef37ea978b5958caefdc962 (diff) | |
download | opie-a93a0ee1fce8b2fb7abac475a97dac8001aed8e0.zip opie-a93a0ee1fce8b2fb7abac475a97dac8001aed8e0.tar.gz opie-a93a0ee1fce8b2fb7abac475a97dac8001aed8e0.tar.bz2 |
moved a lot of code from opie-eye_slave into lib
-rw-r--r-- | libopie2/opiemm/opieexif.cpp | 54 | ||||
-rw-r--r-- | libopie2/opiemm/opieexif.h | 7 |
2 files changed, 12 insertions, 49 deletions
diff --git a/libopie2/opiemm/opieexif.cpp b/libopie2/opiemm/opieexif.cpp index 0860ea8..de49937 100644 --- a/libopie2/opiemm/opieexif.cpp +++ b/libopie2/opiemm/opieexif.cpp @@ -184,193 +184,192 @@ int ExifData::ReadJpegSections (QFile & infile, ReadMode_t ReadMode) } Sections[SectionsRead].Size = itemlen; Data = (uchar *)malloc(itemlen+1); // Add 1 to allow sticking a 0 at the end. Sections[SectionsRead].Data = Data; // Store first two pre-read bytes. Data[0] = (uchar)lh; Data[1] = (uchar)ll; got = infile.readBlock((char*)Data+2, itemlen-2); // Read the whole section. if (( unsigned ) got != itemlen-2){ return false; } SectionsRead++; switch(marker){ case M_SOS: // stop before hitting compressed data // If reading entire image is requested, read the rest of the data. if (ReadMode & READ_IMAGE){ unsigned long size; size = QMAX( 0ul, infile.size()-infile.at() ); Data = (uchar *)malloc(size); if (Data == NULL){ return false; } got = infile.readBlock((char*)Data, size); if (( unsigned ) got != size){ return false; } Sections[SectionsRead].Data = Data; Sections[SectionsRead].Size = size; Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER; SectionsRead ++; //HaveAll = 1; } return true; case M_EOI: // in case it's a tables-only JPEG stream owarn << "No image in jpeg!" << oendl; return false; case M_COM: // Comment section // pieczy 2002-02-12 // now the User comment goes to UserComment // so we can store a Comment section also in READ_EXIF mode process_COM(Data, itemlen); break; case M_JFIF: // Regular jpegs always have this tag, exif images have the exif // marker instead, althogh ACDsee will write images with both markers. // this program will re-create this marker on absence of exif marker. // hence no need to keep the copy from the file. free(Sections[--SectionsRead].Data); break; case M_EXIF: // Seen files from some 'U-lead' software with Vivitar scanner // that uses marker 31 for non exif stuff. Thus make sure // it says 'Exif' in the section before treating it as exif. if ((ReadMode & READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){ process_EXIF((uchar *)Data, itemlen); }else{ // Discard this section. free(Sections[--SectionsRead].Data); } break; case M_SOF0: case M_SOF1: case M_SOF2: case M_SOF3: case M_SOF5: case M_SOF6: case M_SOF7: case M_SOF9: case M_SOF10: case M_SOF11: case M_SOF13: case M_SOF14: case M_SOF15: process_SOFn(Data, marker); default: break; break; } } return true; } - //-------------------------------------------------------------------------- // Discard read data. //-------------------------------------------------------------------------- void ExifData::DiscardData(void) { for (int a=0; a < SectionsRead; a++) free(Sections[a].Data); SectionsRead = 0; } //-------------------------------------------------------------------------- // Convert a 16 bit unsigned value from file's native byte order //-------------------------------------------------------------------------- int ExifData::Get16u(void * Short) { if (MotorolaOrder){ return (((uchar *)Short)[0] << 8) | ((uchar *)Short)[1]; }else{ return (((uchar *)Short)[1] << 8) | ((uchar *)Short)[0]; } } //-------------------------------------------------------------------------- // Convert a 32 bit signed value from file's native byte order //-------------------------------------------------------------------------- int ExifData::Get32s(void * Long) { if (MotorolaOrder){ return ((( char *)Long)[0] << 24) | (((uchar *)Long)[1] << 16) | (((uchar *)Long)[2] << 8 ) | (((uchar *)Long)[3] << 0 ); }else{ return ((( char *)Long)[3] << 24) | (((uchar *)Long)[2] << 16) | (((uchar *)Long)[1] << 8 ) | (((uchar *)Long)[0] << 0 ); } } //-------------------------------------------------------------------------- // Convert a 32 bit unsigned value from file's native byte order //-------------------------------------------------------------------------- unsigned ExifData::Get32u(void * Long) { return (unsigned)Get32s(Long) & 0xffffffff; } //-------------------------------------------------------------------------- // Evaluate number, be it int, rational, or float from directory. //-------------------------------------------------------------------------- double ExifData::ConvertAnyFormat(void * ValuePtr, int Format) { double Value; Value = 0; switch(Format){ case FMT_SBYTE: Value = *(signed char *)ValuePtr; break; case FMT_BYTE: Value = *(uchar *)ValuePtr; break; case FMT_USHORT: Value = Get16u(ValuePtr); break; case FMT_ULONG: Value = Get32u(ValuePtr); break; case FMT_URATIONAL: case FMT_SRATIONAL: { int Num,Den; Num = Get32s(ValuePtr); Den = Get32s(4+(char *)ValuePtr); if (Den == 0){ Value = 0; }else{ Value = (double)Num/Den; } break; } case FMT_SSHORT: Value = (signed short)Get16u(ValuePtr); break; case FMT_SLONG: Value = Get32s(ValuePtr); break; // Not sure if this is correct (never seen float used in Exif format) case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break; case FMT_DOUBLE: Value = *(double *)ValuePtr; break; } return Value; } //-------------------------------------------------------------------------- // Process one of the nested EXIF directories. //-------------------------------------------------------------------------- void ExifData::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength) { int de; int a; int NumDirEntries; unsigned ThumbnailOffset = 0; unsigned ThumbnailSize = 0; NumDirEntries = Get16u(DirStart); @@ -916,280 +915,237 @@ static QImage rotate_90_8( const QImage &img ) { return dest; } static QImage rotate_90_all( const QImage& img ) { dest.create(img.height(), img.width(), img.depth()); for ( y=0; y < img.height(); ++y ) { srcData = (unsigned int *)img.scanLine(y); for ( x=0; x < img.width(); ++x ) { destData = (unsigned int *)dest.scanLine(x); destData[img.height()-y-1] = srcData[x]; } } return dest; } static QImage rotate_90( const QImage & img ) { if ( img.depth() > 8) return rotate_90_all( img ); else return rotate_90_8( img ); } static QImage rotate_180_all( const QImage& img ) { dest.create(img.width(), img.height(), img.depth()); for ( y=0; y < img.height(); ++y ){ srcData = (unsigned int *)img.scanLine(y); destData = (unsigned int *)dest.scanLine(img.height()-y-1); for ( x=0; x < img.width(); ++x ) destData[img.width()-x-1] = srcData[x]; } return dest; } static QImage rotate_180_8( const QImage& img ) { dest.create(img.width(), img.height(), img.depth()); dest.setNumColors(img.numColors()); srcTable = (unsigned int *)img.colorTable(); destTable = (unsigned int *)dest.colorTable(); for ( x=0; x < img.numColors(); ++x ) destTable[x] = srcTable[x]; for ( y=0; y < img.height(); ++y ){ srcData8 = (unsigned char *)img.scanLine(y); destData8 = (unsigned char *)dest.scanLine(img.height()-y-1); for ( x=0; x < img.width(); ++x ) destData8[img.width()-x-1] = srcData8[x]; } return dest; } static QImage rotate_180( const QImage& img ) { if ( img.depth() > 8 ) return rotate_180_all( img ); else return rotate_180_8( img ); } static QImage rotate_270_8( const QImage& img ) { dest.create(img.height(), img.width(), img.depth()); dest.setNumColors(img.numColors()); srcTable = (unsigned int *)img.colorTable(); destTable = (unsigned int *)dest.colorTable(); for ( x=0; x < img.numColors(); ++x ) destTable[x] = srcTable[x]; for ( y=0; y < img.height(); ++y ){ srcData8 = (unsigned char *)img.scanLine(y); for ( x=0; x < img.width(); ++x ){ destData8 = (unsigned char *)dest.scanLine(img.width()-x-1); destData8[y] = srcData8[x]; } } return dest; } static QImage rotate_270_all( const QImage& img ) { dest.create(img.height(), img.width(), img.depth()); for ( y=0; y < img.height(); ++y ){ srcData = (unsigned int *)img.scanLine(y); for ( x=0; x < img.width(); ++x ){ destData = (unsigned int *)dest.scanLine(img.width()-x-1); destData[y] = srcData[x]; } } return dest; } static QImage rotate_270( const QImage& img ) { if ( img.depth() > 8 ) return rotate_270_all( img ); else return rotate_270_8( img ); } - -static QString color_mode_to_string( bool b ) { +QString ExifData::color_mode_to_string( bool b ) { return b ? QObject::tr( "Colormode: Color\n" ) : QObject::tr( "Colormode: Black and white\n" ); } -static QString compression_to_string( int level ) { +QString ExifData::compression_to_string( int level ) { QString str; switch( level ) { case 1: str = QObject::tr( "Basic" ); break; case 2: str = QObject::tr( "Normal" ); break; case 4: str = QObject::tr( "Fine" ); break; default: str = QObject::tr( "Unknown" ); } return QObject::tr("Quality: %1\n").arg(str); } - -static QDateTime parseDateTime( const QString& string ) -{ - QDateTime dt; - if ( string.length() != 19 ) - return dt; - - QString year = string.left( 4 ); - QString month = string.mid( 5, 2 ); - QString day = string.mid( 8, 2 ); - QString hour = string.mid( 11, 2 ); - QString minute = string.mid( 14, 2 ); - QString seconds = string.mid( 18, 2 ); - - bool ok; - bool allOk = true; - int y = year.toInt( &ok ); - allOk &= ok; - - int mo = month.toInt( &ok ); - allOk &= ok; - - int d = day.toInt( &ok ); - allOk &= ok; - - int h = hour.toInt( &ok ); - allOk &= ok; - - int mi = minute.toInt( &ok ); - allOk &= ok; - - int s = seconds.toInt( &ok ); - allOk &= ok; - - if ( allOk ) { - dt.setDate( QDate( y, mo, d ) ); - dt.setTime( QTime( h, mi, s ) ); - } - - return dt; -} - -static QString white_balance_string( int i ) { +QString ExifData::white_balance_string( int i ) { QString balance; switch ( i ) { case 0: balance = QObject::tr( "Unknown" ); break; case 1: balance = QObject::tr( "Daylight" ); break; case 2: balance = QObject::tr( "Fluorescent" ); break; case 3: balance = QObject::tr( "Tungsten" ); break; case 17: balance = QObject::tr( "Standard light A" ); break; case 18: balance = QObject::tr( "Standard light B" ); break; case 19: balance = QObject::tr( "Standard light C" ); break; case 20: balance = QObject::tr( "D55" ); break; case 21: balance = QObject::tr( "D65" ); break; case 22: balance = QObject::tr( "D75" ); break; case 255: balance = QObject::tr( "Other" ); break; default: balance = QObject::tr( "Unknown" ); } return QObject::tr( "White Balance: %1\n" ).arg( balance ); } -static QString metering_mode( int i) { +QString ExifData::metering_mode( int i) { QString meter; switch( i ) { case 0: meter = QObject::tr( "Unknown" ); break; case 1: meter = QObject::tr( "Average" ); break; case 2: meter = QObject::tr( "Center weighted average" ); break; case 3: meter = QObject::tr( "Spot" ); break; case 4: meter = QObject::tr( "MultiSpot" ); break; case 5: meter = QObject::tr( "Pattern" ); break; case 6: meter = QObject::tr( "Partial" ); break; case 255: meter = QObject::tr( "Other" ); break; default: meter = QObject::tr( "Unknown" ); } return QObject::tr( "Metering Mode: %1\n" ).arg( meter ); } -static QString exposure_program( int i ) { +QString ExifData::exposure_program( int i ) { QString exp; switch( i ) { case 0: exp = QObject::tr( "Not defined" ); break; case 1: exp = QObject::tr( "Manual" ); break; case 2: exp = QObject::tr( "Normal progam" ); break; case 3: exp = QObject::tr( "Aperture priority" ); break; case 4: exp = QObject::tr( "Shutter priority" ); break; case 5: exp = QObject::tr( "Creative progam\n(biased toward fast shutter speed" ); break; case 6: exp = QObject::tr( "Action progam\n(biased toward fast shutter speed)" ); break; case 7: exp = QObject::tr( "Portrait mode\n(for closeup photos with the background out of focus)" ); break; case 8: exp = QObject::tr( "Landscape mode\n(for landscape photos with the background in focus)" ); break; default: exp = QObject::tr( "Unknown" ); } return QObject::tr( "Exposure Program: %1\n" ).arg( exp ); } } // namespace MM } // namespace OPIE diff --git a/libopie2/opiemm/opieexif.h b/libopie2/opiemm/opieexif.h index efaed71..fb06bf8 100644 --- a/libopie2/opiemm/opieexif.h +++ b/libopie2/opiemm/opieexif.h @@ -39,101 +39,108 @@ public: uchar * Data; int Type; unsigned Size; }; struct TagTable_t { unsigned short Tag; const char*const Desc; }; private: static const int MAX_SECTIONS=20; static const unsigned int PSEUDO_IMAGE_MARKER=0x123; Section_t Sections[MAX_SECTIONS]; QString CameraMake; QString CameraModel; QString DateTime; int Orientation; int Height, Width; int ExifImageLength, ExifImageWidth; int IsColor; int Process; int FlashUsed; float FocalLength; float ExposureTime; float ApertureFNumber; float Distance; int Whitebalance; int MeteringMode; float CCDWidth; float ExposureBias; int ExposureProgram; int ISOequivalent; int CompressionLevel; QString UserComment; QString Comment; QImage Thumbnail; unsigned char * LastExifRefd; int ExifSettingsLength; double FocalplaneXRes; double FocalplaneUnits; int MotorolaOrder; int SectionsRead; int ReadJpegSections (QFile & infile, ReadMode_t ReadMode); void DiscardData(void); int Get16u(void * Short); int Get32s(void * Long); unsigned Get32u(void * Long); double ConvertAnyFormat(void * ValuePtr, int Format); void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength); void process_COM (const uchar * Data, int length); void process_SOFn (const uchar * Data, int marker); int Get16m(const void * Short); void process_EXIF(unsigned char * CharBuf, unsigned int length); int Exif2tm(struct ::tm * timeptr, char * ExifTime); public: //! Contructor for initialising ExifData(); //! destructor virtual ~ExifData(); //! scan a given file /*! * try to scan the EXIF data of a image file * \param aFile the file to scan * \return true if success, otherwise false */ bool scan(const QString &aFile); QString getCameraMake() { return CameraMake; } QString getCameraModel() { return CameraModel; } QString getDateTime() { return DateTime; } int getOrientation() { return Orientation; } int getHeight() { return Height; } int getWidth() { return Width; } int getIsColor() { return IsColor; } int getProcess() { return Process; } int getFlashUsed() { return FlashUsed; } float getFocalLength() { return FocalLength; } float getExposureTime() { return ExposureTime; } float getApertureFNumber() { return ApertureFNumber; } float getDistance() { return Distance; } int getWhitebalance() { return Whitebalance; } int getMeteringMode() { return MeteringMode; } float getCCDWidth() { return CCDWidth; } float getExposureBias() { return ExposureBias; } int getExposureProgram() { return ExposureProgram; } int getISOequivalent() { return ISOequivalent; } int getCompressionLevel() { return CompressionLevel; } QString getUserComment() { return UserComment; } QString getComment() { return Comment; } QImage getThumbnail(); bool isThumbnailSane(); bool isNullThumbnail() { return !isThumbnailSane(); } + + // some helpers + static QString color_mode_to_string( bool b ); + static QString compression_to_string( int level ); + static QString white_balance_string( int i ); + static QString metering_mode( int i); + static QString exposure_program( int i ); }; } } #endif |