提交 830a235b 编写于 作者: B bernard.xiong

add png image

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@112 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 d3282913
#include "libpng/png.h"
#include <rtthread.h>
#include <rtgui/image_png.h>
#include <rtgui/rtgui_system.h>
#define PNG_MAGIC_LEN 8
struct rtgui_image_png
{
rt_bool_t is_loaded;
struct rtgui_filerw* filerw;
/* png image information */
png_structp png_ptr;
png_infop info_ptr;
rt_uint8_t *pixels;
rt_uint8_t *line_pixels;
};
static rt_bool_t rtgui_image_png_check(struct rtgui_filerw* file);
static rt_bool_t rtgui_image_png_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
static void rtgui_image_png_unload(struct rtgui_image* image);
static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
struct rtgui_image_engine rtgui_image_png_engine =
{
"png",
{ RT_NULL },
rtgui_image_png_check,
rtgui_image_png_load,
rtgui_image_png_unload,
rtgui_image_png_blit
};
static void rtgui_image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
struct rtgui_filerw* filerw = (struct rtgui_filerw*)png_ptr->io_ptr;
rtgui_filerw_read(filerw, data, length, 1);
}
static rt_bool_t rtgui_image_png_process(png_structp png_ptr, png_infop info_ptr, struct rtgui_image_png* png)
{
int x, y;
png_bytep row;
png_bytep data;
rtgui_color_t *ptr;
row = (png_bytep) rtgui_malloc (png_get_rowbytes(png_ptr, info_ptr));
if (row == RT_NULL) return RT_FALSE;
ptr = (rtgui_color_t *)png->pixels;
switch (info_ptr->color_type)
{
case PNG_COLOR_TYPE_RGBA:
for (y = 0; y < info_ptr->height; y++)
{
png_read_row(png_ptr, row, png_bytep_NULL);
for (x = 0; x < info_ptr->width; x++)
{
data = &(row[x * 4]);
ptr[x+y*info_ptr->width] = RTGUI_ARGB((255 - data[3]), data[0], data[1], data[2]);
}
}
break;
case PNG_COLOR_TYPE_PALETTE:
for (y = 0; y < info_ptr->height; y++)
{
png_read_row(png_ptr, row, png_bytep_NULL);
for (x = 0; x < info_ptr->width; x++)
{
data = &(row[x]);
ptr[x] = RTGUI_ARGB(0, info_ptr->palette[data[0]].red,
info_ptr->palette[data[0]].green,
info_ptr->palette[data[0]].blue);
}
}
default:
break;
};
rtgui_free(row);
return RT_TRUE;
}
static rt_bool_t rtgui_image_png_check(struct rtgui_filerw* file)
{
int start;
rt_bool_t is_PNG;
rt_uint8_t magic[4];
if ( !file ) return 0;
start = rtgui_filerw_tell(file);
/* move to the begining of file */
rtgui_filerw_seek(file, 0, SEEK_SET);
is_PNG = RT_FALSE;
if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) )
{
if ( magic[0] == 0x89 &&
magic[1] == 'P' &&
magic[2] == 'N' &&
magic[3] == 'G' )
{
is_PNG = RT_TRUE;
}
}
rtgui_filerw_seek(file, start, SEEK_SET);
return(is_PNG);
}
static rt_bool_t rtgui_image_png_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
{
png_uint_32 width;
png_uint_32 height;
int bit_depth;
int color_type;
double gamma;
struct rtgui_image_png* png;
png = (struct rtgui_image_png*) rtgui_malloc(sizeof(struct rtgui_image_png));
png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png->png_ptr == RT_NULL)
{
rtgui_free(png);
return RT_FALSE;
}
png->info_ptr = png_create_info_struct(png->png_ptr);
if (png->info_ptr == RT_NULL)
{
png_destroy_read_struct(&png->png_ptr, NULL, NULL);
rtgui_free(png);
return RT_FALSE;
}
png->filerw = file;
png_set_read_fn (png->png_ptr, png->filerw, rtgui_image_png_read_data);
png_read_info(png->png_ptr, png->info_ptr);
png_get_IHDR(png->png_ptr, png->info_ptr, &width, &height, &bit_depth,
&color_type, NULL, NULL, NULL);
/* set image information */
image->w = width; image->h = height;
image->engine = &rtgui_image_png_engine;
image->data = png;
if (bit_depth == 16)
png_set_strip_16(png->png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png->png_ptr);
if (bit_depth < 8)
png_set_expand(png->png_ptr);
if (png_get_valid(png->png_ptr, png->info_ptr, PNG_INFO_tRNS))
png_set_expand(png->png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png->png_ptr);
/* Ignore background color */
/* set gamma conversion */
if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma))
png_set_gamma(png->png_ptr, (double)2.2, gamma);
png_read_update_info(png->png_ptr, png->info_ptr);
if (load == RT_TRUE)
{
/* load all pixels */
png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
png->line_pixels = RT_NULL;
rtgui_image_png_process(png->png_ptr, png->info_ptr, png);
}
else
{
png->line_pixels = rtgui_malloc(image->w * sizeof(rtgui_color_t));
png->pixels = RT_NULL;
}
}
static void rtgui_image_png_unload(struct rtgui_image* image)
{
struct rtgui_image_png* png;
if (image != RT_NULL)
{
png = (struct rtgui_image_png*) image->data;
png_read_end(png->png_ptr, NULL);
/* destroy png struct */
png_destroy_info_struct(png->png_ptr, &png->info_ptr);
png_destroy_read_struct(&png->png_ptr, NULL, NULL);
if (png->pixels != RT_NULL) rtgui_free(png->pixels);
if (png->line_pixels != RT_NULL) rtgui_free(png->line_pixels);
/* release data */
rtgui_free(png);
}
}
static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
{
rt_uint16_t x, y;
rtgui_color_t* ptr;
rtgui_color_t foreground;
struct rtgui_image_png* png;
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
RT_ASSERT(image->data != RT_NULL);
png = (struct rtgui_image_png*) image->data;
ptr = png->pixels;
/* save foreground color */
foreground = rtgui_dc_get_color(dc);
/* draw each point within dc */
for (y = 0; y < image->h; y ++)
{
for (x = 0; x < image->w; x++)
{
/* not alpha */
if ((*ptr >> 24) != 255)
{
rtgui_dc_set_color(dc, *ptr);
rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1);
}
/* move to next color buffer */
ptr ++;
}
}
/* restore foreground */
rtgui_dc_set_color(dc, foreground);
}
void rtgui_image_png_init()
{
/* register jpeg on image system */
rtgui_image_register_engine(&rtgui_image_png_engine);
}
RTGUI_ROOT=../..
include $(RTGUI_ROOT)/config.mk
SRC = png.c pngerror.c pnggccrd.c pngget.c pngmem.c pngpread.c pngread.c \
pngrio.c pngrtran.c pngrutil.c pngset.c pngtrans.c pngvcrd.c pngwio.c \
pngwrite.c pngwtran.c pngwutil.c
CFLAGS += -I../libz
OBJ = $(SRC:.c=.o)
LIB = libpng.a
all: $(LIB)
$(LIB): $(OBJ)
$(AR) r $@ $?
$(RANLIB) $@
clean :
$(RM) *.o *~ *.bak
$(RM) $(LIB)
$(RM) .depend
dep : .depend
include .depend
.depend: $(SRC)
$(CC) $(CFLAGS) -M $^ > $@
此差异已折叠。
此差异已折叠。
此差异已折叠。
/* pngerror.c - stub functions for i/o and memory allocation
*
* Last changed in libpng 1.2.13 November 13, 2006
* For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1998-2006 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
* This file provides a location for all error handling. Users who
* need special error handling are expected to write replacement functions
* and use png_set_error_fn() to use those functions. See the instructions
* at each function.
*/
#define PNG_INTERNAL
#include "png.h"
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
static void /* PRIVATE */
png_default_error PNGARG((png_structp png_ptr,
png_const_charp error_message));
static void /* PRIVATE */
png_default_warning PNGARG((png_structp png_ptr,
png_const_charp warning_message));
/* This function is called whenever there is a fatal error. This function
* should not be changed. If there is a need to handle errors differently,
* you should supply a replacement error function and use png_set_error_fn()
* to replace the error function at run-time.
*/
void PNGAPI
png_error(png_structp png_ptr, png_const_charp error_message)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
char msg[16];
if (png_ptr != NULL)
{
if (png_ptr->flags&
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
{
if (*error_message == '#')
{
int offset;
for (offset=1; offset<15; offset++)
if (*(error_message+offset) == ' ')
break;
if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
{
int i;
for (i=0; i<offset-1; i++)
msg[i]=error_message[i+1];
msg[i]='\0';
error_message=msg;
}
else
error_message+=offset;
}
else
{
if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
{
msg[0]='0';
msg[1]='\0';
error_message=msg;
}
}
}
}
#endif
if (png_ptr != NULL && png_ptr->error_fn != NULL)
(*(png_ptr->error_fn))(png_ptr, error_message);
/* If the custom handler doesn't exist, or if it returns,
use the default handler, which will not return. */
png_default_error(png_ptr, error_message);
}
/* This function is called whenever there is a non-fatal error. This function
* should not be changed. If there is a need to handle warnings differently,
* you should supply a replacement warning function and use
* png_set_error_fn() to replace the warning function at run-time.
*/
void PNGAPI
png_warning(png_structp png_ptr, png_const_charp warning_message)
{
int offset = 0;
if (png_ptr != NULL)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
if (png_ptr->flags&
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
#endif
{
if (*warning_message == '#')
{
for (offset=1; offset<15; offset++)
if (*(warning_message+offset) == ' ')
break;
}
}
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
(*(png_ptr->warning_fn))(png_ptr, warning_message+offset);
}
else
png_default_warning(png_ptr, warning_message+offset);
}
/* These utilities are used internally to build an error message that relates
* to the current chunk. The chunk name comes from png_ptr->chunk_name,
* this is used to prefix the message. The message is limited in length
* to 63 bytes, the name characters are output as hex digits wrapped in []
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
const static PNG_CONST char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
static void /* PRIVATE */
png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
error_message)
{
int iout = 0, iin = 0;
while (iin < 4)
{
int c = png_ptr->chunk_name[iin++];
if (isnonalpha(c))
{
buffer[iout++] = '[';
buffer[iout++] = png_digit[(c & 0xf0) >> 4];
buffer[iout++] = png_digit[c & 0x0f];
buffer[iout++] = ']';
}
else
{
buffer[iout++] = (png_byte)c;
}
}
if (error_message == NULL)
buffer[iout] = 0;
else
{
buffer[iout++] = ':';
buffer[iout++] = ' ';
png_strncpy(buffer+iout, error_message, 63);
buffer[iout+63] = 0;
}
}
void PNGAPI
png_chunk_error(png_structp png_ptr, png_const_charp error_message)
{
char msg[18+64];
if (png_ptr == NULL)
png_error(png_ptr, error_message);
else
{
png_format_buffer(png_ptr, msg, error_message);
png_error(png_ptr, msg);
}
}
void PNGAPI
png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
{
char msg[18+64];
if (png_ptr == NULL)
png_warning(png_ptr, warning_message);
else
{
png_format_buffer(png_ptr, msg, warning_message);
png_warning(png_ptr, msg);
}
}
/* This is the default error handling function. Note that replacements for
* this function MUST NOT RETURN, or the program will likely crash. This
* function is used by default, or if the program supplies NULL for the
* error function pointer in png_set_error_fn().
*/
static void /* PRIVATE */
png_default_error(png_structp png_ptr, png_const_charp error_message)
{
#ifndef PNG_NO_CONSOLE_IO
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
if (*error_message == '#')
{
int offset;
char error_number[16];
for (offset=0; offset<15; offset++)
{
error_number[offset] = *(error_message+offset+1);
if (*(error_message+offset) == ' ')
break;
}
if((offset > 1) && (offset < 15))
{
error_number[offset-1]='\0';
fprintf(stderr, "libpng error no. %s: %s\n", error_number,
error_message+offset);
}
else
fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset);
}
else
#endif
fprintf(stderr, "libpng error: %s\n", error_message);
#endif
#ifdef PNG_SETJMP_SUPPORTED
if (png_ptr)
{
# ifdef USE_FAR_KEYWORD
{
jmp_buf jmpbuf;
png_memcpy(jmpbuf,png_ptr->jmpbuf,png_sizeof(jmp_buf));
longjmp(jmpbuf, 1);
}
# else
longjmp(png_ptr->jmpbuf, 1);
# endif
}
#else
PNG_ABORT();
#endif
#ifdef PNG_NO_CONSOLE_IO
/* make compiler happy */ ;
if (&error_message != NULL)
return;
#endif
}
/* This function is called when there is a warning, but the library thinks
* it can continue anyway. Replacement functions don't have to do anything
* here if you don't want them to. In the default configuration, png_ptr is
* not used, but it is passed in case it may be useful.
*/
static void /* PRIVATE */
png_default_warning(png_structp png_ptr, png_const_charp warning_message)
{
#ifndef PNG_NO_CONSOLE_IO
# ifdef PNG_ERROR_NUMBERS_SUPPORTED
if (*warning_message == '#')
{
int offset;
char warning_number[16];
for (offset=0; offset<15; offset++)
{
warning_number[offset]=*(warning_message+offset+1);
if (*(warning_message+offset) == ' ')
break;
}
if((offset > 1) && (offset < 15))
{
warning_number[offset-1]='\0';
fprintf(stderr, "libpng warning no. %s: %s\n", warning_number,
warning_message+offset);
}
else
fprintf(stderr, "libpng warning: %s\n", warning_message);
}
else
# endif
fprintf(stderr, "libpng warning: %s\n", warning_message);
#else
/* make compiler happy */ ;
if (warning_message)
return;
#endif
/* make compiler happy */ ;
if (png_ptr)
return;
}
/* This function is called when the application wants to use another method
* of handling errors and warnings. Note that the error function MUST NOT
* return to the calling routine or serious problems will occur. The return
* method used in the default routine calls longjmp(png_ptr->jmpbuf, 1)
*/
void PNGAPI
png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warning_fn)
{
if (png_ptr == NULL)
return;
png_ptr->error_ptr = error_ptr;
png_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
}
/* This function returns a pointer to the error_ptr associated with the user
* functions. The application should free any memory associated with this
* pointer before png_write_destroy and png_read_destroy are called.
*/
png_voidp PNGAPI
png_get_error_ptr(png_structp png_ptr)
{
if (png_ptr == NULL)
return NULL;
return ((png_voidp)png_ptr->error_ptr);
}
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
void PNGAPI
png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
{
if(png_ptr != NULL)
{
png_ptr->flags &=
((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
}
}
#endif
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -25,6 +25,7 @@
/* #define RTGUI_USING_FONT16 */
#define RT_USING_STDIO_FILERW
#define RTGUI_IMAGE_PNG
#define RTGUI_SVR_THREAD_PRIORITY 15
#define RTGUI_SVR_THREAD_TIMESLICE 5
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册