📄 psd_handler.cpp
字号:
// =================================================================================================// ADOBE SYSTEMS INCORPORATED// Copyright 2002-2007 Adobe Systems Incorporated// All Rights Reserved//// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms// of the Adobe license agreement accompanying it.// =================================================================================================#include "PSD_Handler.hpp"#include "TIFF_Support.hpp"#include "PSIR_Support.hpp"#include "IPTC_Support.hpp"#include "ReconcileLegacy.hpp"#include "MD5.h"using namespace std;// =================================================================================================/// \file PSD_Handler.cpp/// \brief File format handler for PSD (Photoshop).////// This handler ...///// =================================================================================================// =================================================================================================// PSD_CheckFormat// ===============// For PSD we just check the "8BPS" signature, the following version, and that the file is at least// 34 bytes long. This covers the 26 byte header, the 4 byte color mode section length (which might// be 0), and the 4 byte image resource section length (which might be 0). The parsing logic in// CacheFileData will do further checks that the image resources actually exist. Those checks are// not needed to decide if this is a PSD file though, instead they decide if this is valid PSD.// ! The CheckXyzFormat routines don't track the filePos, that is left to ScanXyzFile.bool PSD_CheckFormat ( XMP_FileFormat format, XMP_StringPtr filePath, LFA_FileRef fileRef, XMPFiles * parent ){ IgnoreParam(format); IgnoreParam(filePath); IgnoreParam(parent); XMP_Assert ( format == kXMP_PhotoshopFile ); IOBuffer ioBuf; LFA_Seek ( fileRef, 0, SEEK_SET ); if ( ! CheckFileSpace ( fileRef, &ioBuf, 34 ) ) return false; // 34 = header plus 2 lengths if ( ! CheckBytes ( ioBuf.ptr, "8BPS", 4 ) ) return false; ioBuf.ptr += 4; // Move to the version. XMP_Uns16 version = GetUns16BE ( ioBuf.ptr ); if ( (version != 1) && (version != 2) ) return false; return true; } // PSD_CheckFormat// =================================================================================================// PSD_MetaHandlerCTor// ===================XMPFileHandler * PSD_MetaHandlerCTor ( XMPFiles * parent ){ return new PSD_MetaHandler ( parent );} // PSD_MetaHandlerCTor// =================================================================================================// PSD_MetaHandler::PSD_MetaHandler// ================================PSD_MetaHandler::PSD_MetaHandler ( XMPFiles * _parent ) : iptcMgr(0), exifMgr(0), skipReconcile(false){ this->parent = _parent; this->handlerFlags = kPSD_HandlerFlags; this->stdCharForm = kXMP_Char8Bit;} // PSD_MetaHandler::PSD_MetaHandler// =================================================================================================// PSD_MetaHandler::~PSD_MetaHandler// =================================PSD_MetaHandler::~PSD_MetaHandler(){ if ( this->iptcMgr != 0 ) delete ( this->iptcMgr ); if ( this->exifMgr != 0 ) delete ( this->exifMgr );} // PSD_MetaHandler::~PSD_MetaHandler// =================================================================================================// PSD_MetaHandler::CacheFileData// ==============================//// Find and parse the image resource section, everything we want is in there. Don't simply capture// the whole section, there could be lots of stuff we don't care about.// *** This implementation simply returns when an invalid file is encountered. Should we throw instead?void PSD_MetaHandler::CacheFileData(){ LFA_FileRef fileRef = this->parent->fileRef; XMP_PacketInfo & packetInfo = this->packetInfo; XMP_AbortProc abortProc = this->parent->abortProc; void * abortArg = this->parent->abortArg; const bool checkAbort = (abortProc != 0); XMP_Assert ( (! this->containsXMP) && (! this->containsTNail) ); // Set containsXMP to true here only if the XMP image resource is found. if ( checkAbort && abortProc(abortArg) ) { XMP_Throw ( "PSD_MetaHandler::CacheFileData - User abort", kXMPErr_UserAbort ); } XMP_Uns8 psdHeader[30]; XMP_Int64 filePos; XMP_Uns32 ioLen, cmLen, psirLen; filePos = LFA_Seek ( fileRef, 0, SEEK_SET ); ioLen = LFA_Read ( fileRef, psdHeader, 30 ); if ( ioLen != 30 ) return; // Throw? this->imageHeight = GetUns32BE ( &psdHeader[14] ); this->imageWidth = GetUns32BE ( &psdHeader[18] ); cmLen = GetUns32BE ( &psdHeader[26] ); XMP_Int64 psirOrigin = 26 + 4 + cmLen; filePos = LFA_Seek ( fileRef, psirOrigin, SEEK_SET ); if ( filePos != psirOrigin ) return; // Throw? ioLen = LFA_Read ( fileRef, psdHeader, 4 ); if ( ioLen != 4 ) return; // Throw? psirLen = GetUns32BE ( &psdHeader[0] ); this->psirMgr.ParseFileResources ( fileRef, psirLen ); PSIR_Manager::ImgRsrcInfo xmpInfo; bool found = this->psirMgr.GetImgRsrc ( kPSIR_XMP, &xmpInfo ); if ( found ) { // printf ( "PSD_MetaHandler::CacheFileData - XMP packet offset %d (0x%X), size %d\n", // xmpInfo.origOffset, xmpInfo.origOffset, xmpInfo.dataLen ); this->packetInfo.offset = xmpInfo.origOffset; this->packetInfo.length = xmpInfo.dataLen; this->packetInfo.padSize = 0; // Assume for now, set these properly in ProcessXMP. this->packetInfo.charForm = kXMP_CharUnknown; this->packetInfo.writeable = true; this->xmpPacket.assign ( (XMP_StringPtr)xmpInfo.dataPtr, xmpInfo.dataLen ); this->containsXMP = true; } } // PSD_MetaHandler::CacheFileData// =================================================================================================// PSD_MetaHandler::ProcessTNail// =============================//// A Photoshop file has a thumbnail in image resource 1036. This has the following layout://// offset length description// 0 4 Format: 0 = kRawRGB, 1 = kJpegRGB// 4 4 Thumbnail image width in pixels// 8 4 Thumbnail image height in pixels// 12 4 Width bytes: Padded row bytes = (width * bits per pixel + 31) / 32 * 4// 16 4 Total size = widthbytes * height * planes // 20 4 Size after compression, used for consistency check// 24 2 Bits per pixel, must be 24// 26 2 Number of planes, must be 1// 28 - Thumbnail image stream//// We return the full image resource as the tnailImage part of the XMP_ThumbnailInfo. The client is// responsible for all further parsing, including conversions on little endian machines. (Since// Photoshop image resources are always stored big endian.)//// Actually image resource 1036 is for Photoshop 5 and later. Photoshop 4 used image resource 1033,// which was similar but used BGR pixels. We are ignoring the earlier format.void PSD_MetaHandler::ProcessTNail(){ this->processedTNail = true; // Make sure we only come through here once. this->containsTNail = false; // Set it to true after all of the info is gathered. PSIR_Manager::ImgRsrcInfo tnailRsrc; bool found = this->psirMgr.GetImgRsrc ( kPSIR_Thumbnail, &tnailRsrc ); if ( ! found ) return; this->tnailInfo.fileFormat = this->parent->format; this->tnailInfo.tnailFormat = kXMP_PShopTNail; this->tnailInfo.fullWidth = this->imageWidth; this->tnailInfo.fullHeight = this->imageHeight; this->tnailInfo.tnailImage = (XMP_Uns8*)tnailRsrc.dataPtr; this->tnailInfo.tnailSize = tnailRsrc.dataLen; this->tnailInfo.tnailWidth = GetUns32BE ( this->tnailInfo.tnailImage + 4 ); this->tnailInfo.tnailHeight = GetUns32BE ( this->tnailInfo.tnailImage + 8 ); this->tnailInfo.fullOrientation = this->tnailInfo.tnailOrientation = 0; // ! Not present in PSD files. this->containsTNail = true;} // PSD_MetaHandler::ProcessTNail// =================================================================================================// PSD_MetaHandler::ProcessXMP// ===========================//// Process the raw XMP and legacy metadata that was previously cached.void PSD_MetaHandler::ProcessXMP(){ this->processedXMP = true; // Make sure we only come through here once.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -