?? pluginpsd.cpp
字號:
// ==========================================================
// Photoshop Loader
//
// Design and implementation by
// - Floris van den Berg (flvdberg@wxs.nl)
//
// Based on public domain code created and
// published by Thatcher Ulrich (ulrich@world.std.com)
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// ==========================================================
#include "FreeImage.h"
// ==========================================================
// Bitmap pointer access macros
// ==========================================================
#define BP_START(DIB, WIDTH, HEIGHT) \
int xxxscanline = 0; \
unsigned *xxxbits = (unsigned *)FreeImage_GetScanLine(DIB, HEIGHT - 1 - xxxscanline); \
unsigned *xxxp = xxxbits;
#define BP_NEXT(DIB, WIDTH, HEIGHT) \
xxxp++; \
if (xxxp - xxxbits == WIDTH) { \
xxxscanline++; \
xxxbits = (unsigned *)FreeImage_GetScanLine(DIB, HEIGHT - 1 - xxxscanline); \
xxxp = xxxbits; \
}
#define BP_SETVALUE(VALUE, OFFSET) \
((unsigned char *)xxxp)[OFFSET] = VALUE;
// ==========================================================
// Internal functions
// ==========================================================
static unsigned
Read8(FreeImageIO *io, fi_handle handle) {
unsigned char i = 0;
io->read_proc(&i, 1, 1, handle);
return i;
}
static unsigned
Read16(FreeImageIO *io, fi_handle handle) {
// reads a two-byte big-endian integer from the given file and returns its value.
// assumes unsigned.
unsigned hi = Read8(io, handle);
unsigned lo = Read8(io, handle);
return lo + (hi << 8);
}
static unsigned
Read32(FreeImageIO *io, fi_handle handle) {
// reads a four-byte big-endian integer from the given file and returns its value.
// assumes unsigned.
unsigned b3 = Read8(io, handle);
unsigned b2 = Read8(io, handle);
unsigned b1 = Read8(io, handle);
unsigned b0 = Read8(io, handle);
return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
}
// ----------------------------------------------------------
static void
ScanForResolution(float* hres, float* vres, FreeImageIO *io, fi_handle handle, int width, int height, int channel_count, int byte_count) {
// scans through the next byte_count bytes of the file, looking for an
// image resource block encoding the image's resolution. Returns the resolution(s),
// if found, in the pointed-to floats. Units are in pixels/meter.
while (byte_count) {
// read the image resource block header.
if (Read32(io, handle) != 0x3842494D /* "8BIM" */)
throw "image resource block has unknown signature";
int id = Read16(io, handle);
// skip the name.
int name_length = Read8(io, handle) | 1; // name_length must be odd, so that total including size byte is even.
io->seek_proc(handle, name_length, SEEK_CUR);
// get the size of the data block.
int data_size = Read32(io, handle);
if ((data_size & 1) == 1)
data_size++; // block size must be even.
// account for header size.
byte_count -= 11 + name_length;
// if this block is a resolution info structure, then get the resolution.
if (id == 0x03ED) {
int junk;
int hres_fixed = Read32(io, handle);
junk = Read16(io, handle); // display units of hres.
junk = Read16(io, handle); // display units of width.
int vres_fixed = Read32(io, handle);
junk = Read16(io, handle); // display units of vres.
junk = Read16(io, handle); // display units of height.
byte_count -= data_size;
data_size -= 16;
// skip any extra bytes at the end of this block...
if (data_size > 0)
io->seek_proc(handle, data_size, SEEK_CUR);
// need to convert resolution figures from fixed point, pixels/inch
// to floating point, pixels/meter.
*hres = hres_fixed * ((float)39.4 / (float)65536.0);
*vres = vres_fixed * ((float)39.4 / (float)65536.0);
} else {
// skip the rest of this block.
io->seek_proc(handle, data_size, SEEK_CUR);
byte_count -= data_size;
}
}
}
// ----------------------------------------------------------
static FIBITMAP *
LoadPSDRGB(FreeImageIO *io, fi_handle handle, int width, int height, int channel_count) {
// skip the mode data. (it's the palette for indexed color; other info for other modes.)
long area = width * height;
int mode_data_count = Read32(io, handle);
if (mode_data_count)
io->seek_proc(handle, mode_data_count, SEEK_CUR);
// skip the image resources. (resolution, pen tool paths, alpha channel names, etc)
int resource_data_count = Read32(io, handle);
if (resource_data_count)
io->seek_proc(handle, resource_data_count, SEEK_CUR);
// skip the reserved data
int reserved_data_count = Read32(io, handle);
if (reserved_data_count)
io->seek_proc(handle, reserved_data_count, SEEK_CUR);
// find out if the data is compressed
// 0: no compressiod
// 1: RLE compressed
unsigned compression = Read16(io, handle);
if ((compression > 1) || (compression < 0))
return NULL;
// some formatting information about the channels
const struct ChannelInfo {
int ofs, deflt;
} Channel[4] = {
{ FI_RGBA_RED, 0 }, // red
{ FI_RGBA_GREEN, 0 }, // green
{ FI_RGBA_BLUE, 0 }, // blue
{ FI_RGBA_ALPHA, 255 } // alpha
};
// Create the destination bitmap
FIBITMAP *dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
// finally, read the image data.
if (compression) {
// the RLE-compressed data is preceeded by a 2-byte data count for each row in the data
io->seek_proc(handle, height * channel_count * 2, SEEK_CUR);
// read the RLE data by channel
for (int channel = 0; channel < 4; channel++) {
const ChannelInfo &c = Channel[channel];
BP_START(dib, width, height)
if (channel >= channel_count) {
// fill this channel with default data.
for (int i = 0; i < area; i++) {
BP_SETVALUE(c.deflt, c.ofs);
BP_NEXT(dib, width, height)
}
} else {
// read the RLE data.
int count = 0;
while (count < area) {
int len = Read8(io, handle);
if (len == 128) {
// nop
} else if (len < 128) {
// copy next len + 1 bytes literally.
len++;
// check for buffer overrun
if ((count + len) > area) {
len = area - count;
}
count += len;
while (len) {
BP_SETVALUE(Read8(io, handle), c.ofs);
BP_NEXT(dib, width, height)
len--;
}
} else if (len > 128) {
// next -len + 1 bytes in the dest are replicated from next source byte.
// (interpret len as a negative 8-bit int.)
len ^= 0x0FF;
len += 2;
// check for buffer overrun
if ((count + len) > area) {
len = area - count;
}
count += len;
unsigned val = Read8(io, handle);
while (len) {
BP_SETVALUE(val, c.ofs);
BP_NEXT(dib, width, height)
len--;
}
}
}
}
}
} else {
// we're at the raw image data. it's each channel in order (Red, Green, Blue, Alpha, ...)
// where each channel consists of an 8-bit value for each pixel in the image.
for (int channel = 0; channel < 4; channel++) {
const ChannelInfo &c = Channel[channel];
BP_START(dib, width, height)
if (channel > channel_count) {
// fill this channel with default data.
for (int i = 0; i < area; i++) {
BP_SETVALUE(c.deflt, c.ofs);
BP_NEXT(dib, width, height)
}
} else {
// read the data
for (int i = 0; i < area; i++) {
BP_SETVALUE(Read8(io, handle), c.ofs);
BP_NEXT(dib, width, height)
}
}
}
}
return dib;
}
// ==========================================================
// Plugin Interface
// ==========================================================
static int s_format_id;
// ==========================================================
// Plugin Implementation
// ==========================================================
static const char * DLL_CALLCONV
Format() {
return "PSD";
}
static const char * DLL_CALLCONV
Description() {
return "Adobe Photoshop";
}
static const char * DLL_CALLCONV
Extension() {
return "psd";
}
static const char * DLL_CALLCONV
MimeType() {
return "image/freeimage-psd";
}
static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
return (Read32(io, handle) == 0x38425053);
}
static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
return FALSE;
}
// ----------------------------------------------------------
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
try {
if (Read32(io, handle) == 0x38425053) {
if (Read16(io, handle) == 1) {
// 6 reserved bytes.
Read32(io, handle);
Read16(io, handle);
// Read the number of channels (R, G, B, A, etc).
unsigned channel_count = Read16(io, handle);
if (channel_count >= 0 && channel_count <= 16) {
unsigned height = Read32(io, handle);
unsigned width = Read32(io, handle);
if (Read16(io, handle) == 8) {
unsigned mode = Read16(io, handle);
// Valid options are:
// 0: Bitmap (not implemented)
// 1: Grayscale (not implemented)
// 2: Indexed color (not implemented)
// 3: RGB color
// 4: CMYK color (not implemented)
// 7: Multichannel (not implemented)
// 8: Duotone (not implemented)
// 9: Lab color (not implemented)
switch (mode) {
case 3 :
return LoadPSDRGB(io, handle, width, height, channel_count);
default :
throw "color mode not supported";
}
}
}
}
}
} catch(const char *message) {
FreeImage_OutputMessageProc(s_format_id, message);
}
return NULL;
}
// ==========================================================
// Init
// ==========================================================
void DLL_CALLCONV
InitPSD(Plugin *plugin, int format_id) {
s_format_id = format_id;
plugin->format_proc = Format;
plugin->description_proc = Description;
plugin->extension_proc = Extension;
plugin->regexpr_proc = NULL;
plugin->open_proc = NULL;
plugin->close_proc = NULL;
plugin->pagecount_proc = NULL;
plugin->pagecapability_proc = NULL;
plugin->load_proc = Load;
plugin->save_proc = NULL;
plugin->validate_proc = Validate;
plugin->mime_proc = MimeType;
plugin->supports_export_bpp_proc = SupportsExportDepth;
plugin->supports_export_type_proc = SupportsExportType;
plugin->supports_icc_profiles_proc = NULL; // not implemented yet;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -