?? bitmap.cpp
字號:
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998 Olivier Debon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
///////////////////////////////////////////////////////////////
// Author : Olivier Debon <odebon@club-internet.fr>
//
#include "swf.h"
#ifdef RCSID
static char *rcsid = "$Id: bitmap.cc,v 1.5 1999/09/09 13:19:01 ode Exp $";
#endif
static unsigned char *inputData;
// Class variables
int Bitmap::haveTables = 0;
struct jpeg_decompress_struct Bitmap::jpegObject;
struct jpeg_source_mgr Bitmap::jpegSourceManager;
MyErrorHandler Bitmap::jpegErrorMgr;
Bitmap::Bitmap(long id, int level) : Character(BitmapType, id )
{
pixels = NULL;
alpha_buf = NULL;
colormap = NULL;
nbColors = 0;
defLevel = level;
}
Bitmap::~Bitmap()
{
if (pixels) {
delete[] pixels;
}
if (alpha_buf) {
delete[] alpha_buf;
}
if (colormap)
{
delete colormap;
}
if (haveTables) {
jpeg_destroy_decompress(&jpegObject);
haveTables = 0;
}
}
static void errorExit(j_common_ptr info)
{
(*info->err->output_message) (info);
longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1);
}
// Methods for Source data manager
static void initSource(struct jpeg_decompress_struct *cInfo)
{
cInfo->src->bytes_in_buffer = 0;
}
static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo)
{
cInfo->src->next_input_byte = inputData;
cInfo->src->bytes_in_buffer = 1;
inputData++;
return 1;
}
static void skipInputData(struct jpeg_decompress_struct *cInfo, long count)
{
cInfo->src->bytes_in_buffer = 0;
inputData += count;
}
static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired)
{
return jpeg_resync_to_restart(cInfo, desired);
}
static void termSource(struct jpeg_decompress_struct *cInfo)
{
}
long Bitmap::getWidth()
{
return width;
}
long Bitmap::getHeight()
{
return height;
}
Color *
Bitmap::getColormap(long *n) {
if (n) *n = nbColors;
return colormap;
}
unsigned char *
Bitmap::getPixels()
{
return pixels;
}
// Read Tables and Compressed data to produce an image
static int buildJpegAlpha(Bitmap *b, unsigned char *buffer)
{
z_stream stream;
int status;
unsigned char *data;
data = new unsigned char[b->width*b->height];
if (data == NULL)
return -1;
stream.next_in = buffer;
stream.avail_in = 1;
stream.next_out = data;
stream.avail_out = b->width*b->height;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
status = inflateInit(&stream);
while (1) {
status = inflate(&stream, Z_SYNC_FLUSH) ;
if (status == Z_STREAM_END) {
break;
}
if (status != Z_OK) {
printf("Zlib data error : %s\n", stream.msg);
delete data;
return -1;
}
stream.avail_in = 1;
}
inflateEnd(&stream);
b->alpha_buf = data;
return 0;
}
int
Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset)
{
struct jpeg_decompress_struct cInfo;
struct jpeg_source_mgr mySrcMgr;
MyErrorHandler errorMgr;
JSAMPROW buffer[1];
unsigned char *ptrPix;
int stride;
long n;
#if PRINT&1
printf("flash: loading jpeg (interchange)\n");
#endif
// Kludge to correct some corrupted files
if (stream[1] == 0xd9 && stream[3] == 0xd8) {
stream[3] = 0xd9;
stream[1] = 0xd8;
}
// Setup error handler
cInfo.err = jpeg_std_error(&errorMgr.pub);
errorMgr.pub.error_exit = errorExit;
if (setjmp(errorMgr.setjmp_buffer)) {
// JPEG data Error
jpeg_destroy_decompress(&cInfo);
if (pixels) {
delete[] pixels;
pixels = NULL;
}
return -1;
}
// Set current stream pointer to stream
inputData = stream;
// Here it's Ok
jpeg_create_decompress(&cInfo);
// Setup source manager structure
mySrcMgr.init_source = initSource;
mySrcMgr.fill_input_buffer = fillInputBuffer;
mySrcMgr.skip_input_data = skipInputData;
mySrcMgr.resync_to_restart = resyncToRestart;
mySrcMgr.term_source = termSource;
// Set default source manager
cInfo.src = &mySrcMgr;
jpeg_read_header(&cInfo, FALSE);
jpeg_read_header(&cInfo, TRUE);
cInfo.quantize_colors = TRUE; // Create colormapped image
jpeg_start_decompress(&cInfo);
// Set objet dimensions
height = cInfo.output_height;
width = cInfo.output_width;
bpl = width;
pixels = new unsigned char [height*width];
if (pixels == NULL) {
jpeg_finish_decompress(&cInfo);
jpeg_destroy_decompress(&cInfo);
return -1;
}
ptrPix = pixels;
stride = cInfo.output_width * cInfo.output_components;
buffer[0] = (JSAMPROW)malloc(stride);
while (cInfo.output_scanline < cInfo.output_height) {
jpeg_read_scanlines(&cInfo, buffer, 1);
memcpy(ptrPix,buffer[0],stride);
ptrPix+= stride;
}
free(buffer[0]);
colormap = new Color[cInfo.actual_number_of_colors];
if (colormap == NULL) {
delete pixels;
jpeg_finish_decompress(&cInfo);
jpeg_destroy_decompress(&cInfo);
return -1;
}
nbColors = cInfo.actual_number_of_colors;
for(n=0; n < nbColors; n++)
{
colormap[n].red = cInfo.colormap[0][n];
colormap[n].green = cInfo.colormap[1][n];
colormap[n].blue = cInfo.colormap[2][n];
}
jpeg_finish_decompress(&cInfo);
jpeg_destroy_decompress(&cInfo);
if (read_alpha) {
if (buildJpegAlpha(this, stream + offset) < 0) {
return -1;
}
}
return 0;
}
// Read JPEG image using pre-loaded Tables
int
Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
{
JSAMPROW buffer[1];
unsigned char *ptrPix;
int stride;
long n;
int status;
#if PRINT&1
printf("flash: loading jpeg (abbreviated)\n");
#endif
// Set current stream pointer to stream
inputData = stream;
// Error handler
if (setjmp(jpegErrorMgr.setjmp_buffer)) {
// JPEG data Error
//jpeg_destroy_decompress(&jpegObject);
if (pixels) {
delete[] pixels;
pixels = NULL;
}
return -1;
}
// Here it's ok
jpeg_read_header(&jpegObject, TRUE);
jpegObject.quantize_colors = TRUE; // Create colormapped image
jpeg_start_decompress(&jpegObject);
// Set objet dimensions
height = jpegObject.output_height;
width = jpegObject.output_width;
bpl = width;
pixels = new unsigned char [height*width];
if (pixels == NULL) {
jpeg_finish_decompress(&jpegObject);
return -1;
}
ptrPix = pixels;
stride = jpegObject.output_width * jpegObject.output_components;
buffer[0] = (JSAMPROW)malloc(stride);
while (jpegObject.output_scanline < jpegObject.output_height) {
status = jpeg_read_scanlines(&jpegObject, buffer, 1);
memcpy(ptrPix,buffer[0],stride);
ptrPix+= stride;
}
free(buffer[0]);
colormap = new Color[jpegObject.actual_number_of_colors];
if (colormap == NULL) {
jpeg_finish_decompress(&jpegObject);
delete pixels;
return -1;
}
nbColors = jpegObject.actual_number_of_colors;
for(n=0; n < nbColors; n++)
{
colormap[n].red = jpegObject.colormap[0][n];
colormap[n].green = jpegObject.colormap[1][n];
colormap[n].blue = jpegObject.colormap[2][n];
}
status = jpeg_finish_decompress(&jpegObject);
return 0;
}
// Just init JPEG object and read JPEG Tables
int
Bitmap::readJpegTables(unsigned char *stream)
{
if (haveTables) {
//Error, it has already been initialized
return -1;
}
// Setup error handler
jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
jpegErrorMgr.pub.error_exit = errorExit;
if (setjmp(jpegErrorMgr.setjmp_buffer)) {
// JPEG data Error
jpeg_destroy_decompress(&jpegObject);
return -1;
}
// Set current stream pointer to stream
inputData = stream;
// Here it's Ok
jpeg_create_decompress(&jpegObject);
// Setup source manager structure
jpegSourceManager.init_source = initSource;
jpegSourceManager.fill_input_buffer = fillInputBuffer;
jpegSourceManager.skip_input_data = skipInputData;
jpegSourceManager.resync_to_restart = resyncToRestart;
jpegSourceManager.term_source = termSource;
// Set default source manager
jpegObject.src = &jpegSourceManager;
jpeg_read_header(&jpegObject, FALSE);
haveTables = 1;
return 0;
}
int Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize)
{
z_stream stream;
int status;
unsigned char *data;
#if PRINT&1
printf("flash: loading with zlib\n");
#endif
this->width = width;
this->height = height;
this->bpl = width;
stream.next_in = buffer;
stream.avail_in = 1;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
tableSize++;
// Uncompress Color Table
if (format == 3) {
unsigned char *colorTable;
long n;
// Ajust width for 32 bit padding
width = (width+3)/4*4;
this->width = width;
this->bpl = width;
depth = 1;
colorTable = new unsigned char[tableSize*3];
if (colorTable == NULL) {
return -1;
}
stream.next_out = colorTable;
stream.avail_out = tableSize*3;
inflateInit(&stream);
while (1) {
status = inflate(&stream, Z_SYNC_FLUSH);
if (status == Z_STREAM_END) {
break;
}
if (status != Z_OK) {
printf("Zlib cmap error : %s\n", stream.msg);
return -1;
}
stream.avail_in = 1;
// Colormap if full
if (stream.avail_out == 0) {
break;
}
}
nbColors = tableSize;
colormap = new Color[nbColors];
if (colormap == NULL) {
delete colorTable;
return -1;
}
for(n=0; n < nbColors; n++) {
colormap[n].red = colorTable[n*3+0];
colormap[n].green = colorTable[n*3+1];
colormap[n].blue = colorTable[n*3+2];
}
delete colorTable;
} else if (format == 4) {
depth = 2;
} else if (format == 5) {
depth = 4;
}
data = new unsigned char[depth*width*height];
if (data == NULL) {
if (colormap) delete colormap;
return -1;
}
stream.next_out = data;
stream.avail_out = depth*width*height;
if (format != 3) {
status = inflateInit(&stream);
}
while (1) {
status = inflate(&stream, Z_SYNC_FLUSH) ;
if (status == Z_STREAM_END) {
break;
}
if (status != Z_OK) {
printf("Zlib data error : %s\n", stream.msg);
delete data;
return -1;
}
stream.avail_in = 1;
}
inflateEnd(&stream);
pixels = new unsigned char [height*width];
if (pixels == NULL) {
if (colormap) delete colormap;
delete data;
return -1;
}
if (format != 3) {
int n,c;
unsigned char r,g,b,a;
unsigned char *ptr;
r = g = b = a = 0; /* to supress warnings */
nbColors = 0;
colormap = new Color[256];
if (colormap == NULL) {
delete data;
delete pixels;
return -1;
}
memset(colormap, 0, 256 * sizeof(Color));
ptr = pixels;
for(n=0; n < width*height*depth; n+=depth,ptr++) {
switch (format) {
case 4:
break;
case 5:
a = data[n];
// Reduce color dynamic range
r = data[n+1]&0xe0;
g = data[n+2]&0xe0;
b = data[n+3]&0xe0;
break;
}
for(c=0; c < nbColors; c++) {
if (r == colormap[c].red
&& g == colormap[c].green
&& b == colormap[c].blue) {
*ptr = c;
break;
}
}
if (c == nbColors) {
if (nbColors == 256) continue;
nbColors++;
if (nbColors == 256) {
//printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
}
colormap[c].alpha = a;
colormap[c].red = r;
colormap[c].green = g;
colormap[c].blue = b;
*ptr = c;
}
}
} else {
memcpy(pixels, data, width*height);
}
delete data;
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -