BOOL ImageDib::Read(LPCTSTR lpszPathName) { CFile file; if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite)) return FALSE; BITMAPFILEHEADER bmfh; int nCount=file.Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER)); if(m_lpDib!=NULL) delete []m_lpDib; m_lpDib=new BYTE[file.GetLength() -sizeof(BITMAPFILEHEADER)]; file.Read(m_lpDib, file.GetLength() -sizeof(BITMAPFILEHEADER)); m_lpBmpInfoHead = (LPBITMAPINFOHEADER)m_lpDib; m_imgWidth=m_lpBmpInfoHead->biWidth; m_imgHeight=m_lpBmpInfoHead->biHeight; m_nBitCount=m_lpBmpInfoHead->biBitCount; m_nColorTableLength= ComputeColorTabalLength(m_lpBmpInfoHead->biBitCount); m_hPalette = NULL; if(m_nColorTableLength!=0){m_lpColorTable= (LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER)); MakePalette(); } m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableLength; return TRUE; }
BOOL CDib::AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal) { // asume que BITMAPINFOHEADER, la tabla de colores y la imagen son contiguos // la tabla de colores podría ser de longitud cero Empty(); m_hGlobal = hGlobal; if(bMustDelete == FALSE) { m_nBmihAlloc = noAlloc; } else { m_nBmihAlloc = ((hGlobal == NULL) ? crtAlloc : heapAlloc); } try { m_lpBMIH = (LPBITMAPINFOHEADER) lpvMem; ComputeMetrics(); ComputePaletteSize(m_lpBMIH->biBitCount); m_lpImage = (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries; MakePalette(); } catch(CException* pe) { AfxMessageBox(_T("Error de AttachMemory")); pe->Delete(); return FALSE; } return TRUE; }
CImageBMP::CImageBMP( const CBitmap* bmp) { bgindex = -1; lpbi = 0; RawImage = 0; imagePalette = 0; if (bmp) { BITMAP bm; HBITMAP hBitmap = (HBITMAP)(bmp->GetSafeHandle()); GetObject(hBitmap, sizeof(BITMAP), (LPSTR) &bm); int width = bm.bmWidth; int height = bm.bmHeight; // int depth = bm.bmPlanes; int depth = bm.bmBitsPixel; Create(width, height, depth); HDC dc = ::GetDC(NULL); if (GetDIBits(dc, hBitmap, 0, GetHeight(), RawImage, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0) { TRACE0("GetDIBits failed"); } // Create a palette - PJO HPALETTE palette; if (palette = MakePalette((const BITMAPINFO FAR*)lpbi, 0)) { imagePalette = new CImagePalette; imagePalette->Attach(palette); DibSetUsage(lpbi, (HPALETTE) (*imagePalette), CIMAGE_COLORS); ColorType = (COLORTYPE_PALETTE | COLORTYPE_COLOR); } ::ReleaseDC(NULL, dc); } }
//------------------------------------------------------------------------------ Example::Example(void) : glfw_error_handler(glfwSetErrorCallback(HandleGLFWError)) , glfw_init_ok(glfwInit()) , glfw_window(InitWindow()) , gl() , palette(MakePalette()) , program(MakeProgram()) , view_matrix(program, "ViewMatrix") , screen( oglplus::List("Position").Get(), oglplus::shapes::Screen(), program ), screen_width(800) , screen_height(600) , view_aspect(4.0/3.0) , view_divs(4) , view_tile(0) , view_tile_index(view_divs*view_divs) , mouse_left_down(false) , mouse_middle_down(false) , frame_no(0) { oglplus::UniformSampler(program, "Palette").Set(0); for(unsigned i=0; i!=view_tile_index.size(); ++i) view_tile_index[i] = i; CenterView(); UpdateView(); screen.Use(); self_ptr(this); gl.Enable(oglplus::Capability::ScissorTest); }
/************************************************************************* * * \函数名称: * Read() * * \输入参数: * CFile* pFile - 指向CFile对象的指针 * * \返回值: * BOOL - 如果成功,则返回TRUE * * \说明: * 该函数DIB从一个文件读入CDib对象。该文件必须成功打开。如果该文件是BMP文件 * 读取工作从文件头开始。如果该文件是一个文档,读取工作则从当前文件指针处开始 * ************************************************************************ */ BOOL CDib::Read(CFile* pFile) { // 释放已经分配的内存 Empty(); // 临时存放信息的变量 int nCount, nSize; BITMAPFILEHEADER bmfh; // 进行读操作 try { // 读取文件头 nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { throw new CException; } // 如果文件类型部位"BM",则返回并进行相应错误处理 if(bmfh.bfType != 0x4d42) { throw new CException; } // 计算信息头加上调色板的大小,并分配相应的内存 nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; m_nBmihAlloc = m_nImageAlloc = crtAlloc; // 读取信息头和调色板 nCount = pFile->Read(m_lpBMIH, nSize); // 计算图象数据大小并设置调色板指针 ComputeMetrics(); // 计算调色板的表项数 ComputePaletteSize(m_lpBMIH->biBitCount); // 如果DIB中存在调色板,则创建一个Windows调色板 MakePalette(); // 分配图象数据内存,并从文件中读取图象数据 m_lpImage = (LPBYTE) new char[m_dwSizeImage]; nCount = pFile->Read(m_lpImage, m_dwSizeImage); } // 错误处理 catch(CException* pe) { AfxMessageBox("Read error"); pe->Delete(); return FALSE; } // 返回 return TRUE; }
ImageDib::ImageDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable, unsigned char *pImgData) { if(pImgData==NULL){ m_lpDib=NULL; m_lpColorTable=NULL; m_pImgData=NULL; m_lpBmpInfoHead=NULL; m_hPalette = NULL; } else{ m_imgWidth=size.cx; m_imgHeight=size.cy; m_nBitCount=nBitCount; m_nColorTableLength=ComputeColorTabalLength(nBitCount); int lineByte=(m_imgWidth*nBitCount/8+3)/4*4; int imgBufSize=m_imgHeight*lineByte; m_lpDib=new BYTE [sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableLength+imgBufSize]; m_lpBmpInfoHead = (LPBITMAPINFOHEADER) m_lpDib; m_lpBmpInfoHead->biSize = sizeof(BITMAPINFOHEADER); m_lpBmpInfoHead->biWidth = m_imgWidth; m_lpBmpInfoHead->biHeight = m_imgHeight; m_lpBmpInfoHead->biPlanes = 1; m_lpBmpInfoHead->biBitCount = m_nBitCount; m_lpBmpInfoHead->biCompression = BI_RGB; m_lpBmpInfoHead->biSizeImage = 0; m_lpBmpInfoHead->biXPelsPerMeter = 0; m_lpBmpInfoHead->biYPelsPerMeter = 0; m_lpBmpInfoHead->biClrUsed = m_nColorTableLength; m_lpBmpInfoHead->biClrImportant = m_nColorTableLength; m_hPalette = NULL; if(m_nColorTableLength!=0){ m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER)); memcpy(m_lpColorTable,lpColorTable,sizeof(RGBQUAD) * m_nColorTableLength); MakePalette(); } m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER)+ sizeof(RGBQUAD) * m_nColorTableLength; memcpy(m_pImgData,pImgData,imgBufSize); } }
BOOL CDib::ReadSection(CFile* pFile, CDC* pDC /* = NULL */) { // nueva función que lee el BMP del disco y crea una sección de DIB // permite la modificación de mapas de bits de disco // 1. leer cabecera de archivo para obtener el tamaño de la cabecera de info + tabla de colores // 2. leer cabecera de info (para obtener el tamaño de la imagen) y la tabla de colores // 3. crear sección de DIB en función de los parámetros de la cabecera // 4. leer la imagen en memoria que asigna CreateDibSection Empty(); int nCount, nSize; BITMAPFILEHEADER bmfh; try { nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { //throw new CException; throw new std::exception; } if(bmfh.bfType != 0x4d42) { //throw new CException; throw new std::exception; } nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; m_nBmihAlloc = crtAlloc; m_nImageAlloc = noAlloc; nCount = pFile->Read(m_lpBMIH, nSize); // cabecera de info y tabla de colores if(m_lpBMIH->biCompression != BI_RGB) { //throw new CException; throw new std::exception; } ComputeMetrics(); ComputePaletteSize(m_lpBMIH->biBitCount); MakePalette(); UsePalette(pDC); m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0); ASSERT(m_lpImage != NULL); nCount = pFile->Read(m_lpImage, m_dwSizeImage); // solo la imagen } catch(CException* pe) { AfxMessageBox(_T("Error de ReadSection")); pe->Delete(); return FALSE; } return TRUE; }
BOOL CDib::CopyToMapFile(const TCHAR* strPathname) { // copia el DIB en un nuevo archivo, libera los punteros antes // si se ha utilizado previamente CreateSection, el HBITMAP será NULL (y no utilizable) BITMAPFILEHEADER bmfh; bmfh.bfType = 0x4d42; // 'BM' bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER); // el significado de bfSize abierto a la interpretación bmfh.bfReserved1 = bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); int nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries + m_dwSizeImage; HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL); DWORD dwErr = ::GetLastError(); ASSERT(hMap != NULL); LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // proyectar archivo completo ASSERT(lpvFile != NULL); LPBYTE lpbCurrent = (LPBYTE) lpvFile; memcpy(lpbCurrent, &bmfh, sizeof(BITMAPFILEHEADER)); // cabecera de archivo lpbCurrent += sizeof(BITMAPFILEHEADER); LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpbCurrent; memcpy(lpbCurrent, m_lpBMIH, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries); // información lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; memcpy(lpbCurrent, m_lpImage, m_dwSizeImage); // imagen de bits DWORD dwSizeImage = m_dwSizeImage; Empty(); m_dwSizeImage = dwSizeImage; m_nBmihAlloc = m_nImageAlloc = noAlloc; m_lpBMIH = lpBMIH; m_lpImage = lpbCurrent; m_hFile = hFile; m_hMap = hMap; m_lpvFile = lpvFile; ComputePaletteSize(m_lpBMIH->biBitCount); ComputeMetrics(); MakePalette(); return TRUE; }
CDib::CDib(CSize size, int nBitCount, BOOL bInitialize) { m_pntOrigo = CPoint(0,0); //default origo m_hPalette = NULL; m_lpBMIH = NULL; m_lpImage = NULL; Empty(); ComputePaletteSize(nBitCount); m_lpBMIH = (LPBITMAPINFOHEADER) new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*m_nColorTableEntries]; m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER); m_lpBMIH->biWidth = size.cx; m_lpBMIH->biHeight = size.cy; m_lpBMIH->biPlanes = 1; m_lpBMIH->biBitCount = nBitCount; m_lpBMIH->biCompression = BI_RGB; m_lpBMIH->biSizeImage = 0; m_lpBMIH->biXPelsPerMeter = 0; m_lpBMIH->biYPelsPerMeter = 0; m_lpBMIH->biClrUsed = m_nColorTableEntries; m_lpBMIH->biClrImportant = m_nColorTableEntries; ComputeMetrics(); m_lpImage=(LPBYTE) new char[m_dwSizeImage]; if (bInitialize) { //make default palette from def256pal_x constants int i; switch (nBitCount) { case 1: SetPaletteEntry(0,0); //black SetPaletteEntry(1,RGB(255,255,255)); //white break; case 8: for (i=0; i<=255; i++) { SetPaletteEntry(i,RGB(def256pal_r[i],def256pal_g[i],def256pal_b[i])); } break; case 24: break; } memset(m_lpImage, 0, m_dwSizeImage); //initialize image bits to zero } MakePalette(); }
/************************************************************************* * * \函数名称: * AttachMemory() * * \输入参数: * LPVOID lpvMem - 要关联的内存地址 * BOOL bMustDelete - 如果CDib类负责删除这个内存,标记为TRUE * - 默认值为FALSE * HGLOBAL hGlobal - 如果内存是通过Win32 GlobalAlloc得到的, * - 则CDib对象必须保存该句柄,这样,以后 * - 可以释放句柄。这里假设bMustDelete设置为TRUE * * \返回值: * BOOL - 如果成功,则为TRUE * * \说明: * 用内存中的DIB与已有的CDib对象关联。此内存可能是程序的资源,或者是可能是剪贴板 * 或者OLE数据对象内存。内存可能已经由CRT堆栈用new运算符分配了,或者可能已经由 * Windows堆栈用GlobalAlloc分配了。 * ************************************************************************ */ BOOL CDib::AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal) { // 首先释放已经分配的内存 Empty(); m_hGlobal = hGlobal; // bMustDelete为TRUE表示此CDib类分配的内存,负责删除 // 否则的设置信息头分配状态为noAlloc if(bMustDelete == FALSE) { m_nBmihAlloc = noAlloc; } else { m_nBmihAlloc = ((hGlobal == NULL) ? crtAlloc : heapAlloc); } try { // 设置信息头指针 m_lpBMIH = (LPBITMAPINFOHEADER) lpvMem; // 重新计算得到图象数据块的大小,并设置调色板的指针 ComputeMetrics(); // 计算调色板的尺寸 ComputePaletteSize(m_lpBMIH->biBitCount); // 设置图象数据指针 m_lpImage = (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries; // 如果调色板存在的话,读取它,并创建一个Windows调色板, // 并将调色板的句柄存放在数据成员中 MakePalette(); } // 错误处理 catch(CException* pe) { AfxMessageBox("AttachMemory error"); pe->Delete(); return FALSE; } // 返回 return TRUE; }
CDib& CDib::operator=(const CDib& dib) { ASSERT(this != &dib); //beware of dib=dib if (dib.m_lpBMIH) { Empty(); //clear left operand (dib we are coping to) int headerSize = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*dib.m_nColorTableEntries; //copy header m_lpBMIH = (LPBITMAPINFOHEADER) new char[headerSize]; memcpy(m_lpBMIH,dib.m_lpBMIH,headerSize); //copy member variables ComputeMetrics(); ComputePaletteSize(dib.m_lpBMIH->biBitCount); MakePalette(); m_pntOrigo = dib.m_pntOrigo; //copy bits m_lpImage = (LPBYTE)new char[dib.m_dwSizeImage]; memcpy(m_lpImage,dib.m_lpImage,dib.m_dwSizeImage); } return *this; }
CDib::CDib(const CDib& dib,CRect rect) //copy area of interest from dib { int headerSize = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*dib.m_nColorTableEntries; //copy header m_lpBMIH = (LPBITMAPINFOHEADER) new char[headerSize]; memcpy(m_lpBMIH,dib.m_lpBMIH,headerSize); //correct size m_lpBMIH->biWidth=rect.Width(); m_lpBMIH->biHeight=rect.Height(); m_lpBMIH->biSizeImage = 0; //compute member variables ComputeMetrics(); ComputePaletteSize(dib.m_lpBMIH->biBitCount); MakePalette(); m_pntOrigo = CPoint(0,0); //default origo //copy bits m_lpImage = (LPBYTE)new char[m_dwSizeImage]; for(int y=rect.top; y<=rect.bottom; y++){ for(int x=rect.left; x<=rect.right; x++){ SetPixel(CPoint(x-rect.left,y-rect.top),dib.GetPixel(CPoint(x,y))); } } }
BOOL CDib::Read(CFile* pFile) { // 1. leer cabecera de archivo para obtener el tamaño de la cabecera de info + tabla de colores // 2. leer cabecera de info (para obtener el tamaño de la imagen) y la tabla de colores // 3. leer la imagen // no se puede utilizar bfSize de la cabecera de info Empty(); int nCount, nSize; BITMAPFILEHEADER bmfh; try { nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { //throw new CException; throw new std::exception; } if(bmfh.bfType != 0x4d42) { //throw new CException; throw new std::exception; } nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; m_nBmihAlloc = m_nImageAlloc = crtAlloc; nCount = pFile->Read(m_lpBMIH, nSize); // cabecera de info y tabla de colores ComputeMetrics(); ComputePaletteSize(m_lpBMIH->biBitCount); MakePalette(); m_lpImage = (LPBYTE) new char[m_dwSizeImage]; nCount = pFile->Read(m_lpImage, m_dwSizeImage); // sólo la imagen } catch(CException* pe) { AfxMessageBox(_T("Error de lectura")); pe->Delete(); return FALSE; } return TRUE; }
BOOL CImageBMP::ReadFile(const CString& imageFileName) { if (imageFileName != "") filename = imageFileName; if (lpbi = DibOpenFile((char *)(const char *)filename)) { Width = DibWidth(lpbi); Height = DibHeight(lpbi); Depth = DibBitCount(lpbi); RawImage = (ImagePointerType)DibPtr(lpbi); EffWidth = (long)(((long)Width*Depth + 31) / 32) * 4; HPALETTE palette; if (palette = MakePalette((const BITMAPINFO FAR*)lpbi, 0)) { imagePalette = new CImagePalette; imagePalette->Attach(palette); DibSetUsage(lpbi, (HPALETTE) (*imagePalette), CIMAGE_COLORS); ColorType = (COLORTYPE_PALETTE | COLORTYPE_COLOR); } return TRUE; } return FALSE; }
/************************************************************************* * * \函数名称: * Compress() * * \输入参数: * CDC* pDC - 设备上下文指针 * BOOL bCompress - TRUE对应于压缩的DIB,FALSE对应于不压缩的DIB * * \返回值: * BOOL - 如果成功,则返回TRUE * * \说明: * 该函数将DIB重新生成为压缩或者不压缩的DIB。在内部,它转换已有的DIB为DDB位图 * 然后生成一个新的压缩或者不压缩的DIB。压缩仅为4bpp和8bpp的DIB所支持。不能 * 压缩DIB段 * ************************************************************************ */ BOOL CDib::Compress(CDC* pDC, BOOL bCompress /* = TRUE */) { // 判断是否为4bpp或者8bpp位图,否则,不进行压缩,返回FALSE if((m_lpBMIH->biBitCount != 4) && (m_lpBMIH->biBitCount != 8)) return FALSE; // 如果为DIB段,也不能支持压缩,返回FALSE if(m_hBitmap) return FALSE; TRACE("Compress: original palette size = %d\n", m_nColorTableEntries); // 获得设备上下文句柄 HDC hdc = pDC->GetSafeHdc(); // 将此DIB的调色板选入设备上下文,并保存以前的调色板句柄 HPALETTE hOldPalette = ::SelectPalette(hdc, m_hPalette, FALSE); HBITMAP hBitmap; // 创建一个DDB位图,如果不成功,则返回FALSE if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE; // 计算信息头加上调色板的大小尺寸,并给它们分配内存 int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; // 将信息头和调色板拷贝到内存中 memcpy(lpBMIH, m_lpBMIH, nSize); // new header // 如果需要进行压缩,设置相应的信息,并创建压缩格式的DIB if(bCompress) { switch (lpBMIH->biBitCount) { case 4: lpBMIH->biCompression = BI_RLE4; break; case 8: lpBMIH->biCompression = BI_RLE8; break; default: ASSERT(FALSE); } // 设置位图数据指针为NULL,调用GetDIBits来得到压缩格式的DIB的尺寸 // 如果不能创建DIB,则进行相应的错误处理。 if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight, NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) { AfxMessageBox("Unable to compress this DIB"); // 删除临时变量,并释放已分配内存 ::DeleteObject(hBitmap); delete [] lpBMIH; // 重新将以前的调色板选入,并返回FALSE ::SelectPalette(hdc, hOldPalette, FALSE); return FALSE; } // 如果位图数据为空,则进行相应的错误处理 if (lpBMIH->biSizeImage == 0) { AfxMessageBox("Driver can't do compression"); // 删除临时变量,并释放已分配内存 ::DeleteObject(hBitmap); delete [] lpBMIH; // 重新将以前的调色板选入,并返回FALSE ::SelectPalette(hdc, hOldPalette, FALSE); return FALSE; } // 将位图数据尺寸赋值给类的成员变量 else { m_dwSizeImage = lpBMIH->biSizeImage; } } // 如果是解压缩,进行相应的处理 else { // 设置压缩格式为不压缩 lpBMIH->biCompression = BI_RGB; // 根据位图的宽度和高度计算位图数据内存的大小 DWORD dwBytes = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32; if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32) { dwBytes++; } dwBytes *= 4; // 将得到位图数据的大小尺寸保存在类的成员变量中 m_dwSizeImage = dwBytes * lpBMIH->biHeight; // 将位图数据内存的大小赋值给临时的信息头中的相应的变量 lpBMIH->biSizeImage = m_dwSizeImage; } // 再次调用GetDIBits来生成DIB数据 // 分配临时存放位图数据 LPBYTE lpImage = (LPBYTE) new char[m_dwSizeImage]; // 再次调用GetDIBits来生成DIB数据,注意此时位图数据指针不为空 VERIFY(::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight, lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)); TRACE("dib successfully created - height = %d\n", lpBMIH->biHeight); // 压缩转换完毕,进行相应的其他处理 // 删除临时的DDB位图 ::DeleteObject(hBitmap); // 释放原来的DIB分配的内存 Empty(); // 重新设置图象信息头和图象数据内存分配状态 m_nBmihAlloc = m_nImageAlloc = crtAlloc; // 重新定位信息头和图象数据指针 m_lpBMIH = lpBMIH; m_lpImage = lpImage; // 计算图象数据尺寸,并设置DIB中调色板的指针 ComputeMetrics(); // 计算DIB中调色板的尺寸 ComputePaletteSize(m_lpBMIH->biBitCount); // 如果DIB中调色板存在的话,读取并创建一个Windows调色板 MakePalette(); // 恢复以前的调色板 ::SelectPalette(hdc, hOldPalette, FALSE); TRACE("Compress: new palette size = %d\n", m_nColorTableEntries); // 返回 return TRUE; }
static int ImageToGif(UCHAR **Image,int ImageWidth,int ImageHeight, char *GifFileName,int Paleta,int Laplas) { int NumLevels=255,i; /* Konwersja ekranu wirtualnego do postaci */ GifColorType *ColorMap; /* obrazu w formacie GIF */ GifFileType *GifFile; /* Oparte na bibliotece giflib */ if(prn==ON) fprintf(stdout,"<<< TWORZENIE OBRAZU W FORMACIE GIF'A : %s >>>\n",GifFileName); if((GifFile=EGifOpenFileName(GifFileName,0))==NULL) { QuitGifError(GifFile); return -1; } if((ColorMap=(GifColorType *)malloc(NumLevels*sizeof(GifColorType)))==NULL) { fprintf(stderr,"Failed to allocate memory required, aborted.\n"); QuitGifError(GifFile); return -1; } if(prn==ON) fprintf(stdout,"<<< GENERACJA PALETY BARW (%s) >>>\n", ((Paleta==COLOR) ? "TERM" : ( (Paleta==INVERT_GRAY) ? "INVERT GARY" : "GRAY") ) ); MakePalette(ColorMap,Paleta,Laplas); if(EGifPutScreenDesc(GifFile,ImageWidth,ImageHeight,8,0, 8,ColorMap)==GIF_ERROR) { QuitGifError(GifFile); free((void *)ColorMap); return -1; } if(EGifPutImageDesc(GifFile,0,0,ImageWidth,ImageHeight, FALSE,8,NULL)==GIF_ERROR) { QuitGifError(GifFile); free((void *)ColorMap); return -1; } if(prn==ON) fprintf(stdout,"<<< KODOWANIE OBRAZU >>>\n"); for(i=0 ; i<ImageHeight ; i++) if(EGifPutLine(GifFile,Image[i],ImageWidth)==GIF_ERROR) { QuitGifError(GifFile); free((void *)ColorMap); return -1; } if(EGifCloseFile(GifFile)==GIF_ERROR) { QuitGifError(GifFile); free((void *)ColorMap); return -1; } free((void *)ColorMap); return 0; }
/************************************************************************* * * \函数名称: * CopyToMapFile() * * \输入参数: * const char* strPathname - 映射文件的路径名 * * \返回值: * BOOL - 如果成功,则为TRUE * * \说明: * 该函数可以创建一个新的内存映射文件,并将现有的CDib数据复制到该文件的内存 * 释放以前的所有内存。并关闭现有的所有内存映射文件。实际上,直到新文件 * 关闭的时候,才将这个数据写到磁盘,但是,当CDib对象被重复使用或被破坏 * 时,也会发生写磁盘操作 * ************************************************************************ */ BOOL CDib::CopyToMapFile(const char* strPathname) { BITMAPFILEHEADER bmfh; // 设置文件头信息 bmfh.bfType = 0x4d42; bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER); bmfh.bfReserved1= bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; // 创建接收数据的文件 HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); // 计算文件的大小尺寸 int nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries + m_dwSizeImage; // 创建内存映射文件对象 HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL); DWORD dwErr = ::GetLastError(); ASSERT(hMap != NULL); // 映射整个文件 LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); ASSERT(lpvFile != NULL); // 临时文件指针 LPBYTE lpbCurrent = (LPBYTE) lpvFile; // 拷贝文件头信息到内存映射文件中 memcpy(lpbCurrent, &bmfh, sizeof(BITMAPFILEHEADER)); // 计算信息头在文件中的地址,并拷贝信息头信息 lpbCurrent += sizeof(BITMAPFILEHEADER); LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpbCurrent; memcpy(lpbCurrent, m_lpBMIH, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries); // 计算调色板在文件中的地址,并拷贝调色板 lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; memcpy(lpbCurrent, m_lpImage, m_dwSizeImage); // 暂时存放图象数据尺寸变量 DWORD dwSizeImage = m_dwSizeImage; // 释放一起分配的所有内存 Empty(); // 设置图象数据尺寸并设置内存分配状态 m_dwSizeImage = dwSizeImage; m_nBmihAlloc = m_nImageAlloc = noAlloc; // 信息头指针重新指向文件中的位置 m_lpBMIH = lpBMIH; // 图象数据指针重新指向文件中的数据地址 m_lpImage = lpbCurrent; // 设置文件句柄 m_hFile = hFile; // 设置映射对象句柄 m_hMap = hMap; // 设置映射文件指针 m_lpvFile = lpvFile; // 重新计算得到调色板尺寸 ComputePaletteSize(m_lpBMIH->biBitCount); // 重新计算图象数据块大小,并设置调色板指针 ComputeMetrics(); // 如果调色板存在的话,读取并创建一个Windows调色板 MakePalette(); // 返回 return TRUE; }
BOOL CDib::Compress(CDC* pDC, BOOL bCompress /* = TRUE */) { // 1. crea un mapa de bits GDI a partir de un DIB existente // 2. crea un nuevo DIB a partir del mapa de bits GDI con compresión // 3. libera el DIB original // 4. pone el nuevo DIB en el objeto if((m_lpBMIH->biBitCount != 4) && (m_lpBMIH->biBitCount != 8)) return FALSE; // sólo se admite la compresión para DIBs de 4 y 8 bpp if(m_hBitmap) return FALSE; // ¡no se puede comprimir una sección de DIB! TRACE("Compresión: tamaño original de la paleta = %d\n", m_nColorTableEntries); HDC hdc = pDC->GetSafeHdc(); HPALETTE hOldPalette = ::SelectPalette(hdc, m_hPalette, FALSE); HBITMAP hBitmap; // temporal if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE; int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries; LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; memcpy(lpBMIH, m_lpBMIH, nSize); // nueva cabecera if(bCompress) { switch (lpBMIH->biBitCount) { case 4: lpBMIH->biCompression = BI_RLE4; break; case 8: lpBMIH->biCompression = BI_RLE8; break; default: ASSERT(FALSE); } // llama a GetDIBits con un puntero de datos nulo para obtener el tamaño del DIB comprimido if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight, NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) { AfxMessageBox(_T("No se ha podido comprimir este DIB")); // probablemente un problema con la tabla de colores ::DeleteObject(hBitmap); delete [] lpBMIH; ::SelectPalette(hdc, hOldPalette, FALSE); return FALSE; } if (lpBMIH->biSizeImage == 0) { AfxMessageBox(_T("El controlador no puede realizar la compresión")); ::DeleteObject(hBitmap); delete [] lpBMIH; ::SelectPalette(hdc, hOldPalette, FALSE); return FALSE; } else { m_dwSizeImage = lpBMIH->biSizeImage; } } else { lpBMIH->biCompression = BI_RGB; // descomprimir // descubrir el tamaño de la imagen a partir de la anchura y altura del mapa de bits DWORD dwBytes = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32; if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32) { dwBytes++; } dwBytes *= 4; m_dwSizeImage = dwBytes * lpBMIH->biHeight; // sin compresión lpBMIH->biSizeImage = m_dwSizeImage; } // segunda llamada a GetDIBits para crear el DIB LPBYTE lpImage = (LPBYTE) new char[m_dwSizeImage]; VERIFY(::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight, lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)); TRACE("dib creado con éxito - altura = %d\n", lpBMIH->biHeight); ::DeleteObject(hBitmap); Empty(); m_nBmihAlloc = m_nImageAlloc = crtAlloc; m_lpBMIH = lpBMIH; m_lpImage = lpImage; ComputeMetrics(); ComputePaletteSize(m_lpBMIH->biBitCount); MakePalette(); ::SelectPalette(hdc, hOldPalette, FALSE); TRACE("Compresión: nuevo tamaño de la paleta = %d\n", m_nColorTableEntries); return TRUE; }
void ProcessImageLine(char buffer[]) { char *token; long whattodo; int i; char ImageName[200]; char ParentID[32]; char *img; BITMAPINFO bmi; long colors; WORD *Palette; WORD *Image16; char *Image8; long x,y,w,h,cx,cy,size; ImageList *ImageRecord; x=0; y=0; w=0; h=0; cx=0; cy=0; size=0; Image8=NULL; Image16=NULL; Palette=NULL; token=strtok(buffer," ,\t\n"); if(!token) return; whattodo=FindTODO(token); if(!whattodo) return; if(whattodo == LOAD_PATH || whattodo == LOAD_PATH_TRANSPARENT) { token=strtok(NULL," ,\t\n"); if(!token) return; if(token[0] != '"') { printf("Error in output filename (%s)\n",token); return; } token++; i=0; while(token[i] && token[i] != '"') i++; token[i]=0; strcpy(OutputFile,token); } token=strtok(NULL," ,\t\n"); if(!token) return; strcpy(Label,token); token=strtok(NULL," ,\t\n"); if(!token) return; if(whattodo == LOAD_IMAGE || whattodo == LOAD_DISCARD || whattodo == LOAD_TRANSPARENT || whattodo == LOAD_DISCARD_TRANSPARENT || whattodo == LOAD_PATH || whattodo == LOAD_PATH_TRANSPARENT) { if(token[0] != '"') { printf("Error in filename (%s)\n",token); return; } token++; i=0; while(token[i] && token[i] != '"') i++; token[i]=0; strcpy(ImageName,token); token=strtok(NULL," ,\t\n"); } if(whattodo == LOAD_IMAGE || whattodo == LOAD_TRANSPARENT || whattodo == LOAD_DISCARD || whattodo == LOAD_DISCARD_TRANSPARENT || whattodo == LOAD_PATH || whattodo == LOAD_PATH_TRANSPARENT) { if(OriginalImage) delete OriginalImage; if(!LoadTarga16File(ImageName, &OriginalImage, &bmi )) { printf("Error loading (%s)... ignoring this line\n",ImageName); OriginalImage=NULL; return; } ImageW=bmi.bmiHeader.biWidth; ImageH=bmi.bmiHeader.biHeight; x=0; y=0; w=ImageW; h=ImageH; } if(!OriginalImage) { printf("No image to process\n"); return; } if(whattodo == LOAD_IMAGE || whattodo == LOAD_DISCARD) UseColorKey=0; if(whattodo == LOAD_TRANSPARENT || whattodo == LOAD_DISCARD_TRANSPARENT || whattodo == LOAD_PATH_TRANSPARENT) UseColorKey=_RSC_COLORKEY_; if(whattodo == LOAD_IMAGE || whattodo == LOAD_TRANSPARENT || whattodo == LOAD_PATH || whattodo == LOAD_PATH_TRANSPARENT) { if(token) { cx=atol(token); token=strtok(NULL," ,\t\n"); if(token) cy=atol(token); } } else if(whattodo != LOAD_DISCARD && whattodo != LOAD_DISCARD_TRANSPARENT) { i=0; while(token) { switch(i) { case 0: x=atol(token); break; case 1: y=atol(token); break; case 2: w=atol(token); break; case 3: h=atol(token); break; case 4: cx=atol(token); break; case 5: cy=atol(token); break; } i++; token=strtok(NULL," ,\t\n"); } if(i < 4) { printf("Not enough parameters...\n"); return; } } if(whattodo != LOAD_DISCARD && whattodo != LOAD_DISCARD_TRANSPARENT && whattodo != LOAD_PATH && whattodo != LOAD_PATH_TRANSPARENT) { if(cx == -1) cx=w/2; if(cy == -1) cy=h/2; ImageRecord=new ImageList; memset(ImageRecord,0,sizeof(ImageList)); colors=BuildColorTable((WORD*)OriginalImage,x,y,w,h,ImageW,ImageH-1); if(colors && colors <= 256) { size=w*h; Palette=MakePalette(colors); Image8=(char *)ConvertTo8Bit((WORD*)OriginalImage,x,y,w,h,ImageW,ImageH-1); ImageRecord->Header.Type=_RSC_IS_IMAGE_; strcpy(ImageRecord->Header.ID,Label); ImageRecord->Header.flags=_RSC_8_BIT_ | UseColorKey; ImageRecord->Header.centerx=cx; ImageRecord->Header.centery=cy; ImageRecord->Header.w=w; ImageRecord->Header.h=h; ImageRecord->Header.imageoffset=0; ImageRecord->Header.palettesize=colors; ImageRecord->Header.paletteoffset=0; ImageRecord->ImageSize=size; ImageRecord->PaletteSize=colors*sizeof(WORD); ImageRecord->Image=Image8; ImageRecord->Palette=Palette; HeaderSize+=sizeof(ImageFmt); DataSize+=(ImageRecord->ImageSize+ImageRecord->PaletteSize); } else { size=w*h*sizeof(WORD); Image16=CopySubArea((WORD*)OriginalImage,x,y,w,h,ImageW,ImageH-1); ImageRecord->Header.Type=_RSC_IS_IMAGE_; strcpy(ImageRecord->Header.ID,Label); ImageRecord->Header.flags=_RSC_16_BIT_ | UseColorKey; ImageRecord->Header.centerx=cx; ImageRecord->Header.centery=cy; ImageRecord->Header.w=w; ImageRecord->Header.h=h; ImageRecord->Header.imageoffset=0; ImageRecord->Header.paletteoffset=0; ImageRecord->ImageSize=size; ImageRecord->PaletteSize=0; ImageRecord->Image=Image16; HeaderSize+=sizeof(ImageFmt); DataSize+=(ImageRecord->ImageSize); } ImageTable->Add(UniqueID++,ImageRecord); } }
/************************************************************************* * * \函数名称: * ReadSection() * * \输入参数: * CFile* pFile - 指向CFile对象的指针;对应的磁盘 * - 文件中包含DIB * CDC* pDC - 设备上下文指针 * * \返回值: * BOOL - 如果成功,则返回TRUE * * \说明: * 该函数从BMP文件中读取信息头,调用CreateDIBSection来分配图象内存,然后将 * 图象从该文件读入刚才分配的内存。如果你想从磁盘读取一个DIB,然后通过调用 * GDI函数编辑它的话,可以使用该函数。你可以用Write或CopyToMapFile将DIB写 * 回到磁盘 * ************************************************************************ */ BOOL CDib::ReadSection(CFile* pFile, CDC* pDC /* = NULL */) { // 释放已经分配的内存 Empty(); // 临时变量 int nCount, nSize; BITMAPFILEHEADER bmfh; // 从文件中读取数据 try { // 读取文件头 nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER)); if(nCount != sizeof(BITMAPFILEHEADER)) { throw new CException; } // 如果文件类型部位"BM",则返回并进行相应错误处理 if(bmfh.bfType != 0x4d42) { throw new CException; } // 计算信息头加上调色板的大小,并分配相应的内存 nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]; m_nBmihAlloc = crtAlloc; m_nImageAlloc = noAlloc; // 读取信息头和调色板 nCount = pFile->Read(m_lpBMIH, nSize); // 如果图象为压缩格式,则不进行后续处理 if(m_lpBMIH->biCompression != BI_RGB) { throw new CException; } // 计算图象数据大小并设置调色板指针 ComputeMetrics(); // 计算调色板的表项数 ComputePaletteSize(m_lpBMIH->biBitCount); // 如果DIB中存在调色板,则创建一个Windows调色板 MakePalette(); // 将CDib对象的逻辑调色板选入设备上下文 UsePalette(pDC); // 创建一个DIB段,并分配图象内存 m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0); ASSERT(m_lpImage != NULL); // 从文件中读取图象数据 nCount = pFile->Read(m_lpImage, m_dwSizeImage); } // 错误处理 catch(CException* pe) { AfxMessageBox("ReadSection error"); pe->Delete(); return FALSE; } return TRUE; }