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

📄 img_png.c

📁 微型浏览器
💻 C
字号:
/******************************************************************************* * * img_png.h  *                    * Original code from dillo http://dillo.sourceforge.net * * Hacked by Garett Spencley for Cheetah Web Browser *  * Copyright (C) 1999 Geoff Lane <zzassgl@twirl.mcc.ac.uk> * Copyright (C) 2000 Luca Rota, Jorge Arellano Cid, Eric Gaudet * Copyright (C) 2001 Garett Spencley <gspen@home.com> *  * 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, 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.  * *******************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <gtk/gtk.h>#include <png.h>#include "img_png.h"#include "debug.h"#define DATASIZE  (png->ipbufsize - png->ipbufstart)#define BLACK     0#define WHITE     255enum prog_state {	IS_finished, IS_init, IS_nextdata};/* * This holds the data that must be saved between calls to this module. * Each time it is called it is supplied with a vector of data bytes * obtained from the web server. The module can process any amount of the * supplied data.  The next time the module is called, the vector may be * extended with additional data bytes to be processed.  The module must * keep track of the current start and cursor position of the input data * vector.  As complete output rasters are determined they are sent out of * the module for additional processing. * * NOTE:  There is no external control of the splitting of the input data * vector (only this module understands PNG format data.) This means that * the complete state of a PNG image being processed must be held in the * structure below so that processing can be suspended or resumed at any * point within an input image. * * In the case of the libpng library, it maintains it's own state in * png_ptr and into_ptr so the FSM is very simple - much simpler than the * ones for XBM and PNM are. */struct _PngImage {	ImageData *Image;	/* Image meta data */	double display_exponent;	/* gamma correction */	gulong width;		/* png image width */	gulong height;		/* png image height */	png_structp png_ptr;	/* libpng private data */	png_infop info_ptr;	/* libpng private info */	guchar *image_data;	/* decoded image data    */	guchar **row_pointers;	/* pntr to row starts    */	jmp_buf jmpbuf;		/* png error processing */	gint error;		/* error flag */	gint rowbytes;		/* No. bytes in image row */	short passes;	short channels;		/* No. image channels *//* * 0                                              last byte * +-------+-+-----------------------------------+-+ * |       | |     -- data to be processed --    | | * +-------+-+-----------------------------------+-+ * ^        ^                                     ^ * ipbuf    ipbufstart                            ipbufsize */	guchar *ipbuf;		/* image data in buffer */	gint ipbufstart;	/* first valid image byte */	gint ipbufsize;		/* size of valid data in */	enum prog_state state;	/* FSM current state  */	guchar *linebuf;	/* o/p raster data */};static void Png_error_handling(png_structp png_ptr, png_const_charp msg){   PngImage *png;   g_print("Png_error_handling: %s\n", msg);   png = png_get_error_ptr(png_ptr);   png->error = 1;   png->state = IS_finished;   longjmp(png->jmpbuf, 1);}static void Png_datainfo_callback(png_structp png_ptr, png_infop info_ptr){	PngImage *png;   	gint color_type;   	gint bit_depth;   	gint interlace_type;   	guint i;	char *buf;   	double gamma;	debug_print("Png_datainfo_callback:\n");   	png = png_get_progressive_ptr(png_ptr);	g_return_if_fail(png != NULL);   	png_get_IHDR(png_ptr, info_ptr, &png->width, &png->height, &bit_depth, &color_type, 					&interlace_type, NULL, NULL);   	debug_print("Png_datainfo_callback: png->width  = %ld\n", png->width);   	debug_print("Png_datainfo_callback: png->height = %ld\n", png->height);   	/* we need RGB/RGBA in the end */   	if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) {    	/* Convert indexed images to RGB */      	png_set_expand (png_ptr);   	} else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {    	/* Convert grayscale to RGB */      	png_set_expand (png_ptr);   	} else if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {      	/* We have transparency header, convert it to alpha channel */      	png_set_expand(png_ptr);   	} else if (bit_depth < 8) {      	png_set_expand(png_ptr);   	}   	if (bit_depth == 16)     	png_set_strip_16(png_ptr);   	/* Get and set gamma information. Beware: gamma correction 2.2 will       only work on PC's. todo: select screen gamma correction for other        platforms. */   	if (png_get_gAMA(png_ptr, info_ptr, &gamma))    	png_set_gamma(png_ptr, 2.2, gamma);   	/* Convert gray scale to RGB */   	if (color_type == PNG_COLOR_TYPE_GRAY ||    	color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {      	png_set_gray_to_rgb(png_ptr);   	}   	/* Interlaced */   	if (interlace_type != PNG_INTERLACE_NONE)       	png->passes = png_set_interlace_handling(png_ptr);   	/* get libpng to update it's state */   	png_read_update_info(png_ptr, info_ptr);   	png_get_IHDR(png_ptr, info_ptr, &png->width, &png->height, &bit_depth, &color_type, 					&interlace_type, NULL, NULL);   	png->rowbytes = png_get_rowbytes(png_ptr, info_ptr);   	png->channels = png_get_channels(png_ptr, info_ptr);   	/* init Dillo specifics */   	debug_print("Png_datainfo_callback: rowbytes = %d\n", png->rowbytes);   	debug_print("Png_datainfo_callback: width    = %ld\n", png->width);   	debug_print("Png_datainfo_callback: height   = %ld\n", png->height);   	png->image_data = (guchar *) g_malloc(png->rowbytes * png->height);   	png->row_pointers = (guchar **) g_malloc(png->height * sizeof(guchar *));   	for (i = 0; i < png->height; i++)    	png->row_pointers[i] = png->image_data + (i * png->rowbytes);   	png->linebuf = g_malloc(3 * png->width);	buf = g_malloc(png->width * png->height * 3);	Image_set_parms(png->Image, buf, png->width, png->height, IMG_TYPE_RGB);}static void Png_datarow_callback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, gint pass){	PngImage *png;	guint i;	if (!new_row)		/* work to do? */		return;	png = png_get_progressive_ptr(png_ptr);	png_progressive_combine_row(png_ptr, png->row_pointers[row_num], new_row);	switch (png->channels) {	case 3:		Image_write(png->Image, png->image_data + (row_num * png->rowbytes), row_num, TRUE);		break;	case 4:		{			/* todo: get the backgound color from the parent 			 * of the image widget -- Livio.                 */			gint a, bg_red, bg_green, bg_blue;			guchar *pl = png->linebuf;			guchar *data = png->image_data + (row_num * png->rowbytes);			/* todo: maybe change prefs.bg_color to `a_Dw_widget_get_bg_color`,			 * when background colors are correctly implementated */		/*	bg_blue = (prefs.bg_color) & 0xFF;			bg_green = (prefs.bg_color >> 8) & 0xFF;			bg_red = (prefs.bg_color >> 16) & 0xFF; */			bg_blue = DW_PAINT_DEFAULT_BGND & 0xFF;			bg_green = (DW_PAINT_DEFAULT_BGND >> 8) & 0xFF;			bg_red = (DW_PAINT_DEFAULT_BGND >> 16) & 0xFF; 			for (i = 0; i < png->width; i++) {				a = *(data + 3);				if (a == 255) {					*(pl++) = *(data++);					*(pl++) = *(data++);					*(pl++) = *(data++);					data++;				} else if (a == 0) {					*(pl++) = bg_red;					*(pl++) = bg_green;					*(pl++) = bg_blue;					data += 4;				} else {					png_composite(*(pl++), *(data++), a, bg_red);					png_composite(*(pl++), *(data++), a, bg_green);					png_composite(*(pl++), *(data++), a, bg_blue);					data++;				}			}			Image_write(png->Image, png->linebuf, row_num, TRUE);			break;		}	default:		g_print("Png_datarow_callback: unexpected number of channels = %d\n", png->channels);		abort();	}}static void Png_dataend_callback(png_structp png_ptr, png_infop info_ptr){	PngImage *png;	debug_print("Png_dataend_callback...");	png = png_get_progressive_ptr(png_ptr);	png->state = IS_finished;}void Png_close(PngImage *png){	if(!png) return;	if (png->image_data != NULL)		g_free(png->image_data);	if (png->row_pointers != NULL)		g_free(png->row_pointers);	if (png->linebuf != NULL)		g_free(png->linebuf);	if (setjmp(png->jmpbuf))		png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);	g_free(png);}void Png_write(PngImage *png, void *Buf, size_t Size){	/* Let's make some sound if we have been called with no data */	g_return_if_fail(Buf != NULL && Size > 0);	debug_print("Png_write: BufSize = %d", Size);	/* Keep local copies so we don't have to pass multiple args to	 * a number of functions. */	png->ipbuf      = Buf;	png->ipbufsize = Size;	/* start/resume the FSM here */	while (png->state != IS_finished && DATASIZE) {		switch (png->state) {		case IS_init:			if(DATASIZE < 8) 				return;	/* need MORE data */			/* check the image signature - DON'T update ipbufstart! */			if (!png_check_sig(png->ipbuf, DATASIZE)) {				/* you lied to me about it being a PNG image */				png->state = IS_finished;				break;			}			/* OK, it looks like a PNG image, lets do some set up stuff */			png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png, (png_error_ptr) Png_error_handling, (png_error_ptr) Png_error_handling);			g_return_if_fail(png->png_ptr != NULL);			png->info_ptr = png_create_info_struct(png->png_ptr);			g_return_if_fail(png->png_ptr != NULL);			setjmp(png->jmpbuf);			if (!png->error) {				png_set_progressive_read_fn(png->png_ptr, png, Png_datainfo_callback,	/* performs local init functions */							    Png_datarow_callback,	/* performs per row action */							    Png_dataend_callback);	/* performs cleanup actions */				png->state = IS_nextdata;			}			break;		case IS_nextdata:						if (setjmp(png->jmpbuf)) {				png->state = IS_finished;			} else if (!png->error) {				png_process_data(png->png_ptr, png->info_ptr, png->ipbuf + png->ipbufstart, DATASIZE);				png->ipbufstart += DATASIZE;			}			break;		default:			g_warning("PNG decoder: bad state = %d\n", png->state);			abort();		}	}}/* * Create the image state data that must be kept between calls */PngImage *Png_new(ImageData * Image){	PngImage *png = g_malloc(sizeof(PngImage));	png->Image = Image;	png->state = IS_init;	png->error = 0;	png->ipbuf = NULL;	png->ipbufstart = 0;	png->ipbufsize = 0;	png->linebuf = NULL;	png->linebuf = NULL;	png->row_pointers = NULL;	png->image_data = NULL;	return png;}/* * MIME handler for "image/png" type * (Sets Png_callback or a_Dicache_callback as the cache-client) */DwWidget *a_Png_image(const char *Type, ImageData *image, void **Data){/* * Type: MIME type * Ptr:  points to a Web structure * Call: Dillo calls this with more data/eod * Data: raw image data */	debug_print("a_Png_image: Type = %s", Type);	debug_print("a_Png_image: libpng - Compiled %s; using %s.", PNG_LIBPNG_VER_STRING, png_libpng_ver);	debug_print("a_Png_image: zlib   - Compiled %s; using %s.\n", ZLIB_VERSION, zlib_version);	if(!image)		image = Image_new(0, 0, NULL, DW_PAINT_DEFAULT_BGND);	*Data = image;	return DW_WIDGET(image);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -