libpng - Loading a png from memory question

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
DeNitro
Posts: 4
Joined: Fri Sep 16, 2005 5:13 pm

libpng - Loading a png from memory question

Post by DeNitro »

The libpng screenshot code compiles and works great. I was trying to modify the code to load a PNG from a buffer in memory compiled in using bin2o rather than a file buffer. I replaced png_init_io() call with png_set_read_fn() and pointed it to a custom read funcion I wrote but I can't seem it get my function to do anything but crash the psp. Anyone know of a sample with a custom PNG read function they could point me to or have any experience with it?
Big thanks in advance if anyone can help, I've been stumped by it for a few days now.

--DeNitro
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

DeNitro
Posts: 4
Joined: Fri Sep 16, 2005 5:13 pm

Post by DeNitro »

Awesome got it working. Thanks again mrbrown and great job on the pspsdk. You guys are amazing :)

--DeNitro
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Any examples of how to use it in code?
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Code: Select all

void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
{
}

typedef struct
{

    const unsigned char *buffer;
    png_uint_32 bufsize;
    png_uint_32 current_pos;

} MEMORY_READER_STATE;

static void read_data_memory(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
	MEMORY_READER_STATE *f = (MEMORY_READER_STATE *)png_get_io_ptr(png_ptr);
	if (length > (f->bufsize - f->current_pos)) png_error(png_ptr, "read error in read_data_memory (loadpng)");
	memcpy(data, f->buffer + f->current_pos, length);
	f->current_pos += length;
}

Image* loadImageMemory(const void *buffer, int bufsize)
{
	png_structp png_ptr;
	png_infop info_ptr;
	MEMORY_READER_STATE memory_reader_state;
	unsigned int sig_read = 0;
	png_uint_32 width, height;
	int bit_depth, color_type, interlace_type, x, y;
	u32* line;
	
	if &#40;!buffer || &#40;bufsize <= 0&#41;&#41; return NULL;

	Image* image = &#40;Image*&#41; malloc&#40;sizeof&#40;Image&#41;&#41;;
	if &#40;!image&#41; return NULL;

	png_ptr = png_create_read_struct&#40;PNG_LIBPNG_VER_STRING, NULL, NULL, NULL&#41;;
	if &#40;png_ptr == NULL&#41; &#123;
		free&#40;image&#41;;
		return NULL;;
	&#125;

	png_set_error_fn&#40;png_ptr, &#40;png_voidp&#41; NULL, &#40;png_error_ptr&#41; NULL, user_warning_fn&#41;;

	info_ptr = png_create_info_struct&#40;png_ptr&#41;;
	if &#40;info_ptr == NULL&#41; &#123;
		free&#40;image&#41;;
		png_destroy_read_struct&#40;&png_ptr, png_infopp_NULL, png_infopp_NULL&#41;;
		return NULL;
	&#125;

	memory_reader_state.buffer = &#40;unsigned char *&#41;buffer;
	memory_reader_state.bufsize = bufsize;
	memory_reader_state.current_pos = 0;

	png_set_read_fn&#40;png_ptr, &memory_reader_state, &#40;png_rw_ptr&#41;read_data_memory&#41;;
	png_read_info&#40;png_ptr, info_ptr&#41;;
	png_get_IHDR&#40;png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL&#41;;

	image->imageWidth = width;
	image->imageHeight = height;
	image->textureWidth = getNextPower2&#40;width&#41;;
	image->textureHeight = getNextPower2&#40;height&#41;;

	png_set_sig_bytes&#40;png_ptr, sig_read&#41;;
	png_set_strip_16&#40;png_ptr&#41;;
	png_set_packing&#40;png_ptr&#41;;

	if &#40;color_type == PNG_COLOR_TYPE_PALETTE&#41; png_set_palette_to_rgb&#40;png_ptr&#41;;
	if &#40;color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8&#41; png_set_gray_1_2_4_to_8&#40;png_ptr&#41;;
	if &#40;png_get_valid&#40;png_ptr, info_ptr, PNG_INFO_tRNS&#41;&#41; png_set_tRNS_to_alpha&#40;png_ptr&#41;;
	png_set_filler&#40;png_ptr, 0xff, PNG_FILLER_AFTER&#41;;

	image->data = &#40;Color*&#41; memalign&#40;16, image->textureWidth * image->textureHeight * sizeof&#40;Color&#41;&#41;;
	if &#40;!image->data&#41; &#123;
		free&#40;image&#41;;
		png_destroy_read_struct&#40;&png_ptr, png_infopp_NULL, png_infopp_NULL&#41;;
		return NULL;
	&#125;
	line = &#40;u32*&#41; malloc&#40;width * 4&#41;;
	if &#40;!line&#41; &#123;
		free&#40;image->data&#41;;
		free&#40;image&#41;;
		png_destroy_read_struct&#40;&png_ptr, png_infopp_NULL, png_infopp_NULL&#41;;
		return NULL;
	&#125;
	for &#40;y = 0; y < height; y++&#41; &#123;
		png_read_row&#40;png_ptr, &#40;u8*&#41; line, png_bytep_NULL&#41;;
		for &#40;x = 0; x < width; x++&#41; &#123;
			u32 color = line&#91;x&#93;;
			image->data&#91;x + y * image->textureWidth&#93; =  color;
		&#125;
	&#125;

	free&#40;line&#41;;
	png_read_end&#40;png_ptr, info_ptr&#41;;
	png_destroy_read_struct&#40;&png_ptr, &info_ptr, png_infopp_NULL&#41;;

	return image;
&#125;
While I'm at it.. has anyone seen the above example, and knows what is wrong with it?
Cheers, Art.
Insert_witty_name
Posts: 376
Joined: Wed May 10, 2006 11:31 pm

Post by Insert_witty_name »

Looks like the function from the lastest Lua Player's graphics.cpp.

If it's not then check it out ^^^
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Art wrote:While I'm at it.. has anyone seen the above example, and knows what is wrong with it?
Yes, I have seen this code, because I wrote it. You need the Image struct from graphics.h in order to compile it.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

What is an image structure?
Does that function get placed in graphics.h?
Insert_witty_name
Posts: 376
Joined: Wed May 10, 2006 11:31 pm

Post by Insert_witty_name »

Download the Lua Player source from SVN or http://www.luaplayer.org

The graphics.cpp and graphics.h are included.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Art wrote:What is an image structure?
Does that function get placed in graphics.h?
"struct": http://www.google.com/search?q=c+struct
"Image": see graphics.h
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Code: Select all

typedef struct
&#123;
	int textureWidth;  // the real width of data, 2^n with n>=0
	int textureHeight;  // the real height of data, 2^n with n>=0
	int imageWidth;  // the image width
	int imageHeight;
	Color* data;
&#125; Image;
If I include this into my working program, it breaks it
(I think because it's already declared in graphics.h),
and if I include the whole function above into graphics.h, it doesn't compile either. Would it matter that my SDk install is old?

I'd really like to get either this, or fontlib working so I can get graphic
fonts in programs without myself, or it's users having to copy the 44 character png files to MS.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Art wrote: If I include this into my working program, it breaks it
(I think because it's already declared in graphics.h),
and if I include the whole function above into graphics.h, it doesn't compile either.
My crystal ball is a bit dull these days. What do you mean with "break" and "doesn't compile" (compiler message)? But please consider that this is no C learning forum before you answer. Maybe you should buy some book like "learning C in 21 days" or something like this.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Well I did read the page you linked to, and yes it is rather obvious definition.

I mean If I just include this:

Code: Select all

typedef struct 
&#123; 
   int textureWidth;  // the real width of data, 2^n with n>=0 
   int textureHeight;  // the real height of data, 2^n with n>=0 
   int imageWidth;  // the image width 
   int imageHeight; 
   Color* data; 
&#125; Image; 
Without touching anything else, my program that previously compiled,
now comes up with many errors. One of the first is
graphics.h:23: error: previous declaration of 'Image' was here
Which lead me to believe your function belongs in graphics.h.
There is also a complaint about every occurance of blitImageToScreen as well.

And If I put your function posted above in either main.c or graphics.h
without touching anything else, there are errors as well.

There's no need for programming books, once I get a graphic font working one
way or another (preferably this way, I'll be fine).
I think even the source of a HB game that uses it would do as an example.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Art wrote: Without touching anything else, my program that previously compiled,
now comes up with many errors. One of the first is
graphics.h:23: error: previous declaration of 'Image' was here
The text after "was here" could be important. The compiler has already parsed the Image structure. Maybe you included it from another file as well? Usually in C you write something like this in header files to avoid this problem:
#ifndef GRAPHICS_H
#define GRAPHICS_H
...
#endif
Art wrote: And If I put your function posted above in either main.c or graphics.h
without touching anything else, there are errors as well.
Usually in C you don't put a function in a header file, but the declaration, only. So if you use the original graphics.h and graphics.cpp from Lua Player and if you include just the graphics.h in your main.c (which you need to convert to main.cpp, or you should fix all errors when compiling graphics.cpp as graphics.c), then it should work. Don't forget to add graphics.cpp and main.cpp both to your Makefile.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

Thanks, I'll give it a go.
Shine
Posts: 728
Joined: Fri Dec 03, 2004 12:10 pm
Location: Germany

Post by Shine »

Art wrote: I think even the source of a HB game that uses it would do as an example.
This is a good idea. You could use Lua Player 0.16 from http://www.luaplayer.org/old/index.html (this is the last version without module support, so building and deploying is easier and it should work on firmware >1.5 with loaders). Then delete anything you don't need (but maybe you want script support, too, in your program) and add your code. The licence is BSD, which means that you can do whatever you want with the source, as long as you keep the copyright notice.
Art
Posts: 642
Joined: Wed Nov 09, 2005 8:01 am

Post by Art »

I got this sorted with a bare minimum program required to display one image to the screen, thanks to a fellow called will1234.

http://www.megaupload.com/?d=OMJT4D5N

I think it's a template for a PSP comic book.
Cheers,
Art.
Post Reply