CFreeList* CMemory::GetOrAddFreeList(unsigned int iElementSize, int iAlignment, int iOffset) { SFreeListDesc sDesc; BOOL bResult; int iIndex; SFreeListDesc* psDesc; CFreeList* pcList; SMemoryFreeListParams* psParams; int iFinalOffset; int iStride; iFinalOffset = CalculateOffset(iOffset - sizeof(SMemoryAllocation), iAlignment); psParams = GetFreeListParamsForSize(iElementSize); iStride = CalculateStride(psParams->iMaxElementSize, iAlignment); sDesc.Init(iStride, iAlignment, iOffset); bResult = mcOrder.FindInSorted(&sDesc, CompareFreeListDesc, &iIndex); if (bResult) { psDesc = mcOrder.Get(iIndex); return psDesc->pcFreeList; } else { pcList = mcFreeLists.InsertAfterTail(); pcList->Init(psParams->iChunkSize, psParams->iMaxListSize, iAlignment); sDesc.pcFreeList = pcList; mcOrder.InsertAt(&sDesc, iIndex); return pcList; } }
//Convert a paletted image into a non-paletted one void IMAGE::ExpandPalette(void) { //Do not expand non-paletted images, or those with no data if(!paletted || !data) return; //Calculate the stride of the expanded image unsigned int newStride=CalculateStride(paletteBpp); //Create space for the expanded image data GLubyte * newData=new GLubyte[newStride*height]; if(!newData) { printf("Unable to create memory for expanded data\n"); return; } //Loop through and fill in the unpaletted data for(unsigned int row=0; row<height; ++row) { for(unsigned int i=0; i<width; ++i) { unsigned int currentOldPixel=(row*stride)+i; unsigned int currentNewPixel=(row*newStride)+i*(paletteBpp/8); GLubyte currentPaletteEntry=data[((row*stride)+i)]; for(unsigned int j=0; j<paletteBpp/8; ++j) { newData[currentNewPixel+j]= palette[currentPaletteEntry*(paletteBpp/8)+j]; } } } //Update class member variables paletted=false; bpp=paletteBpp; format=paletteFormat; stride=newStride; if(data) delete [] data; data=newData; }
/** Flips the image rows and removes padding from the end. The BMP format stores the rows of pixels in the image in reverse order, so the topmost row is the last one in the file. This function reverses the order and removes padding from the end. @param[in,out] DestBuffer Pointer to the buffer containing the image data. @param[in] InfoHeader The bitmap info header. */ static void FlipRowsAndRemovePadding(std::vector<std::uint8_t>* DestBuffer, const BitmapInfoHeader& InfoHeader) { std::vector<std::uint8_t> reversed; size_t numRows = InfoHeader.Height; size_t rowLength = InfoHeader.Width * BYTES_PER_PIXEL; reversed.resize(numRows * rowLength); // Stride is needed to advance in the source buffer. size_t stride = CalculateStride(InfoHeader); std::uint8_t* dest = &reversed[0]; const std::uint8_t* src = DestBuffer->data() + (numRows - 1) * stride; for (size_t i = numRows; i > 0; i--) { std::memcpy(dest, src, rowLength); dest += rowLength; src -= stride; } DestBuffer->swap(reversed); }
/** Reads the pixel rows from the bitmap file. @param[in] FileStream The input file stream. @param[out] DestBuffer The buffer to write the pixels to. @param[in] FileHeader The bitmap file header. @param[in] InfoHeader The bitmap info header. @return One of #BitmapLoadStatus codes. */ static BitmapLoadStatus LoadPixels(std::ifstream& FileStream, std::vector<std::uint8_t>* DestBuffer, const BitmapFileHeader& FileHeader, const BitmapInfoHeader& InfoHeader) { FileStream.seekg(FileHeader.PixelArrayOffset); // Workaround for Paint.NET being stupid and generating broken images... if (InfoHeader.PixelDataSize != 0) { DestBuffer->resize(InfoHeader.PixelDataSize); } else { DestBuffer->resize(CalculateStride(InfoHeader) * InfoHeader.Height); } auto buffer = reinterpret_cast<char*>(&DestBuffer->at(0)); FileStream.read(buffer, InfoHeader.PixelDataSize); if (FileStream.gcount() != InfoHeader.PixelDataSize) { return UNEXPECTED_END_OF_FILE; } return LOAD_SUCCESS; }
CFreeList* CMemory::GetFreeList(unsigned int iElementSize, int iAlignment, int iOffset) { SFreeListDesc sDesc; BOOL bResult; int iIndex; SFreeListDesc* psDesc; SMemoryFreeListParams* psParams; int iStride; int iFinalOffset; iFinalOffset = CalculateOffset(iOffset - sizeof(SMemoryAllocation), iAlignment); psParams = GetFreeListParamsForSize(iElementSize); iStride = CalculateStride(psParams->iMaxElementSize, iAlignment); sDesc.Init(iStride, iAlignment, iOffset); bResult = mcOrder.FindInSorted(&sDesc, CompareFreeListDesc, &iIndex); if (bResult) { psDesc = mcOrder.Get(iIndex); return psDesc->pcFreeList; } return NULL; }
//Load an uncompressed true color TGA (24 or 32 bit) bool IMAGE::LoadUncompressedTrueColorTGA(char * filename) { unsigned char uncompTGAHeader[12]={0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char TGAcompare[12]; unsigned char header[6]; LOG::Instance()->OutputSuccess("Loading %s in LoadUncompressedTGA", filename); FILE * file=fopen(filename, "rb"); if(!file) { LOG::Instance()->OutputError("Unable to open %s", filename); return false; } //read the "compare" header fread(TGAcompare, 1, sizeof(TGAcompare), file); if(memcmp(uncompTGAHeader, TGAcompare, sizeof(uncompTGAHeader))!=0) { LOG::Instance()->OutputError("%s is not an uncompressed true color TGA", filename); return false; } //read in header fread(header, 1, sizeof(header), file); //Save data into class member variables width= header[1]*256+header[0]; height= header[3]*256+header[2]; bpp= header[4]; if(width<=0 || height<=0 || (bpp!=24 && bpp!=32)) { fclose(file); LOG::Instance()->OutputError( "%s's height or width is less than zero, or the TGA is not 24/32 bpp", filename); return false; } //Set format if(bpp==24) format=GL_RGB; if(bpp==32) format=GL_RGBA; //Calculate the stride in bytes for each row (allow for 4-byte padding) stride=CalculateStride(); //Allocate space for the image data data=new GLubyte[stride*height]; if(!data) { fclose(file); LOG::Instance()->OutputError( "Unable to allocate data for %s of size %d x %d", filename, stride, height); return false; } //read in the data a line at a time, and save it into the array, //hence making it 32-byte aligned for(unsigned int row=0; row<height; ++row) { fread(&data[row*stride], 1, width*(bpp/8), file); } fclose(file); //Data is in BGR format //swap b and r for(unsigned int row=0; row<height; ++row) { for(unsigned int i=0; i<width; ++i) { //Repeated XOR to swap bytes 0 and 2 data[(row*stride)+i*(bpp/8)] ^= data[(row*stride)+i*(bpp/8)+2] ^= data[(row*stride)+i*(bpp/8)] ^= data[(row*stride)+i*(bpp/8)+2]; } } LOG::Instance()->OutputSuccess("Loaded %s Correctly!", filename); return true; }
//Load a 24 bit .bmp file bool IMAGE::Load24BitBMP(char * filename) { printf("Loading %s in Load24BitBMP()\n", filename); FILE * file; BITMAPFILEHEADER fileHeader; BITMAPINFOHEADER infoHeader; //Open file for reading file=fopen(filename, "rb"); if(!file) { printf("Unable to open %s\n", filename); return false; } //read the file header fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file); //Check this is a bitmap if(fileHeader.bfType != bitmapID) { fclose(file); printf("%s is not a legal .bmp\n", filename); return false; } //Read in the information header fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file); if(infoHeader.biBitCount!=24) { fclose(file); printf("%s is not a 24 bit .bmp\n", filename); return false; } //Set class variables bpp=24; format=GL_RGB; width=infoHeader.biWidth; height=infoHeader.biHeight; //Calculate the stride in bytes for each row (allow for 4-byte padding) stride=CalculateStride(); //Point "file" to the beginning of the data fseek(file, fileHeader.bfOffBits, SEEK_SET); //Allocate space for the image data data=new GLubyte[stride*height]; if(!data) { fclose(file); printf( "Unable to allocate data for %s of size %d x %d\n", filename, stride, height); return false; } //read in the data fread(data, 1, stride*height, file); fclose(file); //Data is in BGR format //swap b and r for(unsigned int row=0; row<height; ++row) { for(unsigned int i=0; i<width; ++i) { //Repeated XOR to swap bytes 0 and 2 data[(row*stride)+i*3] ^= data[(row*stride)+i*3+2] ^= data[(row*stride)+i*3] ^= data[(row*stride)+i*3+2]; } } printf("Loaded %s Correctly!\n", filename); return true; }
//Load an 8 bit .bmp file bool IMAGE::Load8BitBMP(char * filename) { printf("Loading %s in Load8BitBMP()\n", filename); FILE * file; BITMAPFILEHEADER fileHeader; BITMAPINFOHEADER infoHeader; //Open file for reading file=fopen(filename, "rb"); if(!file) { printf("Unable to open %s\n", filename); return false; } //read the file header fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file); //Check this is a bitmap if(fileHeader.bfType != bitmapID) { fclose(file); printf("%s is not a legal .bmp\n", filename); return false; } //Read in the information header fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file); if(infoHeader.biBitCount!=8) { fclose(file); printf("%s is not an 8 bit .bmp\n", filename); return false; } //Set class variables bpp=8; format=GL_COLOR_INDEX; width=infoHeader.biWidth; height=infoHeader.biHeight; paletted=true; paletteBpp=24; paletteFormat=GL_RGB; //Calculate the stride in bytes for each row (allow for 4-byte padding) stride=CalculateStride(); //Create space for a temporary palette GLubyte * tempPalette=new GLubyte[256*4]; if(!tempPalette) { fclose(file); printf("Unable to allocate space for palette\n"); return false; } //Load the palette fread(tempPalette, 256*4, 1, file); //Create space for palette (disregard needless 4th entry) palette=new GLubyte[256*3]; if(!palette) { fclose(file); printf("Unable to allocate space for palette\n"); return false; } //Copy the palette entries from tempPalette to palette //swap bytes 0 and 2 to go from BGR to RGB for(int i=0; i<256; ++i) { palette[i*3+0]=tempPalette[i*4+2]; palette[i*3+1]=tempPalette[i*4+1]; palette[i*3+2]=tempPalette[i*4+0]; } //Clear "tempPalette" data if(tempPalette) delete [] tempPalette; tempPalette=NULL; //Point "file" to the beginning of the data fseek(file, fileHeader.bfOffBits, SEEK_SET); //Allocate space for the image data data=new GLubyte[stride*height]; if(!data) { fclose(file); printf( "Unable to allocate data for %s of size %d x %d\n", filename, stride, height); return false; } //read in the data fread(data, 1, stride*height, file); fclose(file); printf("Loaded %s Correctly!\n", filename); return true; }
//Load an uncompressed 8 Bit TGA (24 or 32 bit) bool IMAGE::LoadUncompressed8BitTGA(char * filename) { unsigned char uncomp8Bit24TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 24, 0, 0, 0, 0}; unsigned char uncomp8Bit32TGAHeader[12]={0, 1, 1, 0, 0, 0, 1, 32, 0, 0, 0, 0}; unsigned char TGAcompare[12]; unsigned char header[6]; printf("Loading %s in LoadUncompressed8BitTGA\n", filename); FILE * file=fopen(filename, "rb"); if(!file) { printf("Unable to open %s\n", filename); return false; } //read the "compare" header fread(TGAcompare, 1, sizeof(TGAcompare), file); if( memcmp(uncomp8Bit24TGAHeader, TGAcompare, sizeof(uncomp8Bit24TGAHeader))!=0 && memcmp(uncomp8Bit32TGAHeader, TGAcompare, sizeof(uncomp8Bit32TGAHeader))!=0) { printf("%s is not an uncompressed 8Bit TGA\n", filename); return false; } //read in header fread(header, 1, sizeof(header), file); //Save data into class member variables width= header[1]*256+header[0]; height= header[3]*256+header[2]; bpp= header[4]; if(width<=0 || height<=0 || bpp!=8) { fclose(file); printf("%s's height or width is less than zero, or the TGA is not 8 bpp\n", filename); return false; } paletted=true; paletteBpp=TGAcompare[7]; if(paletteBpp==24) paletteFormat=GL_RGB; if(paletteBpp==32) paletteFormat=GL_RGBA; //make space for palette palette=new GLubyte[256*paletteBpp/8]; if(!palette) { fclose(file); printf("unable to allocate memory for palette\n"); return false; } //load in the palette fread(palette, 256*paletteBpp/8, 1, file); //Palette is in BGR format //swap b and r for(int i=0; i<256; ++i) { //Repeated XOR to swap bytes 0 and 2 palette[i*(paletteBpp/8)] ^= palette[i*(paletteBpp/8)+2] ^= palette[i*(paletteBpp/8)] ^= palette[i*(paletteBpp/8)+2]; } //Set format format=GL_COLOR_INDEX; //Calculate the stride in bytes for each row (allow for 4-byte padding) stride=CalculateStride(); //Allocate space for the image data data=new GLubyte[stride*height]; if(!data) { fclose(file); printf( "Unable to allocate data for %s of size %d x %d\n", filename, stride, height); return false; } //read in the data a line at a time, and save it into the array, //hence making it 32-byte aligned for(unsigned int row=0; row<height; ++row) { fread(&data[row*stride], 1, width, file); } fclose(file); printf("Loaded %s Correctly!\n", filename); return true; }