一个开源的Flash 播放器,可以在Windows/Linux 上运行

源代码在线查看: image.cpp

软件大小: 604 K
上传用户: maple_78
关键词: Windows Flash Linux 开源
下载地址: 免注册下载 普通下载 VIP

相关代码

				// image.h	-- Thatcher Ulrich  2002
				
				// This source code has been donated to the Public Domain.  Do
				// whatever you want with it.
				
				// Handy image utilities for RGB surfaces.
				
				#include "base/image.h"
				
				#include "base/container.h"
				#include "base/utility.h"
				#include "base/jpeg.h"
				#include "base/tu_file.h"
				#include 
				#include 
				
				
				namespace image
				{
					//
					// image_base
					//
					image_base::image_base(Uint8* data, int width, int height, int pitch)
						:
						m_data(data),
						m_width(width),
						m_height(height),
						m_pitch(pitch)
					{
					}
				
				
					Uint8*	scanline(image_base* surf, int y)
					{
						assert(surf);
						assert(y >= 0 && y < surf->m_height);
						return ((Uint8*) surf->m_data) + surf->m_pitch * y;
					}
				
				
					const Uint8*	scanline(const image_base* surf, int y)
					{
						assert(surf);
						assert(y >= 0 && y < surf->m_height);
						return ((const Uint8*) surf->m_data) + surf->m_pitch * y;
					}
				
				
					//
					// rgb
					//
				
					rgb::rgb(int width, int height)
						:
						image_base(
							0,
							width,
							height,
							(width * 3 + 3) & ~3)	// round pitch up to nearest 4-byte boundary
					{
						assert(width > 0);
						assert(height > 0);
						assert(m_pitch >= m_width * 3);
						assert((m_pitch & 3) == 0);
				
				//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
						m_data = new Uint8[m_pitch * m_height];
					}
				
					rgb::~rgb()
					{
						if (m_data) {
				//			dlfree(m_data);
							delete [] m_data;
							m_data = 0;
						}
					}
				
				
					rgb*	create_rgb(int width, int height)
					// Create an system-memory rgb surface.  The data order is
					// packed 24-bit, RGBRGB..., regardless of the endian-ness of
					// the CPU.
					{
						rgb*	s = new rgb(width, height);
				
						return s;
					}
				
				
					//
					// rgba
					//
				
				
					rgba::rgba(int width, int height)
						:
						image_base(0, width, height, width * 4)
					{
						assert(width > 0);
						assert(height > 0);
						assert(m_pitch >= m_width * 4);
						assert((m_pitch & 3) == 0);
				
				//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
						m_data = new Uint8[m_pitch * m_height];
					}
				
					rgba::~rgba()
					{
						if (m_data) {
				//			dlfree(m_data);
							delete [] m_data;
							m_data = 0;
						}
					}
				
				
					rgba*	create_rgba(int width, int height)
					// Create an system-memory rgb surface.  The data order is
					// packed 32-bit, RGBARGBA..., regardless of the endian-ness
					// of the CPU.
					{
						rgba*	s = new rgba(width, height);
				
						return s;
					}
				
				
					void	rgba::set_pixel(int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
					// Set the pixel at the given position.
					{
						assert(x >= 0 && x < m_width);
						assert(y >= 0 && y < m_height);
				
						Uint8*	data = scanline(this, y) + 4 * x;
				
						data[0] = r;
						data[1] = g;
						data[2] = b;
						data[3] = a;
					}
				
				
					//
					// alpha
					//
				
				
					alpha*	create_alpha(int width, int height)
					// Create an system-memory 8-bit alpha surface.
					{
						alpha*	s = new alpha(width, height);
				
						return s;
					}
				
				
					alpha::alpha(int width, int height)
						:
						image_base(0, width, height, width)
					{
						assert(width > 0);
						assert(height > 0);
				
				//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
						m_data = new Uint8[m_pitch * m_height];
					}
				
				
					alpha::~alpha()
					{
						if (m_data) {
				//			dlfree(m_data);
							delete [] m_data;
							m_data = 0;
						}
					}
				
				
					void	alpha::set_pixel(int x, int y, Uint8 a)
					// Set the pixel at the given position.
					{
						assert(x >= 0 && x < m_width);
						assert(y >= 0 && y < m_height);
				
						Uint8*	data = scanline(this, y) + x;
				
						data[0] = a;
					}
				
				
					bool	alpha::operator==(const alpha& a) const
					// Bitwise content comparison.
					{
						if (m_width != a.m_width
						    || m_height != a.m_height)
						{
							return false;
						}
				
						for (int j = 0, n = m_height; j < n; j++)
						{
							if (memcmp(scanline(this, j), scanline(&a, j), m_width))
							{
								// Mismatch.
								return false;
							}
						}
				
						// Images are identical.
						return true;
					}
				
				
					unsigned int	alpha::compute_hash() const
					// Compute a hash code based on image contents.  Can be useful
					// for comparing images.
					{
						unsigned int	h = bernstein_hash(&m_width, sizeof(m_width));
						h = bernstein_hash(&m_height, sizeof(m_height), h);
				
						for (int i = 0, n = m_height; i < n; i++)
						{
							h = bernstein_hash(scanline(this, i), m_width, h);
						}
				
						return h;
					}
				
				
					//
					// utility
					//
				
				
					void	write_jpeg(tu_file* out, rgb* image, int quality)
					// Write the given image to the given out stream, in jpeg format.
					{
						jpeg::output*	j_out = jpeg::output::create(out, image->m_width, image->m_height, quality);
				
						for (int y = 0; y < image->m_height; y++) {
							j_out->write_scanline(scanline(image, y));
						}
				
						delete j_out;
					}
				
				
					rgb*	read_jpeg(const char* filename)
					// Create and read a new image from the given filename, if possible.
					{
						tu_file	in(filename, "rb");	// file automatically closes when 'in' goes out of scope.
						if (! in.get_error())
						{
							rgb*	im = read_jpeg(&in);
							return im;
						}
						else
						{
							return NULL;
						}
					}
				
				
					rgb*	read_jpeg(tu_file* in)
					// Create and read a new image from the stream.
					{
						jpeg::input*	j_in = jpeg::input::create(in);
						if (j_in == NULL) return NULL;
						
						rgb*	im = image::create_rgb(j_in->get_width(), j_in->get_height());
				
						for (int y = 0; y < j_in->get_height(); y++)
						{
							j_in->read_scanline(scanline(im, y));
						}
				
						delete j_in;
				
						return im;
					}
				
				
					rgb*	read_swf_jpeg2(tu_file* in)
					// Create and read a new image from the stream.  Image is in
					// SWF JPEG2-style format (the encoding tables come first in a
					// separate "stream" -- otherwise it's just normal JPEG).  The
					// IJG documentation describes this as "abbreviated" format.
					{
						jpeg::input*	j_in = jpeg::input::create_swf_jpeg2_header_only(in);
						if (j_in == NULL) return NULL;
						
						rgb*	im = read_swf_jpeg2_with_tables(j_in);
				
						delete j_in;
				
						return im;
					}
				
				
					rgb*	read_swf_jpeg2_with_tables(jpeg::input* j_in)
					// Create and read a new image, using a input object that
					// already has tables loaded.
					{
						assert(j_in);
				
						j_in->start_image();
				
						rgb*	im = image::create_rgb(j_in->get_width(), j_in->get_height());
				
						for (int y = 0; y < j_in->get_height(); y++) {
							j_in->read_scanline(scanline(im, y));
						}
				
						j_in->finish_image();
				
						return im;
					}
				
				
					rgba*	read_swf_jpeg3(tu_file* in)
					// For reading SWF JPEG3-style image data, like ordinary JPEG, 
					// but stores the data in rgba format.
					{
						jpeg::input*	j_in = jpeg::input::create_swf_jpeg2_header_only(in);
						if (j_in == NULL) return NULL;
						
						j_in->start_image();
				
						rgba*	im = image::create_rgba(j_in->get_width(), j_in->get_height());
				
						Uint8*	line = new Uint8[3*j_in->get_width()];
				
						for (int y = 0; y < j_in->get_height(); y++) 
						{
							j_in->read_scanline(line);
				
							Uint8*	data = scanline(im, y);
							for (int x = 0; x < j_in->get_width(); x++) 
							{
								data[4*x+0] = line[3*x+0];
								data[4*x+1] = line[3*x+1];
								data[4*x+2] = line[3*x+2];
								data[4*x+3] = 255;
							}
						}
				
						delete [] line;
				
						j_in->finish_image();
						delete j_in;
				
						return im;
					}
				
				
					void	write_tga(tu_file* out, rgba* im)
					// Write a 32-bit Targa format bitmap.  Dead simple, no compression.
					{
						out->write_byte(0);
						out->write_byte(0);
						out->write_byte(2);	/* uncompressed RGB */
						out->write_le16(0);
						out->write_le16(0);
						out->write_byte(0);
						out->write_le16(0);	/* X origin */
						out->write_le16(0);	/* y origin */
						out->write_le16(im->m_width);
						out->write_le16(im->m_height);
						out->write_byte(32);	/* 32 bit bitmap */
						out->write_byte(0);
				
						for (int y = 0; y < im->m_height; y++)
						{
							uint8*	p = scanline(im, y);
							for (int x = 0; x < im->m_width; x++)
							{
								out->write_byte(p[x * 4]);
								out->write_byte(p[x * 4 + 1]);
								out->write_byte(p[x * 4 + 2]);
								out->write_byte(p[x * 4 + 3]);
							}
						}
					}
				
				
				#if 0
					SDL_Surface*	create_SDL_Surface(rgb* image)
					// Steal *image's data to create an SDL_Surface.
					//
					// DELETES image!!!
					{
						assert(image->m_pitch < 65536);	// SDL_Surface only uses Uint16 for pitch!!!
				
						SDL_Surface*	s = SDL_CreateRGBSurfaceFrom(image->m_data,
											     image->m_width, image->m_height, 24, image->m_pitch,
											     SDL_SwapLE32(0x0FF),
											     SDL_SwapLE32(0x0FF00),
											     SDL_SwapLE32(0x0FF0000),
											     0);
				
						// s owns *image's data now -- invalidate *image.
						image->m_data = 0;
						image->m_height = 0;
						image->m_width = 0;
						image->m_pitch = 0;
						delete image;
				
						assert(s->pixels);
						assert(s->format->BytesPerPixel == 3);
						assert(s->format->BitsPerPixel == 24);
				
						return s;
					}
				#endif // 0
				
					void	make_next_miplevel(rgb* image)
					// Fast, in-place resample.  For making mip-maps.  Munges the
					// input image to produce the output image.
					{
						assert(image->m_data);
				
						int	new_w = image->m_width >> 1;
						int	new_h = image->m_height >> 1;
						if (new_w < 1) new_w = 1;
						if (new_h < 1) new_h = 1;
				
						int	new_pitch = new_w * 3;
						// Round pitch up to the nearest 4-byte boundary.
						new_pitch = (new_pitch + 3) & ~3;
				
						if (new_w * 2 != image->m_width  || new_h * 2 != image->m_height)
						{
							// Image can't be shrunk along (at least) one
							// of its dimensions, so don't bother
							// resampling.  Technically we should, but
							// it's pretty useless at this point.  Just
							// change the image dimensions and leave the
							// existing pixels.
						}
						else
						{
							// Resample.  Simple average 2x2 --> 1, in-place.
							int	pitch = image->m_pitch;
							for (int j = 0; j < new_h; j++) {
								Uint8*	out = ((Uint8*) image->m_data) + j * new_pitch;
								Uint8*	in = ((Uint8*) image->m_data) + (j 								for (int i = 0; i < new_w; i++) {
									int	r, g, b;
									r = (*(in + 0) + *(in + 3) + *(in + 0 + pitch) + *(in + 3 + pitch));
									g = (*(in + 1) + *(in + 4) + *(in + 1 + pitch) + *(in + 4 + pitch));
									b = (*(in + 2) + *(in + 5) + *(in + 2 + pitch) + *(in + 5 + pitch));
									*(out + 0) = r >> 2;
									*(out + 1) = g >> 2;
									*(out + 2) = b >> 2;
									out += 3;
									in += 6;
								}
							}
						}
				
						// Munge image's members to reflect the shrunken image.
						image->m_width = new_w;
						image->m_height = new_h;
						image->m_pitch = new_pitch;
					}
				
				
					void	make_next_miplevel(rgba* image)
					// Fast, in-place resample.  For making mip-maps.  Munges the
					// input image to produce the output image.
					{
						assert(image->m_data);
				
						int	new_w = image->m_width >> 1;
						int	new_h = image->m_height >> 1;
						if (new_w < 1) new_w = 1;
						if (new_h < 1) new_h = 1;
				
						int	new_pitch = new_w * 4;
				
						if (new_w * 2 != image->m_width  || new_h * 2 != image->m_height)
						{
							// Image can't be shrunk along (at least) one
							// of its dimensions, so don't bother
							// resampling.  Technically we should, but
							// it's pretty useless at this point.  Just
							// change the image dimensions and leave the
							// existing pixels.
						}
						else
						{
							// Resample.  Simple average 2x2 --> 1, in-place.
							int	pitch = image->m_pitch;
							for (int j = 0; j < new_h; j++) {
								Uint8*	out = ((Uint8*) image->m_data) + j * new_pitch;
								Uint8*	in = ((Uint8*) image->m_data) + (j 								for (int i = 0; i < new_w; i++) {
									int	r, g, b, a;
									r = (*(in + 0) + *(in + 4) + *(in + 0 + pitch) + *(in + 4 + pitch));
									g = (*(in + 1) + *(in + 5) + *(in + 1 + pitch) + *(in + 5 + pitch));
									b = (*(in + 2) + *(in + 6) + *(in + 2 + pitch) + *(in + 6 + pitch));
									a = (*(in + 3) + *(in + 7) + *(in + 3 + pitch) + *(in + 7 + pitch));
									*(out + 0) = r >> 2;
									*(out + 1) = g >> 2;
									*(out + 2) = b >> 2;
									*(out + 3) = a >> 2;
									out += 4;
									in += 8;
								}
							}
						}
				
						// Munge image's members to reflect the shrunken image.
						image->m_width = new_w;
						image->m_height = new_h;
						image->m_pitch = new_pitch;
					}
				};
				
				
				// Local Variables:
				// mode: C++
				// c-basic-offset: 8 
				// tab-width: 8
				// indent-tabs-mode: t
				// End:
							

相关资源