summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--noncore/graphics/opie-eye/slave/jpeg_slave.cpp8
1 files changed, 8 insertions, 0 deletions
diff --git a/noncore/graphics/opie-eye/slave/jpeg_slave.cpp b/noncore/graphics/opie-eye/slave/jpeg_slave.cpp
index fb7d5de..1bb81d9 100644
--- a/noncore/graphics/opie-eye/slave/jpeg_slave.cpp
+++ b/noncore/graphics/opie-eye/slave/jpeg_slave.cpp
@@ -906,524 +906,532 @@ ExifData::ExifData()
//--------------------------------------------------------------------------
// process a EXIF jpeg file
//--------------------------------------------------------------------------
bool ExifData::scan(const QString & path)
{
int ret;
QFile f(path);
f.open(IO_ReadOnly);
// Scan the JPEG headers.
ret = ReadJpegSections(f, READ_EXIF);
if (ret == false){
owarn << "Not JPEG file!" << oendl;
DiscardData();
f.close();
return false;
}
f.close();
DiscardData();
//now make the strings clean,
// for exmaple my Casio is a "QV-4000 "
CameraMake = CameraMake.stripWhiteSpace();
CameraModel = CameraModel.stripWhiteSpace();
UserComment = UserComment.stripWhiteSpace();
Comment = Comment.stripWhiteSpace();
return true;
}
//--------------------------------------------------------------------------
// Does the embedded thumbnail match the jpeg image?
//--------------------------------------------------------------------------
#ifndef JPEG_TOL
#define JPEG_TOL 0.02
#endif
bool ExifData::isThumbnailSane() {
if (Thumbnail.isNull()) return false;
// check whether thumbnail dimensions match the image
// not foolproof, but catches some altered images (jpegtran -rotate)
if (ExifImageLength != 0 && ExifImageLength != Height) return false;
if (ExifImageWidth != 0 && ExifImageWidth != Width) return false;
if (Thumbnail.width() == 0 || Thumbnail.height() == 0) return false;
if (Height == 0 || Width == 0) return false;
double d = (double)Height/Width*Thumbnail.width()/Thumbnail.height();
return (1-JPEG_TOL < d) && (d < 1+JPEG_TOL);
}
static QImage flip_image( const QImage& img );
static QImage rotate_90( const QImage& img );
static QImage rotate_180( const QImage& );
static QImage rotate_270( const QImage& );
//--------------------------------------------------------------------------
// return a thumbnail that respects the orientation flag
// only if it seems sane
//--------------------------------------------------------------------------
QImage ExifData::getThumbnail() {
if (!isThumbnailSane()) return NULL;
if (!Orientation || Orientation == 1) return Thumbnail;
// now fix orientation
QImage dest = Thumbnail;
switch (Orientation) { // notice intentional fallthroughs
case 2: dest = flip_image( dest ); break;
case 4: dest = flip_image( dest );
case 3: dest =rotate_180( dest ); break;
case 5: dest = flip_image( dest );
case 6: dest = rotate_90( dest ); break;
case 7: dest = flip_image( dest );
case 8: dest = rotate_270( dest ); break;
default: break; // should never happen
}
return dest;
}
/*
*
*/
static QImage flip_image( const QImage& img ) {
return img.mirror( TRUE, FALSE );
}
static QImage dest;
static int x, y;
static unsigned int *srcData, *destData; // we're not threaded anyway
static unsigned char *srcData8, *destData8; // 8 bit is char
static unsigned int *srcTable, *destTable; // destination table
static QImage rotate_90_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(x);
destData8[img.height()-y-1] = srcData8[x];
}
}
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 ) {
return b ? QObject::tr( "Colormode: Color\n" ) : QObject::tr( "Colormode: Black and white\n" );
}
static QString 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 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 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 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 );
}
JpegSlave::JpegSlave()
: SlaveInterface( QStringList::split( " ", "jpeg jpg" ) )
{}
JpegSlave::~JpegSlave() {}
QString JpegSlave::iconViewName( const QString& path) {
ExifData ImageInfo;
if ( !ImageInfo.scan( path ) )
return QString::null;
QString tag;
tag = QObject::tr( "Comment: %1\n" ).arg( ImageInfo.getComment() );
{
// ODP fixme
QString timestring = TimeString::dateString( parseDateTime( ImageInfo.getDateTime() ), FALSE );
tag += QObject::tr( "Date/Time: %1\n" ).arg( timestring );
}
tag += QObject::tr( "Dimensions: %1x%2\n" ).arg(ImageInfo.getWidth())
.arg(ImageInfo.getHeight() );
tag += color_mode_to_string( ImageInfo.getIsColor() );
tag += compression_to_string( ImageInfo.getCompressionLevel() );
return tag;
}
/*
* messy messy string creation
*/
QString JpegSlave::fullImageInfo( const QString& path) {
ExifData ImageInfo;
if ( !ImageInfo.scan( path ) )
return QString::null;
QString tag, tmp;
tag = QObject::tr( "<qt>Comment: %1\n" ).arg( ImageInfo.getComment() );
tmp = ImageInfo.getCameraMake();
if ( tmp.length() )
tag += QObject::tr( "Manufacturer: %1\n" ).arg( tmp );
tmp = ImageInfo.getCameraModel();
if ( tmp.length() )
tag += QObject::tr( "Model: %1\n" ).arg( tmp );
{
// ODP fixme
tmp = TimeString::dateString( parseDateTime( ImageInfo.getDateTime() ), FALSE );
tag += QObject::tr( "Date/Time: %1\n" ).arg( tmp );
}
tag += QObject::tr( "Dimensions: %1x%2\n" ).arg(ImageInfo.getWidth())
.arg(ImageInfo.getHeight() );
tag += color_mode_to_string( ImageInfo.getIsColor() );
tag += compression_to_string( ImageInfo.getCompressionLevel() );
if ( ImageInfo.getOrientation() )
tag += QObject::tr( "Orientation: %1\n" ).arg(ImageInfo.getOrientation() );
{
int flash_used = ImageInfo.getFlashUsed();
if ( flash_used >= 0 )
tag += QObject::tr( "Flash used\n" );
}
if ( ImageInfo.getFocalLength() ) {
tag += QObject::tr( "Focal length: %1\n" ).arg( QString().sprintf( "%4.1f", ImageInfo.getFocalLength() ) );
if ( ImageInfo.getCCDWidth() )
tag += QObject::tr( "35mm equivalent: %1\n" ).arg( (int)(ImageInfo.getFocalLength()/ImageInfo.getCCDWidth()*35 + 0.5) );
}
if ( ImageInfo.getCCDWidth() )
tag += QObject::tr( "CCD width: %1" ).arg( ImageInfo.getCCDWidth() );
if ( ImageInfo.getExposureTime() ) {
tmp = QString().sprintf("%4.2f", ImageInfo.getExposureTime() );
float exposureTime = ImageInfo.getExposureTime();
if ( exposureTime > 0 && exposureTime <= 0.5 )
tmp += QString().sprintf(" (1/%d)", (int)(0.5 +1/exposureTime) );
tag += QObject::tr( "Exposure time: %1\n" ).arg( tmp );
}
if ( ImageInfo.getApertureFNumber() )
tag += QObject::tr( "Aperture: %1\n" ).arg( QString().sprintf("f/%3.1f", (double)ImageInfo.getApertureFNumber() ) );
if ( ImageInfo.getDistance() ) {
if ( ImageInfo.getDistance() < 0 )
tag += QObject::tr( "Distance: %1\n" ).arg( QObject::tr( "Infinite" ) );
else
tag += QObject::tr( "Distance: %1\n" ).arg( QString().sprintf( "%5.2fm", (double)ImageInfo.getDistance() ) );
}
if ( ImageInfo.getExposureBias() ) {
tag += QObject::tr( "Exposure bias: %1\n", QString().sprintf("%4.2f", (double)ImageInfo.getExposureBias() ) );
}
if ( ImageInfo.getWhitebalance() != -1 )
tag += white_balance_string( ImageInfo.getWhitebalance() );
if( ImageInfo.getMeteringMode() != -1 )
tag += metering_mode( ImageInfo.getMeteringMode() );
if ( ImageInfo.getExposureProgram() )
tag += exposure_program( ImageInfo.getExposureProgram() );
if ( ImageInfo.getISOequivalent() )
tag += QObject::tr( "ISO equivalent: %1\n" ).arg( QString().sprintf("%2d", ImageInfo.getISOequivalent() ) );
tmp = ImageInfo.getUserComment();
if ( tmp.length() )
tag += QObject::tr( "EXIF comment: %1" ).arg( tmp );
tag += QObject::tr( "</qt>" );
return tag;
}
QPixmap JpegSlave::pixmap( const QString& path, int wid, int hei) {
ExifData ImageInfo;
+ /*
+ */
if ( !ImageInfo.scan( path ) || ImageInfo.isNullThumbnail() ) {
QImage img;
QImageIO iio( path, 0l );
+ if (wid < ImageInfo.getWidth() || hei<ImageInfo.getHeight()) {
+ odebug << "Scaling "<<ImageInfo.getWidth()<<"x"<<ImageInfo.getHeight()
+ << " to "<<wid<<"x"<<hei<< " ("<<path<<")"<<oendl;
QString str = QString( "Fast Shrink( 4 ) Scale( %1, %2, ScaleFree)" ).arg( wid ).arg( hei );
iio.setParameters( str.latin1() );// will be strdupped anyway
+ } else {
+ odebug << "Not scaling "<<ImageInfo.getWidth()<<"x"<<ImageInfo.getHeight()<< " ("<<path<<")"<<oendl;
+ }
img = iio.read() ? iio.image() : QImage();
return ThumbNailTool::scaleImage( img, wid,hei );
}else{
QImage img = ImageInfo.getThumbnail();
return ThumbNailTool::scaleImage( img, wid,hei );
}
}