/*************************************************************************** copyright : (C) 2003-2006 by Robby Stephenson email : robby@periapsis.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of version 2 of the GNU General Public License as * * published by the Free Software Foundation; * * * ***************************************************************************/ #include "image.h" #include "imagefactory.h" #include "tellico_debug.h" #include "tellico_utils.h" #include <kmdcodec.h> #include <kpixmapio.h> #include <kstaticdeleter.h> #include <tqbuffer.h> #include <tqregexp.h> using Tellico::Data::Image; using Tellico::Data::ImageInfo; KPixmapIO* Image::s_pixmapIO = 0; static KStaticDeleter<KPixmapIO> staticKPixmapIODeleter; KPixmapIO* Image::io() { if(!s_pixmapIO) { staticKPixmapIODeleter.setObject(s_pixmapIO, new KPixmapIO()); } return s_pixmapIO; } Image::Image() : TQImage(), m_id(TQString()), m_linkOnly(false) { } // I'm using the MD5 hash as the id. I consider it rather unlikely that two images in one // collection could ever have the same hash, and this lets me do a fast comparison of two images // simply by comparing their ids. Image::Image(const TQString& filename_) : TQImage(filename_), m_linkOnly(false) { m_format = TQImage::imageFormat(filename_); calculateID(); } Image::Image(const TQImage& img_, const TQString& format_) : TQImage(img_), m_format(format_.ascii()), m_linkOnly(false) { calculateID(); } Image::Image(const TQByteArray& data_, const TQString& format_, const TQString& id_) : TQImage(data_), m_id(idClean(id_)), m_format(format_.ascii()), m_linkOnly(false) { if(isNull()) { m_id = TQString(); } } Image::~Image() { } TQByteArray Image::byteArray() const { return byteArray(*this, outputFormat(m_format)); } bool Image::isNull() const { // 1x1 images are considered null for Tellico. Amazon returns some like that. return TQImage::isNull() || (width() < 2 && height() < 2); } TQPixmap Image::convertToPixmap() const { return io()->convertToPixmap(*this); } TQPixmap Image::convertToPixmap(int w_, int h_) const { if(w_ < width() || h_ < height()) { return io()->convertToPixmap(this->smoothScale(w_, h_, ScaleMin)); } else { return io()->convertToPixmap(*this); } } TQCString Image::outputFormat(const TQCString& inputFormat) { TQStrList list = TQImage::outputFormats(); for(TQStrListIterator it(list); it.current(); ++it) { if(inputFormat == it.current()) { return inputFormat; } } // myDebug() << "Image::outputFormat() - writing " << inputFormat << " as PNG" << endl; return "PNG"; } TQByteArray Image::byteArray(const TQImage& img_, const TQCString& outputFormat_) { TQByteArray ba; TQBuffer buf(ba); buf.open(IO_WriteOnly); TQImageIO iio(&buf, outputFormat_); iio.setImage(img_); iio.write(); buf.close(); return ba; } TQString Image::idClean(const TQString& id_) { static const TQRegExp rx('[' + TQRegExp::escape(TQString::fromLatin1("/@<>#\"&%?={}|^~[]'`\\:+")) + ']'); TQString clean = id_; return shareString(clean.remove(rx)); } void Image::setID(const TQString& id_) { m_id = id_; } void Image::calculateID() { // the id will eventually be used as a filename if(!isNull()) { KMD5 md5(byteArray()); m_id = TQString::fromLatin1(md5.hexDigest()) + TQString::fromLatin1(".") + TQString::fromLatin1(m_format).lower(); m_id = idClean(m_id); } } /******************************************************/ ImageInfo::ImageInfo(const Image& img_) : id(img_.id()) , format(img_.format()) , linkOnly(img_.linkOnly()) , m_width(img_.width()) , m_height(img_.height()) { } ImageInfo::ImageInfo(const TQString& id_, const TQCString& format_, int w_, int h_, bool l_) : id(id_) , format(format_) , linkOnly(l_) , m_width(w_) , m_height(h_) { } int ImageInfo::width(bool loadIfNecessary) const { if(m_width < 1 && loadIfNecessary) { const Image& img = ImageFactory::imageById(id); if(!img.isNull()) { m_width = img.width(); m_height = img.height(); } } return m_width; } int ImageInfo::height(bool loadIfNecessary) const { if(m_height < 1 && loadIfNecessary) { const Image& img = ImageFactory::imageById(id); if(!img.isNull()) { m_width = img.width(); m_height = img.height(); } } return m_height; }