{"id":17463,"date":"2009-07-16T10:00:00","date_gmt":"2009-07-16T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/07\/16\/separating-the-metadata-from-the-dib-pixels-changing-the-raster-operation\/"},"modified":"2009-07-16T10:00:00","modified_gmt":"2009-07-16T10:00:00","slug":"separating-the-metadata-from-the-dib-pixels-changing-the-raster-operation","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20090716-00\/?p=17463","title":{"rendered":"Separating the metadata from the DIB pixels: Changing the raster operation"},"content":{"rendered":"<p>\nFor a few days now, we&#8217;ve\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2009\/07\/14\/9832544.aspx\">\nused the <code>SetDIBitsToDevice<\/code> function\nin conjunction with a precomputed <code>BITMAPINFO<\/code>\nto draw a DIB with an alternate color table<\/a>\nwithout modifying the <code>HBITMAP<\/code><\/a>.\n<\/p>\n<p>\nThe <code>SetDIBitsToDevice<\/code> function operates like\na <code>BitBlt<\/code> with raster operation <code>SRCCOPY<\/code>.\nIf you want another raster operation, you can use\n<code>StretchDIBits<\/code>, which has a final raster operation parameter.\nDespite its name, you don&#8217;t have to stretch with <code>StretchDIBits<\/code>.\nJust pass a source and destination of equal size, and you&#8217;ve performed\na NOP stretch, but you get the benefit of the raster operation.\n<\/p>\n<pre>\nvoid\nPaintContent(HWND hwnd, PAINTSTRUCT *pps)\n{\n if (g_pvBits) {\n    <font COLOR=\"blue\">StretchDIBits<\/font>(pps-&gt;hdc, 0, 0,\n                      g_bmiGray.bmiHeader.biWidth,\n                      g_bmiGray.bmiHeader.biHeight, 0, 0,\n                      <font COLOR=\"blue\">g_bmiGray.bmiHeader.biWidth,\n                      g_bmiGray.bmiHeader.biHeight,<\/font>\n                      g_pvBits,\n                     (BITMAPINFO*)&amp;g_bmiGray, DIB_RGB_COLORS,\n                      <font COLOR=\"blue\">NOTSRCCOPY<\/font>);\n }\n}\n<\/pre>\n<p>\nI changed the call from <code>SetDIBitsToDevice<\/code>\nto <code>StretchDIBits<\/code>,\nsetting the source and destination rectangles to the same size\n(so no actual stretching occurs),\nand specifying a raster operation of <code>NOTSRCCOPY<\/code>\nso the result on screen is a negative grayscale.\n<\/p>\n<p>\nSome people may object to performing a stretch operation\nand requesting no stretching, but that&#8217;s perfectly fine.\nAt least in this case, GDI is not stupid.\nIf you ask it to perform a stretch operation\nbut pass parameters that don&#8217;t do any stretching, it will\noptimize this to a non-stretching operation.\nYou don&#8217;t need to hand-optimize it.\nInstead of writing\n<\/p>\n<pre>\nif (cxSrc == cxDst &amp;&amp; cySrc == cyDst) {\n BitBlt(hdc, xDst, yDst, cxDst, cyDst,\n        hdcSrc, xSrc, ySrc, dwRop);\n} else {\n StretchBlt(hdc, xDst, yDst, cxDst, cyDst,\n            hdcSrc, xSrc, ySrc, cxSrc, cySrc, dwRop);\n}\n<\/pre>\n<p>\n&#8230; just go straight to the <code>StretchBlt<\/code>:\n<\/p>\n<pre>\nStretchBlt(hdc, xDst, yDst, cxDst, cyDst,\n           hdcSrc, xSrc, ySrc, cxSrc, cySrc, dwRop);\n<\/pre>\n<p>\nThe <code>StretchBlt<\/code> function will convert the\noperation to a <code>BitBlt<\/code> if <code>cxSrc == cxDst<\/code>\nand <code>cySrc == cyDst<\/code>.\nYou don&#8217;t have to hand-optimize it.\nThe GDI folks hand-optimized it for you.\n<\/p>\n<p>\n(In fact, for a long time,\nthe <code>SetDIBitsToDevice<\/code> function simply called\n<code>StretchDIBits<\/code>, saying that the input and\noutput rectangles were the same size,\nand <code>StretchDIBits<\/code> detected the absence of stretching\nand used an optimized code path.\nConsequently,\n&#8220;optimizating&#8221; the code by calling\n<code>SetDIBitsToDevice<\/code>\nwas actually a pessimization.)<\/p>\n<p>\nBack to <code>StretchDIBits<\/code>.\nSo far, we&#8217;ve been drawing the entire bitmap at the upper left\ncorner of the destination device context.\nThe last remaining feature of <code>BitBlt<\/code> is\nthe ability to draw a rectangular chunk of a source bitmap\nat a destination location,\nso let&#8217;s do that.\nWe&#8217;ll draw the bottom right corner of the bitmap in\nthe bottom right corner of the window,\nwith negative colors,\nand <i>just to show we can<\/i>, we&#8217;ll also stretch it.\n<\/p>\n<pre>\nvoid\nPaintContent(HWND hwnd, PAINTSTRUCT *pps)\n{\n if (g_pvBits) {\n  <font COLOR=\"blue\">RECT rc;\n  GetClientRect(hwnd, &amp;rc);\n  int cxChunk = g_bmiGray.bmiHeader.biWidth \/ 2;\n  int cyChunk = g_bmiGray.bmiHeader.biHeight \/ 2;\n  StretchDIBits(pps-&gt;hdc, rc.right - cxChunk * 2,\n                rc.bottom - cxChunk * 2,\n                cxChunk * 2, cyChunk * 2,\n                g_bmiGray.bmiHeader.biWidth - cxChunk,\n                g_bmiGray.bmiHeader.biHeight - cyChunk,\n                cxChunk, cyChunk,\n                g_pvBits, (BITMAPINFO*)&amp;g_bmiGray,\n                DIB_RGB_COLORS, NOTSRCCOPY);<\/font>\n }\n}\n<\/pre>\n<p>\nSo far, we&#8217;ve been operating on DIB pixels that are\nheld inside a DIB section.\nBut there&#8217;s no requirement that the bits passed to\n<code>StretchDIBits<\/code> come from an actual DIB section.\nWe&#8217;ll look at the total disembodiment of DIBs next time,\nas well as looking at some unexpected consequences of all our game-playing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For a few days now, we&#8217;ve used the SetDIBitsToDevice function in conjunction with a precomputed BITMAPINFO to draw a DIB with an alternate color table without modifying the HBITMAP. The SetDIBitsToDevice function operates like a BitBlt with raster operation SRCCOPY. If you want another raster operation, you can use StretchDIBits, which has a final raster [&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-17463","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>For a few days now, we&#8217;ve used the SetDIBitsToDevice function in conjunction with a precomputed BITMAPINFO to draw a DIB with an alternate color table without modifying the HBITMAP. The SetDIBitsToDevice function operates like a BitBlt with raster operation SRCCOPY. If you want another raster operation, you can use StretchDIBits, which has a final raster [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17463","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=17463"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/17463\/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=17463"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=17463"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=17463"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}