/*************************************************************************** texture.cpp ---------------------------------------------------------------------------- begin : june 2003 copyright : (C) 2003 by Pierre Alliez - INRIA email : pierre.alliez@sophia.inria.fr ***************************************************************************/ #include "stdafx.h" #include #include #include "texture.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Constructor CTexture::CTexture() { m_pData = NULL; m_Width = 0; m_WidthByte32 = 0; m_Height = 0; m_Depth = 0; m_pFileName = new char[MAX_PATH]; strcpy(m_pFileName,""); } // Destructor CTexture::~CTexture() { Free(); delete [] m_pFileName; } // Alloc int CTexture::Alloc(unsigned int width, unsigned int height, unsigned int depth) { Free(); unsigned int Width32 = WidthByte32(width,depth); m_pData = new unsigned char [Width32 * height]; if(m_pData == NULL) { TRACE("CTexture::Alloc : Insufficiant memory\n"); return 0; } // Set members variables m_Width = width; m_WidthByte32 = Width32; m_Height = height; m_Depth = depth; UpdateHeader(); return 1; } // Free void CTexture::Free() { if(m_pData != NULL) { delete [] m_pData; m_pData = NULL; } m_Width = 0; m_Height = 0; m_Depth = 0; } // ReadFile (dispatch function) int CTexture::ReadFile(char *filename, unsigned int width, unsigned int height, unsigned int depth) { // Cleanup Free(); // Storage strcpy(m_pFileName,filename); // Extension TRACE("CTexture::ReadFile : file : %s\n",filename); int len = strlen(filename); char extension[10]; strcpy(extension,&(filename[len-4])); if(extension == ".bmp") return ReadFileBMP(filename); if(extension == ".raw") return ReadFileRAW(filename,width,height,depth); return 0; } // ReadFileBMP (*.bmp) // Read windows bmp files // Accept only 24 bits // Size : 2^n x 2^m int CTexture::ReadFileBMP(char *filename) { // Check for valid bmp file CFile file; CFileException ex; // Try to open file if(!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex)) { TRACE("Unable to open file for reading"); return 0; } // File header BITMAPFILEHEADER FileHeader; file.Read(&FileHeader,sizeof(BITMAPFILEHEADER)); TRACE("FileHeader.bfType : %d\n",FileHeader.bfType); TRACE("FileHeader.bfSize : %d\n",FileHeader.bfSize); TRACE("FileHeader.bfReserved1 : %d\n",FileHeader.bfReserved1); TRACE("FileHeader.bfReserved2 : %d\n",FileHeader.bfReserved2); TRACE("FileHeader.bfOffBits : %d\n",FileHeader.bfOffBits); // Is it a Windows BMP file ? (BM) WORD sign = ((WORD) ('M' << 8) | 'B'); if(FileHeader.bfType != sign) { TRACE("Invalid BMP file"); file.Close(); return 0; } file.Read(&m_Header,sizeof(BITMAPINFOHEADER)); TRACE("\n"); TRACE("IMAGE HEADER :\n"); TRACE("biSize : %d\n",m_Header.biSize); TRACE("biWidth : %d\n",m_Header.biWidth); TRACE("biHeight : %d\n",m_Header.biHeight); TRACE("biPlanes : %d\n",m_Header.biPlanes); TRACE("biBitCount : %d\n",m_Header.biBitCount); TRACE("biCompression : %d\n",m_Header.biCompression); TRACE("biSizeImage : %d\n",m_Header.biSizeImage); TRACE("biXPelsPerMeter : %d\n",m_Header.biXPelsPerMeter); TRACE("biYPelsPerMeter : %d\n",m_Header.biYPelsPerMeter); TRACE("biClrUsed : %d\n",m_Header.biClrUsed); TRACE("biClrImportant : %d\n",m_Header.biClrImportant); // 24 bits ? if(m_Header.biPlanes != 1 || m_Header.biBitCount != 24) { TRACE("Texture file must have 24 bits depth"); file.Close(); return 0; } // Alloc (does call Free before) Free(); m_pData = new unsigned char[m_Header.biSizeImage]; if(m_pData == NULL) { TRACE("Insufficiant memory"); file.Close(); return 0; } // Update datas m_Width = m_Header.biWidth; m_Height = m_Header.biHeight; m_Depth = m_Header.biBitCount; // Image reading file.Read(m_pData,m_Header.biSizeImage); // Close file file.Close(); UpdateWidthByte32(); return 1; } // UpdateWidthByte32 void CTexture::UpdateWidthByte32() { m_WidthByte32 = WidthByte32(m_Width,m_Depth); } // WidthByte32 unsigned int CTexture::WidthByte32(unsigned int width, unsigned int depth) { // 32 bits alignment (4 bytes) int rest=(width*depth/8)%4; if(rest != 0) return (width*depth/8 + 4-rest); else return (width*depth/8); } // UpdateHeader void CTexture::UpdateHeader() { UpdateWidthByte32(); m_Header.biWidth = m_Width; m_Header.biHeight = m_Height; m_Header.biSizeImage = m_WidthByte32 * m_Height; m_Header.biSize = 40; m_Header.biPlanes = 1; m_Header.biBitCount = m_Depth; m_Header.biCompression = (WORD)0; m_Header.biXPelsPerMeter = 0; m_Header.biYPelsPerMeter = 0; m_Header.biClrUsed = 0; m_Header.biClrImportant = 0; } // ReadFileRAW (*.raw) // Read raw files // Accept only 24 or 32 bits // Size : 2^n x 2^m int CTexture::ReadFileRAW(char *filename, unsigned int width, unsigned int height, unsigned int depth) { // Check for valid file FILE *fp = fopen(filename,"rb"); // Try to open file if(!fp) { TRACE("Unable to open file for reading"); return 0; } // Alloc (does call Free before) if(!Alloc(width,height,depth)) { TRACE("Insufficiant memory"); fclose(fp); return 0; } fread(m_pData,sizeof(unsigned char),m_Width*m_Height*depth/8,fp); // Close file fclose(fp); // Success, also set FileName strcpy(m_pFileName,filename); return 1; } // SaveFile (dispatch function) int CTexture::SaveFile(char *filename) { TRACE("CTexture::SaveFile : file : %s\n",filename); int len = strlen(filename); char extension[10]; strcpy(extension,&(filename[len-4])); if(extension == ".raw") return SaveFileRAW(filename); if(extension == ".bmp") return SaveFileBMP(filename); return 0; } // SaveFileRAW int CTexture::SaveFileRAW(char *filename) { // Check for valid image if((m_Width * m_Height * m_Depth) == 0) { TRACE("CTexture::SaveFileRAW : invalid image"); return 0; } // Check for valid file FILE *fp = fopen(filename,"wb"); // Try to open file if(!fp) { TRACE("Unable to open file for writing"); return 0; } // Image writing fwrite(m_pData,sizeof(unsigned char),m_Width*m_Height*m_Depth/8,fp); // Close file fclose(fp); return 1; } // SaveFileBMP (*.bmp) // Save windows bmp files // Accept only 24 bits int CTexture::SaveFileBMP(char *filename) { if(!IsValid()) return 0; if(m_Depth != 24) return 0; // Check for valid bmp file CFile file; CFileException ex; // Try to open file if(!file.Open(filename,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary,&ex)) { TRACE("Unable to open file for writing"); return 0; } // File header BITMAPFILEHEADER FileHeader; WORD sign = ((WORD) ('M' << 8) | 'B'); FileHeader.bfType = sign; FileHeader.bfSize = 14 + 40 + m_WidthByte32*m_Height; FileHeader.bfReserved1 = 0; FileHeader.bfReserved2 = 0; FileHeader.bfOffBits = 54; TRACE("\nSave BMP File...\n"); TRACE("FileHeader.bfType : %d\n",FileHeader.bfType); TRACE("FileHeader.bfSize : %d\n",FileHeader.bfSize); TRACE("FileHeader.bfReserved1 : %d\n",FileHeader.bfReserved1); TRACE("FileHeader.bfReserved2 : %d\n",FileHeader.bfReserved2); TRACE("FileHeader.bfOffBits : %d\n",FileHeader.bfOffBits); file.Write(&FileHeader,sizeof(BITMAPFILEHEADER)); file.Write(&m_Header,sizeof(BITMAPINFOHEADER)); // DEBUG TRACE("\n"); TRACE("IMAGE HEADER :\n"); TRACE("biSize : %d\n",m_Header.biSize); TRACE("biWidth : %d\n",m_Header.biWidth); TRACE("biHeight : %d\n",m_Header.biHeight); TRACE("biPlanes : %d\n",m_Header.biPlanes); TRACE("biBitCount : %d\n",m_Header.biBitCount); TRACE("biCompression : %d\n",m_Header.biCompression); TRACE("biSizeImage : %d\n",m_Header.biSizeImage); TRACE("biXPelsPerMeter : %d\n",m_Header.biXPelsPerMeter); TRACE("biYPelsPerMeter : %d\n",m_Header.biYPelsPerMeter); TRACE("biClrUsed : %d\n",m_Header.biClrUsed); TRACE("biClrImportant : %d\n",m_Header.biClrImportant); // Image writing file.Write(m_pData,m_Header.biSizeImage); // Close file file.Close(); return 1; } // IsValid int CTexture::IsValid() { int success = 0; success = (m_Depth == 24) || (m_Depth == 32); success &= (m_Width != 0); success &= (m_Height != 0); success &= (m_pData != NULL); if(!success) { TRACE("\n"); TRACE("Invalid texture\n"); TRACE("Width : %d\n",m_Width); TRACE("Height : %d\n",m_Height); TRACE("Depth : %d\n",m_Depth); TRACE("Data : %x\n",m_pData); } return success; } // HigherPowerOfTwo int CTexture::HigherPowerOfTwo(int value) { if(value <= 0) return value; int power = 1; int x = 0; while(1) { x = (int)pow(2,power); if(x >= value) return x; power++; } } // LowerPowerOfTwo int CTexture::LowerPowerOfTwo(int value) { if(value <= 0) return value; int power = 1; int x = 0; while(1) { x = (int)pow(2,power); if(x >= value) return (int)pow(2,power-1); power++; } } // SameSize int CTexture::SameSize(CTexture *pTexture) { int success = (m_Width == pTexture->GetWidth()); success &= (m_Height == pTexture->GetHeight()); return success; } // Flip BGR to RGB int CTexture::BGRtoRGB() { if(!IsValid()) return 0; unsigned char pixel; int BytePerPixel = m_Depth/8; for(unsigned int j=0;j= right || top >= bottom) return 0; if(left < 0 || left >= (int)m_Width || right < 0 || right >= (int)m_Width) return 0; if(top < 0 || top >= (int)m_Height || bottom < 0 || bottom >= (int)m_Height) return 0; int NewWidth = right-left+1; int NewWidthByte32 = WidthByte32(NewWidth,m_Depth); int NewHeight = bottom-top+1; int BytePerPixel = m_Depth / 8; int i,j,k; TRACE("Start extracting...\n"); TRACE("New width : %d\n",NewWidth); TRACE("New height : %d\n",NewHeight); // Alloc unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; if(pData == NULL) { TRACE("Insufficiant memory"); return 0; } for(j=0;jIsValid()) return 0; if(!SameSize(pTexture)) return 0; if(!AddAlphaLayer(0)) return 0; // Fill new data unsigned char *pData = pTexture->GetData(); int size = m_Width * m_Height; int BytePerPixel = pTexture->GetDepth() / 8; for(int i=0;im_hDC, xOffset, yOffset, width, height, 0, 0, 0, m_Height, GetData(), (CONST BITMAPINFO *)&m_Header, DIB_RGB_COLORS); } // Stretch int CTexture::Stretch(CDC *pDC, CRect *pRect) { // Checking if(!IsValid()) return 0; SetStretchBltMode(pDC->m_hDC,COLORONCOLOR); // Painting return StretchDIBits(pDC->m_hDC, pRect->left, pRect->top, pRect->Width(), pRect->Height(), 0, 0, m_Width, m_Height, GetData(), (CONST BITMAPINFO *)&m_Header, DIB_RGB_COLORS,SRCCOPY); } // ReadBuffer int CTexture::ReadBuffer(unsigned char *buffer, int width, int height, int depth) { if(buffer == NULL) return 0; if(!Alloc(width,height,depth)) return 0; int BytePerPixel = depth / 8; for(int j=0;jGetData(); if(pBuffer == NULL) return; unsigned int width = pTexture->GetWidth(); unsigned int height = pTexture->GetHeight(); unsigned int depth = pTexture->GetDepth(); if(!Alloc(width,height,depth)) return; unsigned int BytePerPixel = depth / 8; for(unsigned int j=0;j