void RenderTarget::getImageData(floatv &data) { IImage* img = driver->createImage(target, position2d<s32>(0,0), target->getSize()); uint y = img->getDimension().Height; uint x = img->getDimension().Width; for(uint i = 0; i < y; i++) { for(uint j = 0; j < x; j++) { SColor color = img->getPixel(j,i); data.push_back((float)(color.getRed()/255.0)); data.push_back((float)(color.getGreen()/255.0)); data.push_back((float)(color.getBlue()/255.0)); } } img->drop(); //delete img; }
IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) const { // Try to get the color palette from elsewhere (usually in a pak along with the WAL). // If this fails we use the DefaultPaletteQ2. static s32 * palette = 0; #if TRY_LOADING_PALETTE_FROM_FILE s32 loadedPalette[256]; #endif if (!palette) { #if TRY_LOADING_PALETTE_FROM_FILE IImage * paletteImage; // Look in a couple different places... paletteImage = createImageFromFile("pics/colormap.pcx"); if (!paletteImage) paletteImage = createImageFromFile("pics/colormap.tga"); if (!paletteImage) paletteImage = createImageFromFile("colormap.pcx"); if (!paletteImage) paletteImage = createImageFromFile("colormap.tga"); if (paletteImage && (paletteImage->getDimension().Width == 256) ) { palette = &loadedPalette; for (u32 i = 0; i < 256; ++i) { palette[i] = paletteImage->getPixel(i, 0).color; } } else { //FIXME: try reading a simple palette from "wal.pal" palette = DefaultPaletteQ2; } if (paletteImage) paletteImage->drop(); #endif } else { palette = DefaultPaletteQ2; } SWALHeader header; file->seek(0); if (file->read(&header, sizeof(SWALHeader)) != sizeof(SWALHeader) ) return 0; if (file->getSize() < header.MipmapOffset[0]) return 0; file->seek(header.MipmapOffset[0]); // read image const u32 imageSize = header.ImageHeight * header.ImageWidth; if (file->getSize() < (long)(imageSize + header.MipmapOffset[0])) return 0; u8* data = new u8[imageSize]; file->read(data, imageSize); IImage* image = 0; image = new CImage(ECF_A1R5G5B5, core::dimension2d<u32>(header.ImageWidth, header.ImageHeight)); // I wrote an 8 to 32 converter, but this works with released Irrlicht code. CColorConverter::convert8BitTo16Bit(data, (s16*)image->lock(), header.ImageWidth, header.ImageHeight, palette); image->unlock(); delete [] data; return image; }
bool CreatureSet::RegisterTextures(IVideoDriver* videoDriver, ResourceManager* resourceManager) { bool result = false; //STEP 1: Build an atlas index of all the images needed for textures from the backing file. LOGI("Initializing tile images from file %s", _resourceName.c_str()); ResourceBundle* spriteResourceBundle = resourceManager->GetResourceBundle( "Creatures"); //WARNING: Early returns here! I don't normally like this but the alternative is //huge if/else blocks. if (NULL == spriteResourceBundle) { LOGE("Could not find the 'Creatures' resource bundle in the resource manager."); return false; } if (NULL == videoDriver) { LOGE( "The video driver is null. Since this is needed for creating images this is unrecoverable."); return false; } //END WARNING IImage* image = videoDriver->createImageFromFile(spriteResourceBundle->Find( _resourceName)); int totalSpriteCountScope = 0; if (NULL == image) { LOGE("Unable to load image associated with map png file."); } else { LOGD("Image size is %d x %d", image->getDimension().Width, image->getDimension().Height); //Tiles are identified by an atlas index which tells the system which image in a tilesheet //numbered starting from 0 in the upper left corner and proceeding width first belongs //to a tile. map<int, IImage*> spriteAtlasImageIndexMap; int spritesPerRow = image->getDimension().Width / spriteWidth; int spritesPerColumn = image->getDimension().Height / spriteHeight; const int totalSpriteCount = spritesPerRow * spritesPerColumn; totalSpriteCountScope = totalSpriteCount; int atlasIndex = 0; position2d<s32> position(0, 0); //TODO: Round up to the nearest power of two per image dimension2d<u32> dimensions(64, 64); //Indices for the tilesheets increase breatdth first then depth. for (int y = 0; y < spritesPerColumn; y++) { for (int x = 0; x < spritesPerRow; x++) { IImage* imageTile = videoDriver->createImage(image->getColorFormat(), dimensions); imageTile->fill(image->getPixel(0, 0)); rect<s32> sourceRect(x * spriteWidth, y * spriteHeight, (x * spriteWidth) + spriteWidth, (y * spriteHeight) + spriteHeight); image->copyTo(imageTile, position, sourceRect); if (NULL != imageTile) { LOGD( "Image of sprite being associated with the atlasIndex %d is %d x %d", atlasIndex, imageTile->getDimension().Width, imageTile->getDimension().Height); spriteAtlasImageIndexMap.set(atlasIndex, imageTile); } else { LOGE("Unable to properly cut out a sprite at upper left (%d, %d)", sourceRect.UpperLeftCorner.X, sourceRect.UpperLeftCorner.Y); } atlasIndex++; } } LOGD("Dropping no longer needed image."); image->drop(); image = NULL; //STEP 2: Iterate over tiles in this set and fetch their image from the atlasIndexMap map<stringc, CreatureDefinition*>::Iterator spriteMapIterator = _creatures.getIterator(); while (!spriteMapIterator.atEnd()) { map<stringc, CreatureDefinition*>::Node* node = spriteMapIterator.getNode(); CreatureDefinition* creatureDefinition = node->getValue(); stringc textureName(_worldName); textureName.append("-"); textureName.append(creatureDefinition->GetName()); if (NULL == videoDriver->getTexture(textureName)) { LOGI( "Texture named %s is not registered with the driver. Registering.", textureName.c_str()); //TODO: This is holdover from the code for pulling in more than //one map tile for a specific type. Replace with specific handling //should animations become necessary. What follows is the //ORIGINAL comment from the HexTileSet texture builder. //Tiles can have a length greater than 0 which means //including the starting index x grab the next LENGTH tiles for (int i = 0; i < creatureDefinition->GetIndexLength(); i++) { int spriteAtlasIndex = creatureDefinition->GetAtlasIndex() + i; if (creatureDefinition->GetIndexLength() > 1) { char spriteIndex[5]; sprintf(spriteIndex, "%d", spriteAtlasIndex); stringc incrTextureName(_worldName); incrTextureName.append("-"); incrTextureName.append(creatureDefinition->GetName()); incrTextureName.append("-"); incrTextureName.append(spriteIndex); incrTextureName.trim(); textureName = incrTextureName; } map<int, IImage*>::Node* node = spriteAtlasImageIndexMap.find( spriteAtlasIndex); if (NULL != node) { IImage* textureResource = node->getValue(); if (NULL != textureResource) { LOGI("Started registering %s.", textureName.c_str()); ITexture* createdTexture = videoDriver->addTexture(textureName, textureResource); LOGI("Finished registering %s.", textureName.c_str()); } else { LOGE( "The image created for texture named %s is null or corrupted.", textureName.c_str()); } } } } spriteMapIterator++; } //STEP 3: Clean up //For all entries remaining in the map, delete the image as they were unused. map<int, IImage*>::Iterator mapIterator = spriteAtlasImageIndexMap.getIterator(); while (!mapIterator.atEnd()) { map<int, IImage*>::Node* node = mapIterator.getNode(); if (NULL != node && NULL != node->getValue()) { node->getValue()->drop(); } else { LOGE( "An entry in the temporary map is null or the image contained therein is null. This is a potential resource leak!"); } mapIterator++; } spriteAtlasImageIndexMap.clear(); LOGD("Sprite texture resource cleanup complete."); result = true; } return result; }