How do I load a texture from an image file (other than RAW, and preferably PNG).
Could someone give me a complete (or at least a few lines as to how to do this?
Any help is greatly apreciated.
Loading textures from PNG (or other image formats)
-
- Posts: 197
- Joined: Fri Jul 01, 2005 2:50 am
May your wish be granted:
Note that this function pads to power of 2, so if your texture is 200x100, the texture ends up 256x128.
Code: Select all
static unsigned int vramaddr = 0;
unsigned char *loadPNGfromfile(const char *filename,int widp, int heip, int swizzleit)
{
//this function loads into RAM, not VRAM
//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;
int wid, hei;
//wid = RoundUpPow2(widp);
//hei = RoundUpPow2(heip);
int maxWid, maxHei
//load the PNG
if ((fp = fopen(filename, "rb")) == NULL) return NULL;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return NULL;
}
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 NULL;
}
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);
wid = RoundUpPow2(width);
hei = RoundUpPow2(height);
//widp = 10;
//heip = 10;
maxWid = getMaxInt(wid,(int)width);
maxHei = getMaxInt(hei,(int)height);
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 (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
line = (u32*)memalign(16,RoundUpPow2(width) * 4);
if (!line) {
fclose(fp);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
return NULL;
}
int c;
x=0;
y=0;
//unsigned char *input = inptr;
unsigned char __attribute__((aligned(16))) *output;
unsigned char __attribute__((aligned(16))) *outptr;
//unsigned char *output2, *outptr2;
size_t sizediff;
sizediff = maxWid*maxHei*4;
//if (ramaddr == 0)
//ramaddr = (unsigned int)malloc(sizediff);//(0x40000000 | 0x04000000) + VRAM_OFFSET;
c=0;
ramaddr = (unsigned int)memalign(16,sizediff);
outptr = output = (unsigned char *)ramaddr;
outptr = output;
for (y=0;y<maxHei;y++) {
if(y < height){
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);//}else{
//line = NULL;}
for (x=0;x<maxWid;x++){
int r = 0xff;
int g = 0xff;
int b = 0xff;
int a = 0x00;
//if(x < maxWid-width || y < maxHei-height){a = 0x00;}
if(x <= width && y <= height){
u32 color32 = line[x];
r = color32 & 0xff;
g = (color32 >> 8) & 0xff;
b = (color32 >> 16) & 0xff;
a = (color32 >> 24) & 0xff;
}
outptr[(int)((x*4)+(y*maxWid*4))] = r;
outptr[(int)((x*4)+(y*maxWid*4)+1)] = g;
outptr[(int)((x*4)+(y*maxWid*4)+2)] = b;
outptr[(int)((x*4)+(y*maxWid*4)+3)] = a;
}
}else{for (x=0;x<maxWid;x++){outptr[(int)((x*4)+(y*maxWid*4)+3)] = 0;}}
}
fclose(fp);
if(swizzleit == 0){
return output;
}else{
//return output;
unsigned char __attribute__((aligned(16)))*swizzled;
swizzled = (unsigned char*)memalign(16,maxWid*maxHei*4);
swizzle(swizzled,output,maxWid,maxHei);
//free old texture
free(output);
return swizzled;
}
}
//swizzles the texture (only use with static textures, else too slow)
void swizzle(u8* out, const u8* in, unsigned int width, unsigned int height)
{
//note this function is modified to take into account that 1 pixel (32bit) is
//actually 4 u8, so if you don't want this, change width*4 to width
unsigned int i,j;
unsigned int rowblocks = ((width*4) / 16);
for (j = 0; j < height; ++j)
{
for (i = 0; i < (width*4); ++i)
{
unsigned int blockx = i / 16;
unsigned int blocky = j / 8;
unsigned int x = (i - blockx*16);
unsigned int y = (j - blocky*8);
unsigned int block_index = blockx + ((blocky) * rowblocks);
unsigned int block_address = block_index * 16 * 8;
out[block_address + x + y * 16] = in[i+j*(width*4)];
}
}
}
-
- Posts: 35
- Joined: Mon Aug 22, 2005 7:48 am