📄 photoshopreader.cpp
字号:
if (m_green_channel == 0)
// assume it's grayscale if only the red channel exists
{
assert( m_red_channel != 0 );
m_red_channel->set( x, y, pixel.red );
}
else
{
assert( m_channels.size() >= 3 );
m_red_channel->set( x, y, pixel.red );
m_green_channel->set( x, y, pixel.green );
m_blue_channel->set( x, y, pixel.blue );
}
if (m_alpha_channel != 0)
m_alpha_channel->set( x, y, pixel.alpha );
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
PIX32 t_photoshop_layer::get_pixel( int x, int y, const PIX24* palette ) const
{
PIX32 result;
int index;
assert( m_channels.size() > 0 );
index = m_channels[0]->get( x, y );
result.red = palette[index].red;
result.green = palette[index].green;
result.blue = palette[index].blue;
if (m_alpha_channel != 0)
result.alpha = m_alpha_channel->get( x, y );
else
result.alpha = 255;
return result;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
const char* k_layer_info_keys[] =
{
"levl", // Levels
"curv", // Curves
"brit", //=Brightness/contrast
"blnc", // '=Color balance
"hue ", // '=Old Hue/saturation, Photoshop 4.0
"hue2", // '=New Hue/saturation, Photoshop 5.0
"selc", // '=Selective color
"thrs", // '=Threshold
"nvrt", // '=Invert
"post", // Posterize};
"lrFx", // effects layer
"tySh", // type tool
"luni", // unicode name
"lyid", // unique id
""
};
enum t_layer_info_type
{
k_layer_levels,
k_layer_curves,
k_layer_brightness,
k_layer_balance,
k_layer_hue_4,
k_layer_hue_5,
k_layer_selective,
k_layer_threshold,
k_layer_invert,
k_layer_posterize,
k_layer_effects,
k_layer_text,
k_layer_unicode_name,
k_layer_id,
k_layer_info_max
};
bool t_photoshop_layer::read( std::streambuf& infile )
{
t_layer_header header;
int channel_index;
t_photoshop_channel* channel;
::read( infile, &header, sizeof(header));
m_top = header.top;
m_left = header.left;
m_bottom = header.bottom;
m_right = header.right;
for (channel_index = 0; channel_index < header.channel_count; channel_index++)
{
t_mac_short id;
t_mac_long length;
infile >> id;
infile >> length;
channel = new t_photoshop_channel( id, m_right - m_left, m_bottom - m_top );
m_channels.push_back( channel );
m_channel_lengths.push_back( length );
switch (id)
{
case 0:
m_red_channel = channel;
break;
case 1:
m_green_channel = channel;
break;
case 2:
m_blue_channel = channel;
break;
case 0xFFFF:
m_alpha_channel = channel;
break;
}
}
char signature[4];
::read( infile, signature, sizeof(signature) );
if (memcmp( signature, "8BIM", 4 ) != 0)
return false;
char blend_key[4];
::read( infile, blend_key, sizeof(blend_key) );
m_blend = static_cast<t_photoshop_blend>(0);
while ( memcmp( blend_key, k_blend_keys[m_blend], sizeof( blend_key )) != 0)
{
m_blend = static_cast<t_photoshop_blend>(m_blend + 1);
if (k_blend_keys[m_blend][0] == 0)
return false;
}
BYTE clipping;
infile >> m_opacity;
infile >> clipping;
infile >> m_flags;
infile.sbumpc(); // skip filler byte
t_mac_long length;
t_mac_long layer_mask_length;
t_mac_long blending_length;
infile >> length; // overall length of extra fields.
infile >> layer_mask_length; // length of layer mask information
infile.pubseekoff( layer_mask_length, std::ios::cur );
infile >> blending_length; // length of blending information
infile.pubseekoff( blending_length, std::ios::cur );
t_pascal_string name(4);
name.read( infile );
m_name = name.get();
length = length - (layer_mask_length + blending_length + name.get_size() + 8);
// begin reading tags
while (length >= 8)
{
char signature[4];
char key[4];
t_mac_long item_length;
int next_position;
::read( infile, signature, sizeof( signature ));
if (memcmp( signature, "8BIM", 4 ) != 0)
return false;
::read( infile, key, sizeof(key));
infile >> item_length;
next_position = tell( infile ) + item_length;
if (memcmp( key, "luni", 4 ) == 0)
{
int i;
t_mac_long string_length;
infile >> string_length;
m_name = "";
for (i = 0; i < string_length; i++)
{
infile.sbumpc();
m_name += infile.sbumpc();
}
}
infile.pubseekpos( next_position );
length = length - 12 - item_length;
}
if (length > 0)
infile.pubseekoff( length, std::ios::cur );
return true;
}
bool t_photoshop_layer::read_channels( std::streambuf& infile, CDxFileProgress* file_progress )
{
int channel_index;
int length;
for (channel_index = 0; channel_index < m_channels.size(); channel_index++)
{
length = infile.pubseekoff( 0, std::ios::cur );
if (!m_channels[channel_index]->read( infile, file_progress ))
return false;
length = tell( infile ) - length;
if (length != m_channel_lengths[channel_index])
return false;
}
return true;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
bool t_photoshop_layer::read_background( std::streambuf& infile, int width, int height,
int channels, int bits_per_channel,
t_photoshop_color_mode mode,
CDxFileProgress* file_progress )
{
m_top = 0;
m_left = 0;
m_bottom = height;
m_right = width;
m_blend = k_blend_normal;
m_opacity = 255;
m_name = "background";
int channel_index;
t_photoshop_channel *channel;
t_mac_short compressed;
std::vector<int> scan_lengths;
infile >> compressed;
scan_lengths.resize( channels * height );
if (compressed != 0)
{
int i;
std::vector<t_mac_short> mac_scan_lengths;
mac_scan_lengths.resize( channels * height );
::read( infile, mac_scan_lengths.begin(), sizeof(t_mac_short) * channels * height );
for (i = 0; i < mac_scan_lengths.size(); i++)
scan_lengths[i] = mac_scan_lengths[i];
}
for (channel_index = 0; channel_index < channels; channel_index++)
{
channel = new t_photoshop_channel( channel_index, width, height );
m_channels.push_back( channel );
if (!channel->read_background( infile, compressed != 0,
scan_lengths.begin() + channel_index * height,
file_progress ))
return false;
}
if (mode == k_color_mode_RGB)
{
m_red_channel = m_channels[0];
m_green_channel = m_channels[1];
m_blue_channel = m_channels[2];
if (m_channels.size() > 3)
m_alpha_channel = m_channels[3];
}
if (mode == k_color_mode_indexed && m_channels.size() > 1)
m_alpha_channel = m_channels[1];
return true;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
bool t_photoshop_layer::write_background( std::streambuf& outfile, CDxFileProgress* file_progress )
{
int channel_index;
t_mac_short compressed;
std::vector<int> scan_lengths;
int height = m_bottom - m_top;
compressed = 1;
outfile << compressed;
scan_lengths.resize( m_channels.size() * height );
int i;
int scan_block_start;
std::vector<t_mac_short> mac_scan_lengths;
scan_block_start = tell( outfile );
mac_scan_lengths.resize( m_channels.size() * height );
::write( outfile, mac_scan_lengths.begin(), sizeof(t_mac_short) * m_channels.size() * height );
channel_index = 0;
if (!m_red_channel->write_background( outfile, scan_lengths.begin(), file_progress ))
return false;
channel_index++;
if (m_green_channel != 0)
{
if (!m_green_channel->write_background( outfile,
scan_lengths.begin() + channel_index * height,
file_progress ))
return false;
channel_index++;
}
if (m_blue_channel != 0)
{
if (!m_blue_channel->write_background( outfile,
scan_lengths.begin() + channel_index * height,
file_progress ))
return false;
channel_index++;
}
if (m_alpha_channel != 0)
{
if (!m_alpha_channel->write_background( outfile,
scan_lengths.begin() + channel_index * height,
file_progress ))
return false;
channel_index++;
}
assert( channel_index == m_channels.size() );
for (i = 0; i < mac_scan_lengths.size(); i++)
mac_scan_lengths[i] = scan_lengths[i];
int file_end = tell( outfile );
outfile.pubseekpos( scan_block_start );
::write( outfile, mac_scan_lengths.begin(), sizeof(t_mac_short) * m_channels.size() * height);
outfile.pubseekpos( file_end );
return true;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
bool t_photoshop_layer::write( std::streambuf& outfile, int* channel_block_start, int index )
{
t_layer_header header;
int channel_index;
header.top = m_top;
header.left = m_left;
header.bottom = m_bottom;
header.right = m_right;
header.channel_count = m_channels.size();
::write( outfile, &header, sizeof(header));
*channel_block_start = tell( outfile );
for (channel_index = 0; channel_index < header.channel_count; channel_index++)
{
t_mac_short id;
t_mac_long length;
id = 0;
length = 0;
outfile << id;
outfile << length;
}
outfile.sputn( "8BIM", 4 );
outfile.sputn( k_blend_keys[m_blend], 4 );
outfile << m_opacity;
outfile.sputc( 0 );// clipping = base
outfile.sputc( m_flags ); // flags = visible
outfile.sputc( 0 ); // filler byte
t_mac_long length;
t_mac_long layer_mask_length;
t_mac_long blending_length;
int extra_field_start = tell( outfile );
length = 0;
layer_mask_length = 0;
blending_length = 0;
outfile << length; // overall length of extra fields.
outfile << layer_mask_length; // length of layer mask information
outfile << blending_length; // length of blending information
t_pascal_string name(4);
name.set( m_name.c_str() );
name.write( outfile );
// write layer id
t_mac_long item_length;
t_mac_long id;
int i;
item_length = 4 + m_name.length() * 2;
outfile.sputn( "8BIMluni", 8 );
outfile << item_length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -