Faster PNG loader

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

Moderators: cheriff, TyRaNiD

Post Reply
elevationsnow
Posts: 22
Joined: Sat Sep 10, 2005 6:45 am

Faster PNG loader

Post by elevationsnow »

is there any faster png loader than:

Code: Select all

void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
{
        // ignore PNG warnings
}
void loadImage(const char* filename,int xx,int yy)
{
        u32* vram32;
        u16* vram16;
        int bufferwidth;
        int pixelformat;
        int unknown;
        png_structp png_ptr;
        png_infop info_ptr;
        unsigned int sig_read = 0;
        png_uint_32 width, height;
        int bit_depth, color_type, interlace_type, x, y;
        u32* line;
        FILE *fp;

        if ((fp = fopen(filename, "rb")) == NULL) return;
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if (png_ptr == NULL) {
                fclose(fp);
                return;
        }
        png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn);
        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL) {
                fclose(fp);
                png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
                return;
        }
        png_init_io(png_ptr, fp);
        png_set_sig_bytes(png_ptr, sig_read);
        png_read_info(png_ptr, info_ptr);
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
        png_set_strip_16(png_ptr);
        png_set_packing(png_ptr);
        if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
        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;;
        line = &#40;u32*&#41; malloc&#40;width * 4&#41;;
        if &#40;!line&#41; &#123;
                fclose&#40;fp&#41;;
                png_destroy_read_struct&#40;&png_ptr, png_infopp_NULL, png_infopp_NULL&#41;;
                return;
        &#125;
        sceDisplayWaitVblankStart&#40;&#41;;  // if framebuf was set with PSP_DISPLAY_SETBUF_NEXTFRAME, wait until it is changed
        sceDisplayGetFrameBuf&#40;&#40;void**&#41;&vram32, &bufferwidth, &pixelformat, &unknown&#41;;
        vram16 = &#40;u16*&#41; vram32;
        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 color32 = line&#91;x&#93;;
                        u16 color16;
                        int r = color32 & 0xff;
                        int g = &#40;color32 >> 8&#41; & 0xff;
                        int b = &#40;color32 >> 16&#41; & 0xff;
                        switch &#40;pixelformat&#41; &#123;
                                case PSP_DISPLAY_PIXEL_FORMAT_565&#58;
                                        color16 = &#40;r >> 3&#41; | &#40;&#40;g >> 2&#41; << 5&#41; | &#40;&#40;b >> 3&#41; << 11&#41;;
                                        PlotPixel&#40;x+xx,y+yy,r,g,b&#41;;
                                        break;
                                case PSP_DISPLAY_PIXEL_FORMAT_5551&#58;
                                        color16 = &#40;r >> 3&#41; | &#40;&#40;g >> 3&#41; << 5&#41; | &#40;&#40;b >> 3&#41; << 10&#41;;
                                        PlotPixel&#40;x+xx,y+yy,r,g,b&#41;;
                                        break;
                                case PSP_DISPLAY_PIXEL_FORMAT_4444&#58;
                                        color16 = &#40;r >> 4&#41; | &#40;&#40;g >> 4&#41; << 4&#41; | &#40;&#40;b >> 4&#41; << 8&#41;;
                                        PlotPixel&#40;x+xx,y+yy,r,g,b&#41;;
                                        break;
                                case PSP_DISPLAY_PIXEL_FORMAT_8888&#58;
                                        color32 = r | &#40;g << 8&#41; | &#40;b << 16&#41;;
                                        PlotPixel&#40;x+xx,y+yy,r,g,b&#41;;
                                        break;
                        &#125;
                &#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;;
        fclose&#40;fp&#41;;
&#125;
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Yes, get the switch() outside the for loops (write it out longhand), and don't use PlotPixel, try to poke the addresses directly - as you go across the scanline the address simply increment.
Having said that, check first that it's not the memory stick bandwidth that's the limiting factor.

Jim
Post Reply