static HBITMAP StretchBitmap()

in shell/browser/notifications/win/win32_desktop_notifications/toast.cc [68:198]


static HBITMAP StretchBitmap(HBITMAP bitmap, unsigned width, unsigned height) {
  // We use StretchBlt for the scaling, but that discards the alpha channel.
  // So we first create a separate grayscale bitmap from the alpha channel,
  // scale that separately, and copy it back to the scaled color bitmap.

  BITMAP bm;
  if (!GetObject(bitmap, sizeof(bm), &bm))
    return NULL;

  if (width == 0 || height == 0)
    return NULL;

  HBITMAP result_bitmap = NULL;

  HDC hdc_screen = GetDC(NULL);

  HBITMAP alpha_src_bitmap;
  {
    BITMAPINFOHEADER bmi = {sizeof(BITMAPINFOHEADER)};
    bmi.biWidth = bm.bmWidth;
    bmi.biHeight = bm.bmHeight;
    bmi.biPlanes = bm.bmPlanes;
    bmi.biBitCount = bm.bmBitsPixel;
    bmi.biCompression = BI_RGB;

    void* alpha_src_bits;
    alpha_src_bitmap =
        CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&bmi),
                         DIB_RGB_COLORS, &alpha_src_bits, NULL, 0);

    if (alpha_src_bitmap) {
      if (GetDIBits(hdc_screen, bitmap, 0, 0, 0,
                    reinterpret_cast<BITMAPINFO*>(&bmi), DIB_RGB_COLORS) &&
          bmi.biSizeImage > 0 && (bmi.biSizeImage % 4) == 0) {
        auto* buf = reinterpret_cast<BYTE*>(
            _aligned_malloc(bmi.biSizeImage, sizeof(DWORD)));

        if (buf) {
          GetDIBits(hdc_screen, bitmap, 0, bm.bmHeight, buf,
                    reinterpret_cast<BITMAPINFO*>(&bmi), DIB_RGB_COLORS);

          const DWORD* src = reinterpret_cast<DWORD*>(buf);
          const DWORD* end = reinterpret_cast<DWORD*>(buf + bmi.biSizeImage);

          BYTE* dest = reinterpret_cast<BYTE*>(alpha_src_bits);

          for (; src != end; ++src, ++dest) {
            BYTE a = *src >> 24;
            *dest++ = a;
            *dest++ = a;
            *dest++ = a;
          }

          _aligned_free(buf);
        }
      }
    }
  }

  if (alpha_src_bitmap) {
    BITMAPINFOHEADER bmi = {sizeof(BITMAPINFOHEADER)};
    bmi.biWidth = width;
    bmi.biHeight = height;
    bmi.biPlanes = 1;
    bmi.biBitCount = 32;
    bmi.biCompression = BI_RGB;

    void* color_bits;
    auto* color_bitmap =
        CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&bmi),
                         DIB_RGB_COLORS, &color_bits, NULL, 0);

    void* alpha_bits;
    auto* alpha_bitmap =
        CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&bmi),
                         DIB_RGB_COLORS, &alpha_bits, NULL, 0);

    HDC hdc = CreateCompatibleDC(NULL);
    HDC hdc_src = CreateCompatibleDC(NULL);

    if (color_bitmap && alpha_bitmap && hdc && hdc_src) {
      SetStretchBltMode(hdc, HALFTONE);

      // resize color channels
      SelectObject(hdc, color_bitmap);
      SelectObject(hdc_src, bitmap);
      StretchBlt(hdc, 0, 0, width, height, hdc_src, 0, 0, bm.bmWidth,
                 bm.bmHeight, SRCCOPY);

      // resize alpha channel
      SelectObject(hdc, alpha_bitmap);
      SelectObject(hdc_src, alpha_src_bitmap);
      StretchBlt(hdc, 0, 0, width, height, hdc_src, 0, 0, bm.bmWidth,
                 bm.bmHeight, SRCCOPY);

      // flush before touching the bits
      GdiFlush();

      // apply the alpha channel
      auto* dest = reinterpret_cast<BYTE*>(color_bits);
      auto* src = reinterpret_cast<const BYTE*>(alpha_bits);
      auto* end = src + (width * height * 4);
      while (src != end) {
        dest[3] = src[0];
        dest += 4;
        src += 4;
      }

      // create the resulting bitmap
      result_bitmap =
          CreateDIBitmap(hdc_screen, &bmi, CBM_INIT, color_bits,
                         reinterpret_cast<BITMAPINFO*>(&bmi), DIB_RGB_COLORS);
    }

    if (hdc_src)
      DeleteDC(hdc_src);
    if (hdc)
      DeleteDC(hdc);

    if (alpha_bitmap)
      DeleteObject(alpha_bitmap);
    if (color_bitmap)
      DeleteObject(color_bitmap);

    DeleteObject(alpha_src_bitmap);
  }

  ReleaseDC(NULL, hdc_screen);

  return result_bitmap;
}