⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 photoshopreader.cpp

📁 网络泡泡被.net管理
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// --------------------------------------------------------------------------------
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 + -