在看ImageMagick时,忽然觉得,我们应该至少能完全掌握一种是常使用的图片文件格式才行。
首先想到,应该是BMP,不要求复杂,只掌握24bit,非压编的BMP即可。
于是用WTL的CMemoryDC试写了一个,因为是第一次这样按位来SetPixel,有很多问题到写时才觉得复杂,
真正完成时,已经是深夜了。 把它们贴到blog上,以后不想再又试一遍了。
void TouchBmp(HDC dc, const char *fil) { CRect wnd_rc; GetClientRect(wnd_rc); CMemoryDC mdc(dc, wnd_rc); mslog(_T("Cliping: t: %d l: %d, r:%d b:%d"), wnd_rc.top, wnd_rc.left, wnd_rc.right, wnd_rc.bottom); if (m_bmps.size() < 4) { m_bmps = file_as_string(fil); // std::ofstream ofil("ot.bmp", std::ios::binary); // ofil<<m_bmps; mslog(_T("m_bmps: file size : %d"), m_bmps.size()); BITMAPFILEHEADER bmpfh; memcpy(&bmpfh, m_bmps.data(), sizeof(bmpfh)); mslog(_T("HEADER: sig: %c%c size: %u, offsets:%u -- reserved1:%u,reserved2:%u"), JRBIT1(bmpfh.bfType), JRBIT2(bmpfh.bfType), bmpfh.bfSize, bmpfh.bfOffBits, bmpfh.bfReserved1, bmpfh.bfReserved2 ); BITMAPINFOHEADER bmpinfo; memcpy(&bmpinfo, m_bmps.data() + sizeof(bmpfh), sizeof(bmpinfo)); mslog(_T("INFO: size: %u w: %d h: %d plms: %d bc: %d press: %u imgsize: %u ppmx: %d ppmy: %d clrs: %d impt: %d"), bmpinfo.biSize, bmpinfo.biWidth, bmpinfo.biHeight, bmpinfo.biPlanes, bmpinfo.biBitCount, bmpinfo.biCompression, bmpinfo.biSizeImage, bmpinfo.biXPelsPerMeter, bmpinfo.biYPelsPerMeter, bmpinfo.biClrUsed, bmpinfo.biClrImportant ); } BITMAPFILEHEADER bmpfh; memcpy(&bmpfh, m_bmps.data(), sizeof(bmpfh)); BITMAPINFOHEADER bmpinfo; memcpy(&bmpinfo, m_bmps.data() + sizeof(bmpfh), sizeof(bmpinfo)); const unsigned char *bits = (unsigned char *) (m_bmps.data() + bmpfh.bfOffBits); if (bmpinfo.biBitCount != 24) return; int linew = JRROUNDUPTO(bmpinfo.biWidth*3, 4); mslog(_T("LINEW: %d LINEW_RAW: %d"), linew, bmpinfo.biWidth*3); for(int i=0; i<bmpinfo.biHeight; ++i) { for (int j=0; j<bmpinfo.biWidth; ++j){ const unsigned char *clrs = bits + i*linew + j * 3; mdc.SetPixel(j, wnd_rc.bottom - i, RGB(clrs[2], clrs[1], clrs[0])); } } } std::string m_bmps;
win32的GUI编程有很多容易忘记、但是又很重要的东西。
比如BMP的行padding,RGB在文件中的排列。
在WTL中响应WM_PAINT时,没有用到begin/end paint时,
WM_TIMER会失效。