void metric_generate_coeffs_for_subimage (coeffs_union_t *coeffs, bitmap_t *bitmap, int x, int y, int width, int height, metric_t *metric) { if (metric->kind == METRIC_SUBPIXEL) { bitmap_t *sub_bitmap, *scaled_bitmap; sub_bitmap = bitmap_sub(bitmap, x, y, width, height); assert(sub_bitmap != 0); //bitmap_write(sub_bitmap, "/tmp/sub.png"); scaled_bitmap = bitmap_scale(sub_bitmap, NUM_SUBPIXEL_ROWS_COLS, NUM_SUBPIXEL_ROWS_COLS, FILTER_MITCHELL); assert(scaled_bitmap != 0); bitmap_free(sub_bitmap); //bitmap_write(scaled_bitmap, "/tmp/scaled.png"); assert(scaled_bitmap->color == COLOR_RGB_8); assert(scaled_bitmap->pixel_stride == NUM_CHANNELS); assert(scaled_bitmap->row_stride == NUM_SUBPIXEL_ROWS_COLS * NUM_CHANNELS); color_convert_rgb_pixels(coeffs->subpixel.subpixels, scaled_bitmap->data, NUM_SUBPIXELS, metric->color_space); bitmap_free(scaled_bitmap); } else assert(0); }
/* blunt force truma way of achiving alpha blended plotting */ static bool plot_alpha_bitmap(HDC hdc, struct bitmap *bitmap, int x, int y, int width, int height) { #ifdef WINDOWS_GDI_ALPHA_WORKED BLENDFUNCTION blnd = { AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA }; HDC bmihdc; bool bltres; bmihdc = CreateCompatibleDC(hdc); SelectObject(bmihdc, bitmap->windib); bltres = AlphaBlend(hdc, x, y, width, height, bmihdc, 0, 0, bitmap->width, bitmap->height, blnd); DeleteDC(bmihdc); return bltres; #else HDC Memhdc; BITMAPINFOHEADER bmih; int v, vv, vi, h, hh, width4, transparency; unsigned char alpha; bool isscaled = false; /* set if the scaled bitmap requires freeing */ BITMAP MemBM; BITMAPINFO *bmi; HBITMAP MemBMh; PLOT_LOG("%p bitmap %d,%d width %d height %d", bitmap, x, y, width, height); PLOT_LOG("clipped %ld,%ld to %ld,%ld",plot_clip.left, plot_clip.top, plot_clip.right, plot_clip.bottom); Memhdc = CreateCompatibleDC(hdc); if (Memhdc == NULL) { return false; } if ((bitmap->width != width) || (bitmap->height != height)) { PLOT_LOG("scaling from %d,%d to %d,%d", bitmap->width, bitmap->height, width, height); bitmap = bitmap_scale(bitmap, width, height); if (bitmap == NULL) return false; isscaled = true; } bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) + (bitmap->width * bitmap->height * 4)); if (bmi == NULL) { DeleteDC(Memhdc); return false; } MemBMh = CreateCompatibleBitmap(hdc, bitmap->width, bitmap->height); if (MemBMh == NULL){ free(bmi); DeleteDC(Memhdc); return false; } /* save 'background' data for alpha channel work */ SelectObject(Memhdc, MemBMh); BitBlt(Memhdc, 0, 0, bitmap->width, bitmap->height, hdc, x, y, SRCCOPY); GetObject(MemBMh, sizeof(BITMAP), &MemBM); bmih.biSize = sizeof(bmih); bmih.biWidth = bitmap->width; bmih.biHeight = bitmap->height; bmih.biPlanes = 1; bmih.biBitCount = 32; bmih.biCompression = BI_RGB; bmih.biSizeImage = 4 * bitmap->height * bitmap->width; bmih.biXPelsPerMeter = 3600; /* 100 dpi */ bmih.biYPelsPerMeter = 3600; bmih.biClrUsed = 0; bmih.biClrImportant = 0; bmi->bmiHeader = bmih; GetDIBits(hdc, MemBMh, 0, bitmap->height, bmi->bmiColors, bmi, DIB_RGB_COLORS); /* then load 'foreground' bits from bitmap->pixdata */ width4 = bitmap->width * 4; for (v = 0, vv = 0, vi = (bitmap->height - 1) * width4; v < bitmap->height; v++, vv += bitmap->width, vi -= width4) { for (h = 0, hh = 0; h < bitmap->width; h++, hh += 4) { alpha = bitmap->pixdata[vi + hh + 3]; /* multiplication of alpha value; subject to profiling could be optional */ if (alpha == 0xFF) { bmi->bmiColors[vv + h].rgbBlue = bitmap->pixdata[vi + hh + 2]; bmi->bmiColors[vv + h].rgbGreen = bitmap->pixdata[vi + hh + 1]; bmi->bmiColors[vv + h].rgbRed = bitmap->pixdata[vi + hh]; } else if (alpha > 0) { transparency = 0x100 - alpha; bmi->bmiColors[vv + h].rgbBlue = (bmi->bmiColors[vv + h].rgbBlue * transparency + (bitmap->pixdata[vi + hh + 2]) * alpha) >> 8; bmi->bmiColors[vv + h].rgbGreen = (bmi->bmiColors[vv + h]. rgbGreen * transparency + (bitmap->pixdata[vi + hh + 1]) * alpha) >> 8; bmi->bmiColors[vv + h].rgbRed = (bmi->bmiColors[vv + h].rgbRed * transparency + bitmap->pixdata[vi + hh] * alpha) >> 8; } } }
static bool bitmap(int x, int y, int width, int height, struct bitmap *bitmap, colour bg, bitmap_flags_t flags) { #if NSWS_PLOT_DEBUG LOG(("%p bitmap %d,%d width %d height %d", current_hwnd, x, y, width, height)); #endif if (bitmap == NULL) return false; HDC hdc = doublebuffering ? bufferdc : GetDC(current_hwnd); if (hdc == NULL) { return false; } RECT *cliprect = gui_window_clip_rect(current_gui); if (cliprect == NULL) cliprect = &localhistory_clip; HRGN clipregion = CreateRectRgnIndirect(cliprect); if (clipregion == NULL) { if (!doublebuffering) ReleaseDC(current_hwnd, hdc); return false; } HDC Memhdc = CreateCompatibleDC(hdc); if (Memhdc == NULL) { DeleteObject(clipregion); if (!doublebuffering) ReleaseDC(current_hwnd, hdc); return false; } BITMAPINFOHEADER bmih; RECT r; int v, vv, vi, h, hh, width4, transparency; unsigned char alpha; bool modifying = false; SelectClipRgn(hdc, clipregion); if ((bitmap->width != width) || (bitmap->height != height)) { bitmap = bitmap_scale(bitmap, width, height); if (bitmap == NULL) return false; modifying = true; } if ((flags & BITMAPF_REPEAT_X) || (flags & BITMAPF_REPEAT_Y)) { struct bitmap *prebitmap = bitmap_pretile(bitmap, cliprect->right - x, cliprect->bottom - y, flags); if (prebitmap == NULL) return false; if (modifying) { free(bitmap->pixdata); free(bitmap); } modifying = true; bitmap = prebitmap; } BITMAP MemBM; BITMAPINFO *bmi = (BITMAPINFO *) malloc(sizeof(BITMAPINFOHEADER) + (bitmap->width * bitmap->height * 4)); if (bmi == NULL) { DeleteObject(clipregion); DeleteDC(Memhdc); if (!doublebuffering) ReleaseDC(current_hwnd, hdc); return false; } HBITMAP MemBMh = CreateCompatibleBitmap( hdc, bitmap->width, bitmap->height); if (MemBMh == NULL){ DeleteObject(clipregion); free(bmi); DeleteDC(Memhdc); if (!doublebuffering) ReleaseDC(current_hwnd, hdc); return false; } /* save 'background' data for alpha channel work */ SelectObject(Memhdc, MemBMh); BitBlt(Memhdc, 0, 0, bitmap->width, bitmap->height, hdc, x, y, SRCCOPY); GetObject(MemBMh, sizeof(BITMAP), &MemBM); bmih.biSize = sizeof(bmih); bmih.biWidth = bitmap->width; bmih.biHeight = bitmap->height; bmih.biPlanes = 1; bmih.biBitCount = 32; bmih.biCompression = BI_RGB; bmih.biSizeImage = 4 * bitmap->height * bitmap->width; bmih.biXPelsPerMeter = 3600; /* 100 dpi */ bmih.biYPelsPerMeter = 3600; bmih.biClrUsed = 0; bmih.biClrImportant = 0; bmi->bmiHeader = bmih; GetDIBits(hdc, MemBMh, 0, bitmap->height, bmi->bmiColors, bmi, DIB_RGB_COLORS); /* then load 'foreground' bits from bitmap->pixdata */ width4 = bitmap->width * 4; for (v = 0, vv = 0, vi = (bitmap->height - 1) * width4; v < bitmap->height; v++, vv += bitmap->width, vi -= width4) { for (h = 0, hh = 0; h < bitmap->width; h++, hh += 4) { alpha = bitmap->pixdata[vi + hh + 3]; /* multiplication of alpha value; subject to profiling could be optional */ if (alpha == 0xFF) { bmi->bmiColors[vv + h].rgbBlue = bitmap->pixdata[vi + hh + 2]; bmi->bmiColors[vv + h].rgbGreen = bitmap->pixdata[vi + hh + 1]; bmi->bmiColors[vv + h].rgbRed = bitmap->pixdata[vi + hh]; } else if (alpha > 0) { transparency = 0x100 - alpha; bmi->bmiColors[vv + h].rgbBlue = (bmi->bmiColors[vv + h].rgbBlue * transparency + (bitmap->pixdata[vi + hh + 2]) * alpha) >> 8; bmi->bmiColors[vv + h].rgbGreen = (bmi->bmiColors[vv + h]. rgbGreen * transparency + (bitmap->pixdata[vi + hh + 1]) * alpha) >> 8; bmi->bmiColors[vv + h].rgbRed = (bmi->bmiColors[vv + h].rgbRed * transparency + bitmap->pixdata[vi + hh] * alpha) >> 8; } /* alternative simple 2/3 stage alpha value handling */ /* if (bitmap->pixdata[vi + hh + 3] > 0xAA) { bmi->bmiColors[vv + h].rgbBlue = bitmap->pixdata[vi + hh + 2]; bmi->bmiColors[vv + h].rgbGreen = bitmap->pixdata[vi + hh + 1]; bmi->bmiColors[vv + h].rgbRed = bitmap->pixdata[vi + hh]; } else if (bitmap->pixdata[vi + hh + 3] > 0x70){ bmi->bmiColors[vv + h].rgbBlue = (bmi->bmiColors[vv + h].rgbBlue + bitmap->pixdata[vi + hh + 2]) / 2; bmi->bmiColors[vv + h].rgbRed = (bmi->bmiColors[vv + h].rgbRed + bitmap->pixdata[vi + hh]) / 2; bmi->bmiColors[vv + h].rgbGreen = (bmi->bmiColors[vv + h].rgbGreen + bitmap->pixdata[vi + hh + 1]) / 2; } else if (bitmap->pixdata[vi + hh + 3] > 0x30){ bmi->bmiColors[vv + h].rgbBlue = (bmi->bmiColors[vv + h].rgbBlue * 3 + bitmap->pixdata[vi + hh + 2]) / 4; bmi->bmiColors[vv + h].rgbRed = (bmi->bmiColors[vv + h].rgbRed * 3 + bitmap->pixdata[vi + hh]) / 4; bmi->bmiColors[vv + h].rgbGreen = (bmi->bmiColors[vv + h].rgbGreen * 3 + bitmap->pixdata[vi + hh + 1]) / 4; } */ } }