{"id":17503,"date":"2009-07-14T10:00:00","date_gmt":"2009-07-14T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/07\/14\/the-fun-and-profit-of-manipulating-the-dib-color-table-can-be-done-without-having-to-modify-it\/"},"modified":"2009-07-14T10:00:00","modified_gmt":"2009-07-14T10:00:00","slug":"the-fun-and-profit-of-manipulating-the-dib-color-table-can-be-done-without-having-to-modify-it","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090714-00\/?p=17503","title":{"rendered":"The fun and profit of manipulating the DIB color table can be done without having to modify it"},"content":{"rendered":"<p>\nIf I were\n<a HREF=\"http:\/\/blogs.msdn.com\/michkap\/\">\nMichael Kaplan<\/a>,\nI&#8217;d have a more clever title like\n<i>I&#8217;m not touching you!<\/i>\nor <i>Look but don&#8217;t touch<\/i>\nor maybe <i>Looking at a DIB through <code>BITMAPINFO<\/code>-colored\nglasses<\/i>.\n<\/p>\n<p>\nWe saw\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/11\/15\/1081320.aspx\">\nsome time ago<\/a>\nthat you can manipulate the DIB color table to perform wholesale color\nremapping.\nBut in fact you can do this even without modifying the DIB color table,\nwhich is a handy trick if you want to do color remapping but you\ndon&#8217;t want to change the bitmap itself.\nFor example,\nthe bitmap is not one that is under your control\n(so you shouldn&#8217;t be modifying it),\nor the bitmap might be in use on multiple threads\n(so modifying it will result in race conditions).\n<\/p>\n<p>\nLet&#8217;s demonstrate this technique by converting the &#8220;Gone Fishing&#8221; bitmap\nto grayscale, but doing so without actually modifying the bitmap.\nAs always, we start with our\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2003\/07\/23\/54576.aspx\">\nscratch program<\/a>\nand make the following changes:\n<\/p>\n<pre>\n<font COLOR=\"blue\">HBITMAP g_hbm;<\/font>\n<\/font>\nBOOL\nOnCreate(HWND hwnd, LPCREATESTRUCT lpcs)\n{\n<font COLOR=\"blue\"> \/\/ 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 return TRUE;\n}\nvoid\nOnDestroy(HWND hwnd)\n{\n <font COLOR=\"blue\">if (g_hbm) DeleteObject(g_hbm);<\/font>\n PostQuitMessage(0);\n}\nvoid\nPaintContent(HWND hwnd, PAINTSTRUCT *pps)\n{\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.<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/12\/01\/273018.aspx\">bmPlanes<\/a> * bm.bmBitsPixel &lt;= 8) {\n   struct BITMAPINFO256 {\n    BITMAPINFOHEADER bmiHeader;\n    RGBQUAD bmiColors[256];\n   } bmiGray;\n   <a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2005\/06\/28\/433341.aspx\">ZeroMemory<\/a>(&amp;bmiGray, sizeof(bmiGray));\n   HDC hdc = CreateCompatibleDC(NULL);\n   if (hdc) {\n    HBITMAP hbmPrev = SelectBitmap(hdc, g_hbm);\n    UINT cColors = GetDIBColorTable(hdc, 0, 256, bmiGray.bmiColors);\n    for (UINT iColor = 0; iColor &lt; cColors; iColor++) {\n     BYTE b = (BYTE)((<a HREF=\"http:\/\/en.wikipedia.org\/wiki\/Grayscale#Converting_color_to_grayscale\">30<\/a> * bmiGray.bmiColors[iColor].rgbRed +\n                      <a HREF=\"http:\/\/en.wikipedia.org\/wiki\/Grayscale#Converting_color_to_grayscale\">59<\/a> * bmiGray.bmiColors[iColor].rgbGreen +\n                      <a HREF=\"http:\/\/en.wikipedia.org\/wiki\/Grayscale#Converting_color_to_grayscale\">11<\/a> * bmiGray.bmiColors[iColor].rgbBlue) \/ 100);\n     bmiGray.bmiColors[iColor].rgbRed   = b;\n     bmiGray.bmiColors[iColor].rgbGreen = b;\n     bmiGray.bmiColors[iColor].rgbBlue  = b;\n    }\n    bmiGray.bmiHeader.biSize        = sizeof(bmiGray.bmiHeader);\n    bmiGray.bmiHeader.biWidth       = bm.bmWidth;\n    bmiGray.bmiHeader.biHeight      = bm.bmHeight;\n    bmiGray.bmiHeader.biPlanes      = bm.bmPlanes;\n    bmiGray.bmiHeader.biBitCount    = bm.bmBitsPixel;\n    bmiGray.bmiHeader.biCompression = BI_RGB;\n    bmiGray.bmiHeader.biClrUsed     = cColors;\n    SetDIBitsToDevice(pps-&gt;hdc, 0, 0,\n                      bmiGray.bmiHeader.biWidth,\n                      bmiGray.bmiHeader.biHeight, 0, 0,\n                      0, bmiGray.bmiHeader.biHeight,\n                      bm.bmBits,\n                     (BITMAPINFO*)&amp;bmiGray, DIB_RGB_COLORS);\n    BitBlt(pps-&gt;hdc, bm.bmWidth, 0, bm.bmWidth, bm.bmHeight,\n           hdc, 0, 0, SRCCOPY);\n    SelectBitmap(hdc, hbmPrev);\n    DeleteDC(hdc);\n   }\n  }\n }<\/font>\n}\n<\/pre>\n<p>\nThings start off innocently enough, loading the bitmap into a\nDIB section for use during painting.\n<\/p>\n<p>\nWe do our work at paint time.\nFirst, we confirm\nthat we indeed have a DIB section and that it is 8bpp or lower,\nbecause bitmaps at higher than 8bpp do not use color tables.\n<\/p>\n<p>\nWe then select the bitmap into a DC so we can call\n<code>GetDIBColorTable<\/code> to get its current color table.\n(This is the only step that\nrequires the bitmap to be selected into a device context.)\nWe then edit the color table to convert each color to\nits grayscale equivalent.\n<\/p>\n<p>\nFinally, we fill in the <code>BITMAPINFO<\/code> structure\nwith the description of the bitmap bits,\nand then we call <code>SetDIBitsToDevice<\/code> to send\nthe pixels to the destination DC.\n<\/p>\n<p>\nJust for good measure, we also <code>BitBlt<\/code> the\noriginal unmodified bitmap,\nto prove that the original bitmap is intact and unchanged.\n<\/p>\n<p>\nThis mini-program is really just a stepping stone to other\nthings you can do with this technique of separating the\nmetadata (the <code>BITMAPINFO<\/code>) from the pixels.\nWe&#8217;ll continue our investigations tomorrow.\n<\/p>\n<p>\n(Before you all run out and use this technique everywhere you can imagine,\nwait for the remarks in Friday&#8217;s installment.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If I were Michael Kaplan, I&#8217;d have a more clever title like I&#8217;m not touching you! or Look but don&#8217;t touch or maybe Looking at a DIB through BITMAPINFO-colored glasses. We saw some time ago that you can manipulate the DIB color table to perform wholesale color remapping. But in fact you can do this [&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-17503","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>If I were Michael Kaplan, I&#8217;d have a more clever title like I&#8217;m not touching you! or Look but don&#8217;t touch or maybe Looking at a DIB through BITMAPINFO-colored glasses. We saw some time ago that you can manipulate the DIB color table to perform wholesale color remapping. But in fact you can do this [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17503","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=17503"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17503\/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=17503"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17503"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17503"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}