TexturePtr SpriteManager::getSpriteTexture(int id) { if(id == 0) return g_graphics.getEmptyTexture(); assert(id > 0 && id <= m_spritesCount); // load sprites on demand TexturePtr& sprite = m_sprites[id-1]; if(!sprite) sprite = loadSpriteTexture(id); //TODO: release unused sprites textures after X seconds // to avoid massive texture allocations return sprite; }
bool loadSpriteFromPNG (const char * file, struct spriteBank *sprites, int index) { if (sprites->type<2) { char * error = joinStrings(file, "\n\nPNG files currently not supported in palette mode. Change to 32-bit mode and try again."); errorBox ("Can't open PNG file", error); delete error; return false; } // Open the file FILE * fp = fopen (file, "rb"); if (fp == NULL) { char * error = joinStrings(file, "\n\nThe file can't be opened. I don't know why."); errorBox ("Can't open PNG file", error); delete error; return false; } char tmp[10]; size_t bytes_read = fread(tmp, 1, 8, fp); if (bytes_read != 8 && ferror (fp)) { fprintf(stderr, "Reading error in loadSpriteFromPNG.\n"); } if (png_sig_cmp((png_byte *) tmp, 0, 8)) { fclose (fp); char * error = joinStrings(file, "\n\nIt doesn't appear to be a valid PNG image."); errorBox ("Can't open PNG file", error); delete error; return false; } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose (fp); char * error = joinStrings(file, "\n\nError reading the file."); errorBox ("Can't open PNG file", error); delete error; return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); fclose (fp); char * error = joinStrings(file, "\n\nError reading the file."); errorBox ("Can't open PNG file", error); delete error; return false; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose (fp); char * error = joinStrings(file, "\n\nError readin the file"); return errorBox ("Can't open PNG file", error); } png_init_io(png_ptr, fp); // Tell libpng which file to read png_set_sig_bytes(png_ptr, 8); // 8 bytes already read png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); if (bit_depth < 8) png_set_packing(png_ptr); png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); int rowbytes = png_get_rowbytes(png_ptr, info_ptr); unsigned char * row_pointers[height]; unsigned char * data = new unsigned char [rowbytes*height]; for (int i = 0; i<height; i++) row_pointers[i] = data + i*rowbytes; png_read_image(png_ptr, (png_byte **) row_pointers); png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose (fp); if (sprites->sprites[index].data) delete sprites->sprites[index].data; sprites->sprites[index].data = data; sprites->sprites[index].width = width; sprites->sprites[index].height = height; int n, r, g, b; for (int x=0; x<width;x++) { for (int y=0; y<height; y++) { if (! sprites->sprites[index].data[4*width*y + x*4 + 3]) { n = r = g = b = 0; if (x>0 && sprites->sprites[index].data[4*width*y + (x-1)*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*y + (x-1)*4]; g+= sprites->sprites[index].data[4*width*y + (x-1)*4+1]; b+= sprites->sprites[index].data[4*width*y + (x-1)*4+2]; } if (x<width-1 && sprites->sprites[index].data[4*width*y + (x+1)*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*y + (x+1)*4]; g+= sprites->sprites[index].data[4*width*y + (x+1)*4+1]; b+= sprites->sprites[index].data[4*width*y + (x+1)*4+2]; } if (y>0 && sprites->sprites[index].data[4*width*(y-1) + x*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*(y-1) + x*4]; g+= sprites->sprites[index].data[4*width*(y-1) + x*4+1]; b+= sprites->sprites[index].data[4*width*(y-1) + x*4+2]; } if (y<height-1 && sprites->sprites[index].data[4*width*(y+1) + x*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*(y+1) + x*4]; g+= sprites->sprites[index].data[4*width*(y+1) + x*4+1]; b+= sprites->sprites[index].data[4*width*(y+1) + x*4+2]; } if (n) { r /= n; g /= n; b /= n; sprites->sprites[index].data[4*width*y + x*4]=r; sprites->sprites[index].data[4*width*y + x*4+1]=g; sprites->sprites[index].data[4*width*y + x*4+2]=b; } } } } loadSpriteTexture (sprites, index); return true; }
bool loadSpriteFromTGA (const char * file, struct spriteBank *sprites, int index) { palCol thePalette[256]; // Open the file FILE * fp = fopen (file, "rb"); if (fp == NULL) { char * error = joinStrings(file, "\n\nThe file can't be opened. I don't know why."); errorBox ("Can't open TGA file", error); delete error; return false; } // Grab the header TGAHeader imageHeader; const char * errorBack; errorBack = readTGAHeader (imageHeader, fp, thePalette); if (errorBack) { fclose (fp); char * error = joinStrings(file, "\n\n", errorBack); errorBox ("Can't open TGA file", error); delete error; return false; } unsigned char *data; if (sprites->type < 2) { data = new unsigned char[imageHeader.height * imageHeader.width]; if (! data) { fclose (fp); errorBox ("Can't create sprite", "Out of memory."); return false; } unsigned char palSize = sprites->myPalette.total; unsigned char r,g,b; int c; for (int t2 = imageHeader.height-1; t2>=0; t2 --) { for (int t1 = 0; t1 < imageHeader.width; t1 ++) { if (! imageHeader.compressed) { grabRGB (fp, imageHeader.pixelDepth, r, g, b, thePalette); } else { grabRGBCompressed (fp, imageHeader.pixelDepth, r, g, b, thePalette); } if (sprites->type == 1) data[t2*imageHeader.width+t1] = findClosestPal (&sprites->myPalette, r, g, b); else { if ((c = findOrAddPal (&sprites->myPalette, r, g, b)) < 0) { fclose(fp); errorBox ("Can't create sprite", "The sprite bank palette doesn't have enough room left to add the colours. Change the palette mode to locked or 32-bit and try again."); sprites->myPalette.total = palSize; delete data; return false; } data[t2*imageHeader.width+t1] = c; } } } } else { data = new unsigned char[imageHeader.height * imageHeader.width * 4]; if (! data) { fclose (fp); errorBox ("Can't create sprite", "Out of memory."); return false; } unsigned char r,g,b,a; fprintf (stderr, "Compressed: %d (%d)\n", imageHeader.compressed, imageHeader.pixelDepth); for (int t2 = imageHeader.height-1; t2>=0; t2 --) { for (int t1 = 0; t1 < imageHeader.width; t1 ++) { if (! imageHeader.compressed) { grabRGBA (fp, imageHeader.pixelDepth, r, g, b, a, thePalette); } else { grabRGBACompressed (fp, imageHeader.pixelDepth, r, g, b, a, thePalette); } data[t2*imageHeader.width*4+t1*4] = r; data[t2*imageHeader.width*4+t1*4+1] = g; data[t2*imageHeader.width*4+t1*4+2] = b; data[t2*imageHeader.width*4+t1*4+3] = a; } } } fclose (fp); if (sprites->sprites[index].data) delete sprites->sprites[index].data; sprites->sprites[index].data = data; sprites->sprites[index].width = imageHeader.width; sprites->sprites[index].height = imageHeader.height; if (sprites->type>=2) { int n, r, g, b; int width = imageHeader.width; int height = imageHeader.height; for (int x=0; x<width;x++) { for (int y=0; y<height; y++) { if (! sprites->sprites[index].data[4*width*y + x*4 + 3]) { n = r = g = b = 0; if (x>0 && sprites->sprites[index].data[4*width*y + (x-1)*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*y + (x-1)*4]; g+= sprites->sprites[index].data[4*width*y + (x-1)*4+1]; b+= sprites->sprites[index].data[4*width*y + (x-1)*4+2]; } if (x<width-1 && sprites->sprites[index].data[4*width*y + (x+1)*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*y + (x+1)*4]; g+= sprites->sprites[index].data[4*width*y + (x+1)*4+1]; b+= sprites->sprites[index].data[4*width*y + (x+1)*4+2]; } if (y>0 && sprites->sprites[index].data[4*width*(y-1) + x*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*(y-1) + x*4]; g+= sprites->sprites[index].data[4*width*(y-1) + x*4+1]; b+= sprites->sprites[index].data[4*width*(y-1) + x*4+2]; } if (y<height-1 && sprites->sprites[index].data[4*width*(y+1) + x*4 + 3]) { n++; r+= sprites->sprites[index].data[4*width*(y+1) + x*4]; g+= sprites->sprites[index].data[4*width*(y+1) + x*4+1]; b+= sprites->sprites[index].data[4*width*(y+1) + x*4+2]; } if (n) { r /= n; g /= n; b /= n; sprites->sprites[index].data[4*width*y + x*4]=r; sprites->sprites[index].data[4*width*y + x*4+1]=g; sprites->sprites[index].data[4*width*y + x*4+2]=b; } } } } } loadSpriteTexture (sprites, index); return true; }