{"id":17483,"date":"2009-07-15T10:00:00","date_gmt":"2009-07-15T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/07\/15\/separating-the-metadata-from-the-dib-pixels-precalculating-the-bitmapinfo\/"},"modified":"2009-07-15T10:00:00","modified_gmt":"2009-07-15T10:00:00","slug":"separating-the-metadata-from-the-dib-pixels-precalculating-the-bitmapinfo","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090715-00\/?p=17483","title":{"rendered":"Separating the metadata from the DIB pixels: Precalculating the BITMAPINFO"},"content":{"rendered":"<p>\nLast time, we saw\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2009\/07\/14\/9832544.aspx\">\nthat you can use the <code>SetDIBitsToDevice<\/code> function\nto draw a DIB with an alternate color table without having\nto modify the <code>HBITMAP<\/code><\/a>.\nIn that version of the function, we selected the <code>HBITMAP<\/code>\ninto a device context in preparation for drawing from it,\nbut in fact that step isn&#8217;t necessary for drawing.\nIt was merely necessary to get the original color table\nso we could build our grayscale color table.\nIf you don&#8217;t care what the original colors are,\nthen you can skip that step.\nAnd even if you care what the old colors are,\nand if you assume that the colors don&#8217;t change,\nthen you only need to ask once.\n<\/p>\n<p>\nTo demonstrate, that\nall the work of building the <code>BITMAPINFO<\/code>\nstructure could have been done ahead of time,\nlet&#8217;s use this alternate version of our program:\n<\/p>\n<pre>\nHBITMAP g_hbm;\n<font COLOR=\"blue\">struct BITMAPINFO256 {\n BITMAPINFOHEADER bmiHeader;\n   RGBQUAD bmiColors[256];\n} g_bmiGray;\nvoid *g_pvBits;<\/font>\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n \/\/ change path as appropriate\n g_hbm = (HBITMAP)LoadImage(g_hinst,\n                      TEXT(\"C:\\\\Windows\\\\Gone Fishing.bmp\"),\n                      IMAGE_BITMAP, 0, 0,\n                      LR_CREATEDIBSECTION | LR_LOADFROMFILE);<\/font>\n <font COLOR=\"blue\">if (g_hbm) {\n  BITMAP bm;\n  if (GetObject(g_hbm, sizeof(bm), &amp;bm) == sizeof(bm) &amp;&amp;\n                bm.bmBits != NULL &amp;&amp;\n                bm.bmPlanes * bm.bmBitsPixel &lt;= 8) {\n   ZeroMemory(&amp;g_bmiGray, sizeof(g_bmiGray));\n   HDC hdc = CreateCompatibleDC(NULL);\n   if (hdc) {\n    HBITMAP hbmPrev = SelectBitmap(hdc, g_hbm);\n    UINT cColors = GetDIBColorTable(hdc, 0, 256, g_bmiGray.bmiColors);\n    for (UINT iColor = 0; iColor &lt; cColors; iColor++) {\n     BYTE b = (BYTE)((30 * g_bmiGray.bmiColors[iColor].rgbRed +\n                      59 * g_bmiGray.bmiColors[iColor].rgbGreen +\n                      11 * g_bmiGray.bmiColors[iColor].rgbBlue) \/ 100);\n     g_bmiGray.bmiColors[iColor].rgbRed   = b;\n     g_bmiGray.bmiColors[iColor].rgbGreen = b;\n     g_bmiGray.bmiColors[iColor].rgbBlue  = b;\n    }\n    g_bmiGray.bmiHeader.biSize        = sizeof(g_bmiGray.bmiHeader);\n    g_bmiGray.bmiHeader.biWidth       = bm.bmWidth;\n    g_bmiGray.bmiHeader.biHeight      = bm.bmHeight;\n    g_bmiGray.bmiHeader.biPlanes      = bm.bmPlanes;\n    g_bmiGray.bmiHeader.biBitCount    = bm.bmBitsPixel;\n    g_bmiGray.bmiHeader.biCompression = BI_RGB;\n    g_bmiGray.bmiHeader.biClrUsed     = cColors;\n    <font COLOR=\"red\">g_pvBits                          = bm.bmBits;<\/font>\n    DeleteDC(hdc);\n   }\n }<\/font>\n return TRUE;\n}\nvoid\nPaintContent(HWND hwnd, PAINTSTRUCT *pps)\n{\n <font COLOR=\"red\">if (g_pvBits) {<\/font>\n    <font COLOR=\"blue\">SetDIBitsToDevice(pps-&gt;hdc, 0, 0,\n                  g_bmiGray.bmiHeader.biWidth,\n                  g_bmiGray.bmiHeader.biHeight, 0, 0,\n                  0, g_bmiGray.bmiHeader.biHeight,\n                  <font COLOR=\"red\">g_pvBits<\/font>,\n                  (BITMAPINFO*)&amp;g_bmiGray, DIB_RGB_COLORS);\n }<\/font>\n}\n<\/pre>\n<p>\nI moved the blue code from <code>PaintContent<\/code>\nto <code>OnCreate<\/code> to demonstrate that pretty much all\nof the work we used to do in <code>PaintContent<\/code>\ncould have been done ahead of time.\nThe only other thing we had to do was save the pointer to the bits\nso we could pass them to <code>SetDIBitsToDevice<\/code>.\n(Of course, that pointer becomes invalid once the controlling\n<code>HBITMAP<\/code> is destroyed, so be careful!\nIn practice, you probably would be better off calling\n<code>GetObject<\/code> immediately before drawing\nto protect against the case that somebody deleted the bitmap\nout from under you.)\n<\/p>\n<p>\nNext time,\nwe&#8217;ll look at another operation we can perform\nwhen we have a <code>BITMAPINFO<\/code> and a collection of pixels.\n<\/p>\n<p>\n(Note that there are issues with this technique\nwhich will be taken up on Friday.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time, we saw that you can use the SetDIBitsToDevice function to draw a DIB with an alternate color table without having to modify the HBITMAP. In that version of the function, we selected the HBITMAP into a device context in preparation for drawing from it, but in fact that step isn&#8217;t necessary for drawing. [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-17483","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Last time, we saw that you can use the SetDIBitsToDevice function to draw a DIB with an alternate color table without having to modify the HBITMAP. In that version of the function, we selected the HBITMAP into a device context in preparation for drawing from it, but in fact that step isn&#8217;t necessary for drawing. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17483","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=17483"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17483\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=17483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}