//******************************************** // Texture.cpp //******************************************** // class CTexture //******************************************** // pierre.alliez@cnet.francetelecom.fr // Created : 17/12/97 // Modified : 19/12/97 //******************************************** #include "stdafx.h" #include "math.h" #include "Texture.h" #include "gl/gl.h" #include "gl/glu.h" #include "LTGA.h" // Zyu add on 100722,支持64位 #include "ximage.h" //#include "planydec.h" //#include "plexcept.h" //#include "planybmp.h" //#include "pldibsect.h" //#include "plbmpenc.h" ////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////// //******************************************** // Constructor //******************************************** CTexture::CTexture() { m_pData = NULL; m_Width = 0; m_WidthByte32 = 0; m_Height = 0; m_Depth = 0; m_FileName = _T(""); } //******************************************** // Destructor //******************************************** CTexture::~CTexture() { Free(); } ////////////////////////////////////////////// // DATAS ////////////////////////////////////////////// //******************************************** // Alloc //******************************************** int CTexture::Alloc(unsigned int width, unsigned int height, unsigned int depth) { Free(); unsigned int BytePerPixel = (unsigned int)(depth / 8); unsigned int Width32 = WidthByte32(width,depth); // Only rgb and rgba modes ASSERT(BytePerPixel == 3 || BytePerPixel == 4); m_pData = new unsigned char [Width32 * height]; if (m_pData == NULL) { TRACE(_T("CTexture::Alloc : Insuffisant memory\n")); AfxMessageBox(_T("CTexture::Alloc : Insufisant memory")); 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; } ////////////////////////////////////////////// ////////////////////////////////////////////// // FILE READING ////////////////////////////////////////////// ////////////////////////////////////////////// //******************************************** // ReadFile // Redirection //******************************************** int CTexture::ReadFile(const TCHAR *filename, unsigned int width, unsigned int height, unsigned int depth) { // Cleanup Free(); // Storage m_FileName = filename; // Extension CString string = filename; string.MakeLower(); TRACE(_T("CTexture::ReadFile : file : %s\n"),filename); XPathParser parser(string); CString extension=(const TCHAR *)parser.m_sExt; //CString extension = string.Right(4); // Redirection BMP int nRet=FALSE; if (extension == _T(".bmp")) { nRet = ReadFileBMP(filename); } else if (extension == _T(".jpg")) { nRet = ReadFileJPG(filename); } else if (extension == _T(".gif")) { nRet =ReadFileGIF(filename); } else if (extension == _T(".raw")) { nRet = ReadFileRAW(filename,width,height,depth); } else { // Zyu modify on 100723,支持64位 /* PLAnyPicDecoder Decoder; //Decoder.SetTraceConfig (2, NULL); //_T("c:\paintlib.log")); PLWinBmp NewBmp; try { Decoder.MakeBmpFromFile (_AS(filename), &NewBmp); int iBytePixel=NewBmp.GetBitsPerPixel()/8; if (iBytePixel==3 || iBytePixel==4) { Free(); m_Width = NewBmp.GetWidth(); m_Height = NewBmp.GetHeight(); m_Depth=NewBmp.GetBitsPerPixel(); int nWidth32=WidthByte32(m_Width, m_Depth); ASSERT(nWidth32==NewBmp.GetBytesPerLine()); m_pData = new unsigned char[nWidth32*m_Height]; //unsigned char **pLineArray=NewBmp.GetLineArray(); //unsigned char *pLine=m_pData; //for(int i=m_Height-1; i>=0; i--,pLine+=nWidth32) { // memcpy(pLine, pLineArray[i], nWidth32); //} memcpy(m_pData, NewBmp.GetBits(), nWidth32*m_Height); UpdateHeader(); nRet = TRUE; } } catch (PLTextException e) { char sz[1024]; sprintf (sz, "Error decoding %s: %s", filename, (const char *)e); PLPicDecoder::Trace (1, sz); } catch (CMemoryException e) { TRACE (_T("Error decoding %s: Out of memory.\n"), filename); } */ Free(); nRet = (int)CTangentImage::ReadOtherPicFile(filename, m_Header, (char *&)m_pData); if (!nRet && extension == _T(".tga")) nRet = ReadFileTGA(filename); } // Storage again m_FileName = filename; // Unrecognized file format //CString message; //message.Format(_T("CTexture::ReadFile : invalid file redirection : %s\n"),filename); //AfxMessageBox(string); return nRet; } //******************************************** // ReadFileBMP (*.bmp) //******************************************** // Read windows bmp files // Accept only 24 bits // Size : 2^n x 2^m //******************************************** int CTexture::ReadFileBMP(const TCHAR *filename) { // Check for valid bmp file CFile file; CFileException ex; // Try to open file if (!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex)) { #ifdef _DEBUG afxDump << _T("File could not be opened ") << ex.m_cause << _T("\n"); #endif AfxMessageBox(_T("Unable to open file for reading")); return 0; } // File header BITMAPFILEHEADER FileHeader; TRY { file.Read(&FileHeader,sizeof(BITMAPFILEHEADER)); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during reading ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during reading file header")); file.Close(); return 0; } END_CATCH TRACE(_T("FileHeader.bfType : %d\n"),FileHeader.bfType); TRACE(_T("FileHeader.bfSize : %d\n"),FileHeader.bfSize); TRACE(_T("FileHeader.bfReserved1 : %d\n"),FileHeader.bfReserved1); TRACE(_T("FileHeader.bfReserved2 : %d\n"),FileHeader.bfReserved2); TRACE(_T("FileHeader.bfOffBits : %d\n"),FileHeader.bfOffBits); // Is it a Windows BMP file ? (BM) WORD sign = ((WORD) ('M' << 8) | 'B'); if (FileHeader.bfType != sign) { AfxMessageBox(_T("Invalid BMP file")); file.Close(); return 0; } // Image header TRY { file.Read(&m_Header,sizeof(BITMAPINFOHEADER)); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during reading ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during reading image header")); file.Close(); return 0; } END_CATCH // DEBUG TRACE(_T("\n")); TRACE(_T("**** IMAGE HEADER :\n")); TRACE(_T("**** biSize : %d\n"),m_Header.biSize); TRACE(_T("**** biWidth : %d\n"),m_Header.biWidth); TRACE(_T("**** biHeight : %d\n"),m_Header.biHeight); TRACE(_T("**** biPlanes : %d\n"),m_Header.biPlanes); TRACE(_T("**** biBitCount : %d\n"),m_Header.biBitCount); TRACE(_T("**** biCompression : %d\n"),m_Header.biCompression); TRACE(_T("**** biSizeImage : %d\n"),m_Header.biSizeImage); TRACE(_T("**** biXPelsPerMeter : %d\n"),m_Header.biXPelsPerMeter); TRACE(_T("**** biYPelsPerMeter : %d\n"),m_Header.biYPelsPerMeter); TRACE(_T("**** biClrUsed : %d\n"),m_Header.biClrUsed); TRACE(_T("**** biClrImportant : %d\n"),m_Header.biClrImportant); // 24 bits ? if (m_Header.biPlanes != 1 || m_Header.biBitCount != 24) { AfxMessageBox(_T("Texture file must have 24 bits depth")); file.Close(); return 0; } // Alloc (does call Free before) Free(); int nSize=m_Header.biSizeImage; if (nSize<=0) nSize =WidthByte32(m_Header.biWidth, m_Header.biBitCount)*m_Header.biHeight; m_pData = new unsigned char[nSize]; if (m_pData == NULL) { //AfxMessageBox(_T("Insuffisant memory")); file.Close(); return 0; } // Update datas m_Width = m_Header.biWidth; m_Height = m_Header.biHeight; m_Depth = m_Header.biBitCount; // Image reading TRY { file.Read(m_pData,nSize); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during reading ") << e->m_cause << _T("\n"); #endif //AfxMessageBox(_T("Error during reading image")); file.Close(); return 0; } END_CATCH // Close file file.Close(); // Success, also set FileName m_FileName = filename; UpdateWidthByte32(); return 1; } // Zyu modify on 100722,支持64位 //extern BOOL ReadJpeg(FILE *input_file, BITMAPINFOHEADER &bmfHeader, char *&pData); int CTexture::ReadFileJPG(const TCHAR *filename) { // Zyu modify on 100722,支持64位 /* FILE *fp=_tfopen(filename, _T("rb")); if (!fp) return FALSE; // File header Free(); if (!ReadJpeg(fp, m_Header, (char * &)m_pData)) { fclose(fp); return FALSE; } fclose(fp); */ // File header Free(); if (!CTangentImage::ReadJpeg(filename, m_Header,(char * &)m_pData)) { return FALSE; } // DEBUG TRACE(_T("\n")); TRACE(_T("**** IMAGE HEADER :\n")); TRACE(_T("**** biSize : %d\n"),m_Header.biSize); TRACE(_T("**** biWidth : %d\n"),m_Header.biWidth); TRACE(_T("**** biHeight : %d\n"),m_Header.biHeight); TRACE(_T("**** biPlanes : %d\n"),m_Header.biPlanes); TRACE(_T("**** biBitCount : %d\n"),m_Header.biBitCount); TRACE(_T("**** biCompression : %d\n"),m_Header.biCompression); TRACE(_T("**** biSizeImage : %d\n"),m_Header.biSizeImage); TRACE(_T("**** biXPelsPerMeter : %d\n"),m_Header.biXPelsPerMeter); TRACE(_T("**** biYPelsPerMeter : %d\n"),m_Header.biYPelsPerMeter); TRACE(_T("**** biClrUsed : %d\n"),m_Header.biClrUsed); TRACE(_T("**** biClrImportant : %d\n"),m_Header.biClrImportant); // 24 bits ? if (m_Header.biPlanes != 1 || (m_Header.biBitCount != 24 && m_Header.biBitCount != 32 )) { //AfxMessageBox(_T("Texture file must have 24 bits depth")); return 0; } // Update datas m_Width = m_Header.biWidth; m_Height = m_Header.biHeight; m_Depth = m_Header.biBitCount; // Success, also set FileName m_FileName = filename; UpdateHeader(); return 1; } // Zyu modify on 100722,支持64位 //extern int WriteJpeg( FILE * input_file, FILE * output_file); //extern int g_iSrcImgType; int CTexture::ReadFileGIF(const TCHAR *filename) { // Zyu modify on 100722 /* FILE *fpIn=_tfopen(filename, _T("rb")); if (!fpIn) return FALSE; XString sTempFile=GetTempFileName(_T(".jpg")); FILE *fpOut=_tfopen(sTempFile, _T("wb")); if (!fpOut) { fclose(fpIn); return FALSE; } XPushMemVar vTemp(g_iSrcImgType, 1); int nRet=WriteJpeg(fpIn, fpOut); fclose(fpIn); fclose(fpOut); */ XString sTempFile=GetTempFileName(_T(".jpg")); int nRet = CTangentImage::WriteJpeg(filename, sTempFile, CXIMAGE_FORMAT_GIF); if (!nRet) return nRet; nRet=ReadFileJPG(sTempFile); _tremove(sTempFile); return nRet; } int CTexture::ReadFileTGA(const TCHAR *filename) { LTGA ltga; if (!ltga.LoadFromFile(_AS(filename))) { // Zyu modify on 100722,支持64位 /* FILE *fpIn=_tfopen(filename, _T("rb")); if (!fpIn) return FALSE; XString sTempFile=GetTempFileName(_T(".jpg")); FILE *fpOut=_tfopen(sTempFile, _T("wb")); if (!fpOut) { fclose(fpIn); return FALSE; } XPushMemVar vTemp(g_iSrcImgType, 2); int nRet=WriteJpeg(fpIn, fpOut); fclose(fpIn); fclose(fpOut); */ XString sTempFile=GetTempFileName(_T(".jpg")); int nRet = CTangentImage::WriteJpeg(filename, sTempFile, CXIMAGE_FORMAT_TGA); if (!nRet) return nRet; nRet=ReadFileJPG(sTempFile); _tremove(sTempFile); return nRet; } if (ltga.GetImageType()!=itRGB && ltga.GetImageType()!=itRGBA) return FALSE; Free(); m_FileName=filename; m_Depth=ltga.GetPixelDepth(); m_Width = ltga.GetImageWidth(); m_Height = ltga.GetImageHeight(); UpdateWidthByte32(); int iPixelPerByte=m_Depth/8; int nWidthNormal=iPixelPerByte*m_Width; m_pData = new unsigned char[m_WidthByte32*m_Height]; unsigned char *pSrc=ltga.GetPixels(); for(unsigned int row=0; row0); ASSERT(height>0); ASSERT(depth>0); ASSERT(depth%8==0); ASSERT(depth/8==3 || depth/8==4); // Check for valid file CFile file; CFileException ex; // Try to open file if (!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex)) { #ifdef _DEBUG afxDump << _T("File could not be opened ") << ex.m_cause << _T("\n"); #endif AfxMessageBox(_T("Unable to open file for reading")); return 0; } // Alloc (does call Free before) if (!Alloc(width,height,depth)) { AfxMessageBox(_T("Insuffisant memory")); file.Close(); return 0; } // Image reading TRY { file.Read(m_pData,m_Width*m_Height*depth/8); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during reading ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during reading image")); file.Close(); return 0; } END_CATCH // Close file file.Close(); // Success, also set FileName m_FileName = filename; return 1; } ////////////////////////////////////////////// ////////////////////////////////////////////// // FILE SAVING ////////////////////////////////////////////// ////////////////////////////////////////////// //******************************************** // SaveFile // Redirection //******************************************** int CTexture::SaveFile(const TCHAR *filename) { CString string = filename; string.MakeLower(); TRACE(_T("CTexture::SaveFile : file : %s\n"),filename); CString extension = string.Right(4); // Redirection RAW if (extension == _T(".raw")) return SaveFileRAW(filename); // Redirection BMP if (extension == _T(".bmp")) return SaveFileBMP(filename); // Unrecognized file format CString message; message.Format(_T("CTexture::SaveFile : invalid file redirection : %s\n"),filename); AfxMessageBox(message); return 0; } //******************************************** // SaveFileRAW //******************************************** int CTexture::SaveFileRAW(const TCHAR *filename) { // Check for valid image if ((m_Width * m_Height * m_Depth) == 0) { AfxMessageBox(_T("CTexture::SaveFileRAW : invalid image")); return 0; } // Check for valid file CFile file; CFileException ex; // Try to open file if (!file.Open(filename, CFile::modeWrite | CFile::typeBinary,&ex)) { #ifdef _DEBUG afxDump << _T("File could not be opened ") << ex.m_cause << _T("\n"); #endif AfxMessageBox(_T("Unable to open file for writing")); return 0; } // Image writing TRY { file.Write(m_pData,m_Width*m_Height*m_Depth/8); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during writing ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during writing image")); file.Close(); return 0; } END_CATCH // Close file file.Close(); return 1; } //******************************************** // SaveFileBMP (*.bmp) //******************************************** // Save windows bmp files // Accept only 24 bits //******************************************** int CTexture::SaveFileBMP(const TCHAR *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)) { #ifdef _DEBUG afxDump << _T("File could not be opened ") << ex.m_cause << _T("\n"); #endif AfxMessageBox(_T("Unable to open file for writing")); return 0; } // File header BITMAPFILEHEADER FileHeader; WORD sign = ((WORD) (_T('M') << 8) | _T('B')); FileHeader.bfType = sign; FileHeader.bfSize = 14 + 40 + m_WidthByte32*m_Height; FileHeader.bfReserved1 = 0; FileHeader.bfReserved2 = 0; FileHeader.bfOffBits = 54; TRACE(_T("\nSave BMP File...\n")); TRACE(_T("FileHeader.bfType : %d\n"),FileHeader.bfType); TRACE(_T("FileHeader.bfSize : %d\n"),FileHeader.bfSize); TRACE(_T("FileHeader.bfReserved1 : %d\n"),FileHeader.bfReserved1); TRACE(_T("FileHeader.bfReserved2 : %d\n"),FileHeader.bfReserved2); TRACE(_T("FileHeader.bfOffBits : %d\n"),FileHeader.bfOffBits); TRY { file.Write(&FileHeader,sizeof(BITMAPFILEHEADER)); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during writing ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during writing file header")); file.Close(); return 0; } END_CATCH // Image header TRY { file.Write(&m_Header,sizeof(BITMAPINFOHEADER)); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during writing ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during writing image header")); file.Close(); return 0; } END_CATCH // DEBUG TRACE(_T("\n")); TRACE(_T("**** IMAGE HEADER :\n")); TRACE(_T("**** biSize : %d\n"),m_Header.biSize); TRACE(_T("**** biWidth : %d\n"),m_Header.biWidth); TRACE(_T("**** biHeight : %d\n"),m_Header.biHeight); TRACE(_T("**** biPlanes : %d\n"),m_Header.biPlanes); TRACE(_T("**** biBitCount : %d\n"),m_Header.biBitCount); TRACE(_T("**** biCompression : %d\n"),m_Header.biCompression); TRACE(_T("**** biSizeImage : %d\n"),m_Header.biSizeImage); TRACE(_T("**** biXPelsPerMeter : %d\n"),m_Header.biXPelsPerMeter); TRACE(_T("**** biYPelsPerMeter : %d\n"),m_Header.biYPelsPerMeter); TRACE(_T("**** biClrUsed : %d\n"),m_Header.biClrUsed); TRACE(_T("**** biClrImportant : %d\n"),m_Header.biClrImportant); // Image writing TRY { file.Write(m_pData,m_Header.biSizeImage); } CATCH(CFileException, e) { #ifdef _DEBUG afxDump << _T("Error during writing ") << e->m_cause << _T("\n"); #endif AfxMessageBox(_T("Error during writing image")); file.Close(); return 0; } END_CATCH // Close file file.Close(); return 1; } ////////////////////////////////////////////// ////////////////////////////////////////////// // CHECKING ////////////////////////////////////////////// ////////////////////////////////////////////// //******************************************** // 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(_T("\n")); TRACE(_T("Invalid texture\n")); TRACE(_T("Width : %d\n"),m_Width); TRACE(_T("Height : %d\n"),m_Height); TRACE(_T("Depth : %d\n"),m_Depth); TRACE(_T("Data : %x\n"),m_pData); } return success; } //******************************************** // HigherPowerOfTwo //******************************************** int CTexture::HigherPowerOfTwo(int value) { ASSERT(value > 0); if (value <= 0) return value; int power = 1; int x = 0; while(1) { x = (int)pow(2.0,power); if (x >= value) return x; power++; } return value; } //******************************************** // LowerPowerOfTwo //******************************************** int CTexture::LowerPowerOfTwo(int value) { ASSERT(value > 0); if (value <= 0) return value; int power = 1; int x = 0; while(1) { x = (int)pow(2.0,power); if (x >= value) return (int)pow(2.0,power-1); power++; } return value; } //******************************************** // 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(void) { 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(_T("Start extracting...\n")); TRACE(_T("New width : %d\n"),NewWidth); TRACE(_T("New height : %d\n"),NewHeight); ASSERT(NewWidth>=1); ASSERT(NewHeight>=1); // Alloc unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; if (pData == NULL) { AfxMessageBox(_T("Insuffisant memeory")); return 0; } for(j=0;j=1); ASSERT(NewHeight>=1); // Alloc unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; if (pData == NULL) { AfxMessageBox(_T("Insuffisant memeory")); return 0; } // o o // x o for(j=0;j=1); ASSERT(NewHeight>=1); // Alloc unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; if (pData == NULL) { AfxMessageBox(_T("Insuffisant memeory")); return 0; } // x o for(j=0;j 0); for(int i=0;iIsValid()) 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; ASSERT(size > 0); for(int i=0;im_hDC, xOffset, yOffset, width, height, 0, 0, 0, m_Height, GetData(), (CONST BITMAPINFO *)&m_Header, DIB_RGB_COLORS); } //******************************************** // 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;j=0); ASSERT(y=0); int BytePerPixel = m_Depth / 8; // Grey scale if (BytePerPixel == 1) return (int)m_pData[m_WidthByte32*y + x]; else // 24 or 32 bits (alpha layer) return (int)((int)m_pData[m_WidthByte32*y + x*BytePerPixel+0]+ (int)m_pData[m_WidthByte32*y + x*BytePerPixel+1]+ (int)m_pData[m_WidthByte32*y + x*BytePerPixel+2])/3; } unsigned char * CTexture::RepeatData(int uRep, int vRep) { if (!m_pData) return NULL; unsigned nSize=m_Width*m_Height*m_Depth/8*uRep*vRep; unsigned char *pNewData=new unsigned char[nSize]; if (!pNewData) return NULL; int iPerByte=m_Depth/8; int nRow=m_Height*vRep; int nCol=m_Width*uRep; for(int v=0; vnMaxSize) nNewHeight=nMaxSize; else { for(unsigned char cShift=1; cShiftnLow && nNewHeightnMaxSize) nNewWidth=nMaxSize; else { for(unsigned char cShift=1; cShiftnLow && nNewWidth=0); if (v1>=m_Height) v1=m_Height-1; for(unsigned int j=0; j=0); if (u1>=m_Width) u1=m_Width-1; double uDif=du-u; // 用 (u, v), (u+1, v), (u+1, v+1), (u, v+1) 4点的坐标来插值 unsigned char *rgbNew=pNewData+i*nWidth32+j*iPerByte; unsigned char *uv=m_pData+v*m_WidthByte32+u*iPerByte; unsigned char *u1v=m_pData+v*m_WidthByte32+u1*iPerByte; unsigned char *u1v1=m_pData+v1*m_WidthByte32+u1*iPerByte; unsigned char *uv1=m_pData+v1*m_WidthByte32+u*iPerByte; double duv=sqrt(vDif*vDif+uDif*uDif); double du1v=sqrt(vDif*vDif+(1.0-uDif)*(1.0-uDif)); double du1v1=sqrt((1.0-vDif)*(1.0-vDif)+(1.0-uDif)*(1.0-uDif)); double duv1=sqrt((1.0-vDif)*(1.0-vDif)+uDif*uDif); double suv = duv/(duv+du1v+du1v1+duv1); double su1v = du1v/(duv+du1v+du1v1+duv1); double su1v1 = du1v1/(duv+du1v+du1v1+duv1); double suv1 = duv1/(duv+du1v+du1v1+duv1); for(int m=0; m