Всем доброго времени суток! Никогда не работал до этого с WinGDI. Задача - рисовать рисунки и сохранять в BMP файлы. Компрессия RLE, формат - 8 бит на байт. рисунки в дальнейшем передаются по сети, поэтому размер критичен. Никаких 4х байт на точку нельзя допустить. рисунки не сложные, в основном из закрашенных прямоугольных областей, поэтому RLE дает хороший результат сжатия. Как делаю: Сначала hDC = CreateCompatibleDC() hBMP = CreateCompatibleBitmap(hDC, w, h) SelectObject(hDC, hBMP) потом рисую что надо Далее описываю BITMAPINFOHEADER: bih.biSize=sizeof(BITMAPINFOHEADER); bih.biWidth=w; bih.biHeight=h; bih.biPlanes=1; bih.biBitCount=8; bih.biCompression=BI_RLE8; bih.biSizeImage=0; bih.biXPelsPerMeter=0; bih.biYPelsPerMeter=0; bih.biClrUsed=0; bih.biClrImportant=0; В нем явно указываю, что хочу по 8 бит на точку. Затем получаю BITMAPINFO : GetDIBits(hDC, hBmp, 0, 0, NULL, &bi, DIB_RGB_COLORS); Теперь предполагаю, что в bi.bmiColors лежит палитра, размером 256, тип RGBQUAD Потом считываю нужные биты картинки : GetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, bmpData, &bi, DIB_RGB_COLORS); Заполняю BITMAPFILEHEADER. И пишу всё в файл: >>BITMAPFILEHEADER>>bi.bmiHeader>>bi.bmiColors>>bmpData Файл получается нормального формата, читается чем угодно. Но!!! на месте палитры, лежат какие-то непонятные данные, не похоже на цвета. И что бы я не рисовал, рисуется цветом 255! (если выключить компрессию, то видно, весь рисунок состоит из 0x00 и 0xFF). А в таблице на этих местах просто непонятные данные! отсюда рисунок состоит совсем не из тех цветов, которые я хотел использовать... Куда копать?? Как вообще можно преобразовать формат 32 бита на точку в 8 бит на точку? понятно, что потери будут. Но как искать подхлдящие цвета? Вообще на рисунки всего не больше 10ти разных цветов используется. Ниже привел код всего этого безобразия: Код (Text): int h=100; int w=200; BITMAPFILEHEADER hdr; BITMAPINFOHEADER bih; // bitmap info-header BITMAPINFO bi; //BITMAPINFOHEADER bih.biSize=sizeof(BITMAPINFOHEADER); bih.biWidth=w; bih.biHeight=h; bih.biPlanes=1; bih.biBitCount=8; //bih.biCompression=BI_RLE8; bih.biCompression=0; bih.biSizeImage=0; bih.biXPelsPerMeter=0; bih.biYPelsPerMeter=0; bih.biClrUsed=0; bih.biClrImportant=0; //BITMAPINFO bi.bmiHeader=bih; //Create Dc HDC hDC = CreateCompatibleDC(NULL); HBITMAP hBmp = CreateCompatibleBitmap(hDC, w, h); //BMP SelectObject(hDC, hBmp); //BRUSH hBRUSH = CreateSolidBrush(RGB(0x00,0x70,0x70)); SelectObject(hDC, hBRUSH); //Rectangle Rectangle(hDC, 40,40,80,80); //Text TextOut(hDC, 20, 20, "test",4); GetDIBits(hDC, hBmp, 0, 0, NULL, &bi, DIB_RGB_COLORS); BYTE * bmpData=(BYTE *)malloc(bi.bmiHeader.biSizeImage); GetDIBits(hDC, hBmp, 0, bi.bmiHeader.biHeight, bmpData, &bi, DIB_RGB_COLORS); HANDLE hf = CreateFile("c:\\img.bmp", GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); DWORD dwTmp; //BITMAPFILEHEADER hdr.bfSize=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*(1 << bi.bmiHeader.biBitCount) + bi.bmiHeader.biSizeImage; hdr.bfType=0x4D42; hdr.bfReserved1=0; hdr.bfReserved2=0; hdr.bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*(1 << bi.bmiHeader.biBitCount); WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL); WriteFile(hf, (LPVOID) &bi.bmiHeader, sizeof(BITMAPINFOHEADER), (LPDWORD) &dwTmp, NULL); WriteFile(hf, (LPVOID) bi.bmiColors, sizeof(RGBQUAD) * (1 << bi.bmiHeader.biBitCount), (LPDWORD) &dwTmp, NULL); WriteFile(hf, (LPSTR) bmpData, bi.bmiHeader.biSizeImage, (LPDWORD) &dwTmp,NULL); // Close the .BMP file. CloseHandle(hf);
Может в другую ветку кинуть? Или форум другой. Кстати, кто знает форумы похожего содержания за бугром???
Советую посмотреть как это реализует сам майкросовт - в примерах SDK есть ViewDIB, она как раз такое и делает.
Вот этот код я считаю неверным. Коварная ошибка скрыта в нем. Код (Text): HDC hDC = CreateCompatibleDC(NULL); HBITMAP hBmp = CreateCompatibleBitmap(hDC, w, h); Попробуй след: Код (Text): HDC sDC = GetDC (0); HDC hDC = CreateCompatibleDC(sDC); HBITMAP hBmp = CreateCompatibleBitmap(sDC, w, h); ReleaseDC (0, sDC); Фишка, в том что у контекста устройства, пока ты его не привязал к определенному растру, уже есть стандартный растр, который (из экономии?) собой представляет монохромную картинку размером 1х1 пиксель. Используя этот контекст, в качестве образца для создания растра требуемых размеров, ты фактически заказываешь себе монохромный растр.
Span Как вообще можно преобразовать формат 32 бита на точку в 8 бит на точку? Цитат из Feng Yuan. Windows Graphics Programming Win32 GDI and DirectDraw (R). 13.6 BITMAP COLOR-DEPTH REDUCTION: "Now that we have a good algorithm to find the “optimal” palette of a bitmap, the next fun thing to try is reducing high-color or bitmap-color bitmaps to index-based bitmaps, or generally to reduce the color depth of a bitmap. For example, we can convert a true color image to an 8-bpp image, reducing it to one-third of its original size plus any gain from RLE compression. We can also convert an 8-bpp to a 4-bpp image." Файл получается нормального формата. Я не встречался с RLE-сжатыми картинками. Можешь прицепить сюда?
Если не секрет, это должно быть в БМПшнике? Код (Text): C:\WINDOWS\WinSxs\ Microsoft.Windows.SystemCompatible,processorArchitecture="x86",publicKeyToken="6595b64144ccf1df",type="win32",version="5b?