📄 photoshopreader.cpp
字号:
// --------------------------------------------------------------------------------
bool t_image_resource_header::read( std::streambuf& infile )
{
char signature[4];
::read( infile, signature, sizeof( signature ));
if (memcmp( signature, "8BIM", 4 ) != 0)
return false;
::read( infile, &m_resource_type, sizeof( m_resource_type ));
if (!m_name.read( infile ))
return false;
infile >> m_length;
return true;
}
// --------------------------------------------------------------------------------
// image resource header
// --------------------------------------------------------------------------------
bool t_image_resource_header::write( std::streambuf& outfile, t_resource_type type, const char* name )
{
m_resource_type = type;
m_length = 0;
m_name.set( name );
outfile.sputn( "8BIM", 4 );
outfile << m_resource_type;
m_name.write( outfile );
outfile << m_length;
m_header_end = outfile.pubseekoff( 0, std::ios::cur );
return true;
}
// --------------------------------------------------------------------------------
// image resource header
// --------------------------------------------------------------------------------
bool t_image_resource_header::write_length( std::streambuf& outfile )
{
int file_pos = outfile.pubseekoff( 0, std::ios::cur );
outfile.pubseekoff( m_header_end - sizeof( m_length ), std::ios::cur );
m_length = file_pos - m_header_end;
outfile << m_length;
outfile.pubseekpos( file_pos );
if ((file_pos & 1) == 1)
outfile.sputc( 0 ); // add a padding byte to make total length even.
return true;
}
static const char* k_blend_keys[] =
{ "norm", "dark", "lite", "hue ", "sat ", "colr", "lum ", "mul ", "scrn", "diss",
"over", "hLit", "sLit", "diff", "smud", "div ", "idiv", "" };
// ------------------------------------------------------------------------
// read a compressed image
// ------------------------------------------------------------------------
bool t_photoshop_channel::read_compressed( std::streambuf& infile, bool padded,
int* scan_lengths, CDxFileProgress* file_progress )
{
int x, y;
BYTE* row_ptr;
int count;
int run;
BYTE pixel;
int size = 0;
row_ptr = m_data.begin();
for (y = 0; y < m_height; y++)
{
count = 0;
x = 0;
while (x < m_width)
{
run = infile.sbumpc();
count++;
if (run <= 127)
{
::read( infile, row_ptr, run + 1 );
count += run + 1;
x += run + 1;
row_ptr += run + 1;
}
else
{
pixel = infile.sbumpc();
memset( row_ptr, pixel, 257 - run );
count++;
x += 257 - run;
row_ptr += 257 - run;
}
}
// read padding byte, if any.
if (count != scan_lengths[y])
return false;
if (file_progress != 0)
{
size += m_width;
if (size >= k_file_progress_unit)
{
file_progress->increment( size / k_file_progress_unit );
size = size % k_file_progress_unit;
}
}
}
if (file_progress != 0 && size > 0)
file_progress->increment(1);
return true;
}
// ------------------------------------------------------------------------
// photoshop channel
// ------------------------------------------------------------------------
bool t_photoshop_channel::read( std::streambuf& infile, CDxFileProgress* file_progress )
{
t_mac_short compressed;
infile >> compressed;
if (!compressed)
{
::read( infile, m_data.begin(), m_width * m_height );
if (file_progress != 0)
file_progress->increment( (m_width * m_height + k_file_progress_unit - 1)
/ k_file_progress_unit );
}
else
{
// read scan line sizes
std::vector<t_mac_short> mac_scan_lengths;
std::vector<int> scan_lengths;
int i;
scan_lengths.resize( m_height );
mac_scan_lengths.resize( m_height );
::read( infile, mac_scan_lengths.begin(), sizeof(t_mac_short) * m_height );
for (i = 0; i < m_height; i++)
scan_lengths[i] = mac_scan_lengths[i];
return read_compressed( infile, true, scan_lengths.begin(), file_progress );
}
return true;
}
// ------------------------------------------------------------------------
// photoshop channel
// ------------------------------------------------------------------------
bool t_photoshop_channel::read_background( std::streambuf& infile, bool compressed,
int* scan_lengths, CDxFileProgress* file_progress )
{
if (!compressed)
{
::read( infile, m_data.begin(), m_width * m_height );
if (file_progress != 0)
file_progress->increment( (m_width * m_height + k_file_progress_unit - 1)
/ k_file_progress_unit );
return true;
}
return read_compressed( infile, false, scan_lengths, file_progress );
}
// ------------------------------------------------------------------------
// read a compressed image
// ------------------------------------------------------------------------
bool t_photoshop_channel::write_compressed( std::streambuf& outfile, int* scan_lengths,
CDxFileProgress* file_progress )
{
int x, y;
BYTE* row_ptr;
BYTE* block_start;
int block_length;
int count;
int run;
int size = 0;
row_ptr = m_data.begin();
for (y = 0; y < m_height; y++)
{
count = 0;
x = 0;
// record start of scan line
scan_lengths[y] = outfile.pubseekoff( 0, std::ios::cur );
// compress a single scan line
while (x < m_width)
{
block_start = row_ptr;
block_length = 0;
run = 1;
// find how many consecutive bytes of the same type we have
do
{
run = 1;
while (x + run < m_width && *row_ptr == row_ptr[run] && run < 128)
run++;
// stop if we have a run of 4 or more bytes.
if ( run >= 4 )
break;
// move ahead to the next unique byte
if ( run + block_length <= 128 )
block_length += run;
else
{ // limit uncompressed block length to 128 bytes
run = 128 - block_length;
block_length = 128;
}
x += run;
row_ptr += run;
} while ( block_length < 128 && x < m_width);
// write an uncompressed block
if (block_length > 0)
{
outfile.sputc( block_length - 1 );
::write( outfile, block_start, block_length );
}
// write run, if any
if (run >= 4)
{
outfile.sputc( 257 - run );
outfile.sputc( *row_ptr );
row_ptr += run;
x += run;
}
}
// record line length
int position = outfile.pubseekoff( 0, std::ios::cur );
scan_lengths[y] = position - scan_lengths[y];
if (file_progress != 0)
{
size += m_width;
if (size >= k_file_progress_unit)
{
file_progress->increment( size / k_file_progress_unit );
size = size % k_file_progress_unit;
}
}
}
if (file_progress != 0 && size > 0)
file_progress->increment(1);
return true;
}
// ------------------------------------------------------------------------
// photoshop channel
// ------------------------------------------------------------------------
bool t_photoshop_channel::write_background( std::streambuf& outfile, int* scan_lengths,
CDxFileProgress* file_progress )
{
return write_compressed( outfile, scan_lengths, file_progress );
}
// ------------------------------------------------------------------------
// photoshop channel
// ------------------------------------------------------------------------
bool t_photoshop_channel::write( std::streambuf& outfile, CDxFileProgress* file_progress )
{
t_mac_short compressed;
compressed = 1;
outfile << compressed;
// read scan line sizes
std::vector<t_mac_short> mac_scan_lengths;
std::vector<int> scan_lengths;
int i;
int scan_block_start = outfile.pubseekoff( 0, std::ios::cur );
scan_lengths.resize( m_height );
mac_scan_lengths.resize( m_height );
::write( outfile, mac_scan_lengths.begin(), sizeof(t_mac_short) * m_height );
if (!write_compressed( outfile, scan_lengths.begin(), file_progress ))
return false;
int file_end = outfile.pubseekoff( 0, std::ios::cur );
outfile.pubseekpos( scan_block_start );
for (i = 0; i < m_height; i++)
mac_scan_lengths[i] = scan_lengths[i];
::write( outfile, mac_scan_lengths.begin(), sizeof(t_mac_short) * m_height );
outfile.pubseekpos( file_end );
return true;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
t_photoshop_layer::t_photoshop_layer()
{
m_red_channel = 0;
m_green_channel = 0;
m_blue_channel = 0;
m_alpha_channel = 0;
m_flags = 8;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
t_photoshop_layer::t_photoshop_layer( const char* name, int top, int left, int bottom, int right,
int bits )
{
int width = right - left;
int height = bottom - top;
m_name = name;
m_top = top;
m_left = left;
m_bottom = bottom;
m_right = right;
m_opacity = 255;
m_blend = k_blend_normal;
m_red_channel = new t_photoshop_channel( 0, width, height );
if (bits >= 24)
{
m_green_channel = new t_photoshop_channel( 1, width, height );
m_blue_channel = new t_photoshop_channel( 2, width, height );
}
else
{
m_green_channel = 0;
m_blue_channel = 0;
}
if (bits < 32)
m_alpha_channel = 0;
else
{
m_alpha_channel = new t_photoshop_channel( 0xffff, width, height );
m_channels.push_back( m_alpha_channel );
}
m_channels.push_back( m_red_channel );
if (bits >= 24)
{
m_channels.push_back( m_green_channel );
m_channels.push_back( m_blue_channel );
}
}
// ------------------------------------------------------------------------
// photoshop channel
// ------------------------------------------------------------------------
t_photoshop_layer::~t_photoshop_layer()
{
int i;
for (i = 0; i < m_channels.size(); i++)
delete m_channels[i];
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
PIX32 t_photoshop_layer::get_pixel( int x, int y ) const
{
PIX32 result;
if ( x < m_left || x >= m_right || y < m_top || y >= m_bottom )
{
result.alpha = 0;
return result;
}
x -= m_left;
y -= m_top;
if (m_green_channel == 0)
// assume it's grayscale if only the red channel exists
{
assert( m_red_channel != 0 );
result.red = result.green = result.blue = m_red_channel->get(x,y);
}
else
{
assert( m_channels.size() >= 3 );
result.red = m_red_channel->get( x, y );
result.green = m_green_channel->get( x, y );
result.blue = m_blue_channel->get( x, y );
}
if (m_alpha_channel != 0)
result.alpha = m_alpha_channel->get( x, y );
else
result.alpha = 255;
return result;
}
// ------------------------------------------------------------------------
// photoshop layer
// ------------------------------------------------------------------------
void t_photoshop_layer::set_pixel( int x, int y, PIX32 pixel )
{
if ( x < m_left || x >= m_right || y < m_top || y >= m_bottom )
return;
x -= m_left;
y -= m_top;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -