PSD preview implementation ยป exiv2-0.21.1_psd_preview.patch
| exiv2-0.21.1/src/image.cpp 2011-04-21 13:58:21.000000000 +0200 | ||
|---|---|---|
| 257 | 257 |
comment_ = comment; |
| 258 | 258 |
} |
| 259 | 259 | |
| 260 |
const DataBuf& Image::preview() const |
|
| 261 |
{
|
|
| 262 |
return preview_; |
|
| 263 |
} |
|
| 264 | ||
| 265 |
DataBuf& Image::preview() |
|
| 266 |
{
|
|
| 267 |
return preview_; |
|
| 268 |
} |
|
| 269 | ||
| 260 | 270 |
void Image::setByteOrder(ByteOrder byteOrder) |
| 261 | 271 |
{
|
| 262 | 272 |
byteOrder_ = byteOrder; |
| exiv2-0.21.1/src/image.hpp 2011-04-22 22:11:09.000000000 +0200 | ||
|---|---|---|
| 385 | 385 |
bool supportsMetadata(MetadataId metadataId) const; |
| 386 | 386 |
//! Return the flag indicating the source when writing XMP metadata. |
| 387 | 387 |
bool writeXmpFromPacket() const; |
| 388 |
/*! |
|
| 389 |
@return modifiable reference to this image's native preview |
|
| 390 |
*/ |
|
| 391 |
virtual DataBuf& preview(); |
|
| 392 |
/*! |
|
| 393 |
@return read only reference to this image's native preview |
|
| 394 |
*/ |
|
| 395 |
virtual const DataBuf& preview() const; |
|
| 388 | 396 |
//@} |
| 389 | 397 | |
| 390 | 398 |
protected: |
| ... | ... | |
| 397 | 405 |
std::string xmpPacket_; //!< XMP packet |
| 398 | 406 |
int pixelWidth_; //!< image pixel width |
| 399 | 407 |
int pixelHeight_; //!< image pixel height |
| 408 |
DataBuf preview_; //!< generic preview image |
|
| 400 | 409 | |
| 401 | 410 |
private: |
| 402 | 411 |
//! @name NOT implemented |
| exiv2-0.21.1/src/preview.cpp 2011-04-22 23:52:35.000000000 +0200 | ||
|---|---|---|
| 236 | 236 |
//! Function to create new LoaderTiff |
| 237 | 237 |
Loader::AutoPtr createLoaderTiff(PreviewId id, const Image &image, int parIdx); |
| 238 | 238 | |
| 239 |
//! Loader for PSD previews in Jpeg format |
|
| 240 |
class LoaderPsdJpeg : public Loader {
|
|
| 241 |
public: |
|
| 242 |
// Constructor |
|
| 243 |
LoaderPsdJpeg(PreviewId id, const Image &image, int parIdx); |
|
| 244 | ||
| 245 |
//! Get properties of a preview image with given params |
|
| 246 |
virtual PreviewProperties getProperties() const; |
|
| 247 | ||
| 248 |
//! Get a buffer that contains the preview image |
|
| 249 |
virtual DataBuf getData() const; |
|
| 250 | ||
| 251 |
//! Read preview image dimensions |
|
| 252 |
virtual bool readDimensions(); |
|
| 253 | ||
| 254 |
}; |
|
| 255 | ||
| 256 |
//! Function to create new LoaderPsdJpeg |
|
| 257 |
Loader::AutoPtr createLoaderPsdJpeg(PreviewId id, const Image &image, int parIdx); |
|
| 258 | ||
| 239 | 259 |
// ***************************************************************************** |
| 240 | 260 |
// class member definitions |
| 241 | 261 | |
| ... | ... | |
| 265 | 285 |
{ 0, createLoaderExifJpeg, 5 },
|
| 266 | 286 |
{ 0, createLoaderExifJpeg, 6 },
|
| 267 | 287 |
{ "image/x-canon-cr2", createLoaderExifJpeg, 7 },
|
| 268 |
{ 0, createLoaderExifJpeg, 8 }
|
|
| 288 |
{ 0, createLoaderExifJpeg, 8 },
|
|
| 289 |
{ 0, createLoaderPsdJpeg, 0 }
|
|
| 269 | 290 |
}; |
| 270 | 291 | |
| 271 | 292 |
const LoaderExifJpeg::Param LoaderExifJpeg::param_[] = {
|
| ... | ... | |
| 663 | 684 |
return DataBuf(mio.mmap(), mio.size()); |
| 664 | 685 |
} |
| 665 | 686 | |
| 687 |
LoaderPsdJpeg::LoaderPsdJpeg(PreviewId id, const Image &image, int parIdx) |
|
| 688 |
: Loader(id, image) |
|
| 689 |
{
|
|
| 690 |
if (image_.preview().size_ > 0) {
|
|
| 691 |
size_ = image_.preview().size_; |
|
| 692 |
valid_ = true; |
|
| 693 |
} |
|
| 694 |
} |
|
| 695 | ||
| 696 |
Loader::AutoPtr createLoaderPsdJpeg(PreviewId id, const Image &image, int parIdx) |
|
| 697 |
{
|
|
| 698 |
return Loader::AutoPtr(new LoaderPsdJpeg(id, image, parIdx)); |
|
| 699 |
} |
|
| 700 | ||
| 701 |
PreviewProperties LoaderPsdJpeg::getProperties() const |
|
| 702 |
{
|
|
| 703 |
PreviewProperties prop = Loader::getProperties(); |
|
| 704 |
prop.mimeType_ = "image/jpeg"; |
|
| 705 |
prop.extension_ = ".jpg"; |
|
| 706 |
#ifdef EXV_UNICODE_PATH |
|
| 707 |
prop.wextension_ = EXV_WIDEN(".jpg");
|
|
| 708 |
#endif |
|
| 709 |
return prop; |
|
| 710 |
} |
|
| 711 | ||
| 712 |
DataBuf LoaderPsdJpeg::getData() const |
|
| 713 |
{
|
|
| 714 |
if (!valid()) return DataBuf(); |
|
| 715 |
return DataBuf(image_.preview().pData_, image_.preview().size_); |
|
| 716 |
} |
|
| 717 | ||
| 718 |
bool LoaderPsdJpeg::readDimensions() |
|
| 719 |
{
|
|
| 720 |
if (!valid()) return false; |
|
| 721 |
if (width_ || height_) return true; |
|
| 722 | ||
| 723 |
try {
|
|
| 724 |
Image::AutoPtr image = ImageFactory::open(image_.preview().pData_, image_.preview().size_); |
|
| 725 |
if (image.get() == 0) return false; |
|
| 726 |
image->readMetadata(); |
|
| 727 | ||
| 728 |
width_ = image->pixelWidth(); |
|
| 729 |
height_ = image->pixelHeight(); |
|
| 730 |
} |
|
| 731 |
catch (const AnyError& /* error */ ) {
|
|
| 732 |
#ifndef SUPPRESS_WARNINGS |
|
| 733 |
EXV_WARNING << "Invalid JPEG preview image.\n"; |
|
| 734 |
#endif |
|
| 735 |
return false; |
|
| 736 |
} |
|
| 737 |
return true; |
|
| 738 |
} |
|
| 739 | ||
| 666 | 740 |
} // namespace |
| 667 | 741 | |
| 668 | 742 |
// ***************************************************************************** |
| exiv2-0.21.1/src/psdimage.cpp 2011-04-22 23:06:29.000000000 +0200 | ||
|---|---|---|
| 296 | 296 |
break; |
| 297 | 297 |
} |
| 298 | 298 | |
| 299 |
// - PS 4.0 preview data is fetched from ThumbnailResource |
|
| 300 |
// - PS >= 5.0 preview data is fetched from ThumbnailResource2 |
|
| 301 |
case kPhotoshopResourceID_ThumbnailResource: |
|
| 302 |
case kPhotoshopResourceID_ThumbnailResource2: |
|
| 303 |
{
|
|
| 304 |
/* Photoshop thumbnail resosurce header |
|
| 305 |
offset length name description |
|
| 306 |
====== ======= ==== =========== |
|
| 307 |
0 4 bytes format = 1 (kJpegRGB). Also supports kRawRGB (0). |
|
| 308 |
4 4 bytes width Width of thumbnail in pixels. |
|
| 309 |
8 4 bytes height Height of thumbnail in pixels. |
|
| 310 |
12 4 bytes widthbytes Padded row bytes as (width * bitspixel + 31) / 32 * 4. |
|
| 311 |
16 4 bytes size Total size as widthbytes * height * planes |
|
| 312 |
20 4 bytes compressedsize Size after compression. Used for consistentcy check. |
|
| 313 |
24 2 bytes bitspixel = 24. Bits per pixel. |
|
| 314 |
26 2 bytes planes = 1. Number of planes. |
|
| 315 |
28 Variable Data JFIF data in RGB format. |
|
| 316 |
Note: For resource ID 1033 the data is in BGR format. |
|
| 317 |
*/ |
|
| 318 | ||
| 319 |
byte buf[28]; |
|
| 320 |
if (io_->read(buf, 28) != 28) |
|
| 321 |
{
|
|
| 322 |
throw Error(3, "Photoshop"); |
|
| 323 |
} |
|
| 324 |
uint32_t format_ = getLong(buf, bigEndian); |
|
| 325 |
uint32_t size_ = getLong(buf + 20, bigEndian); // compressedsize |
|
| 326 | ||
| 327 |
if (format_ == 1 && size_ > 0) {
|
|
| 328 |
DataBuf preview(size_); |
|
| 329 |
io_->read(preview.pData_, preview.size_); |
|
| 330 |
if (io_->error() || io_->eof()) throw Error(14); |
|
| 331 |
preview_ = preview; |
|
| 332 |
} |
|
| 333 |
break; |
|
| 334 |
} |
|
| 335 | ||
| 299 | 336 |
default: |
| 300 | 337 |
{
|
| 301 | 338 |
break; |