WriteableBitmapEx alpha blend color issue - wpf

I'm trying to use WriteableBitmap with the WriteableBitmapEx extension methods. The code sample is below along with two screenshots. The first screenshot is what my code generates and the second what I'm expecting (hand drawn via Paint.Net).
Am I using WriteableBitmapEx incorrectly, misunderstanding how it works or is it a bug?
This is on .Net 4.6.1 and WriteableBitmapEx 1.6.2.
public MainWindow()
{
InitializeComponent();
_bitmap = BitmapFactory.New(1000, 1000);
_bitmap.FillRectangle(0,0,1000,1000, ColorToInt(Colors.White), true);
_bitmap.FillRectangle(100, 100, 500, 500, ColorToInt(_color), true);
_bitmap.FillRectangle(150, 150, 550, 550, ColorToInt(_color), true);
_bitmap.FillRectangle(200, 200, 600, 600, ColorToInt(_color), true);
_bitmap.FillRectangle(250, 250, 650, 650, ColorToInt(_color), true);
_bitmap.FillRectangle(300, 300, 700, 700, ColorToInt(_color), true);
_bitmap.FillRectangle(350, 350, 750, 750, ColorToInt(_color), true);
_bitmap.FillRectangle(400, 400, 800, 800, ColorToInt(_color), true);
Image1.Source = _bitmap;
}
private readonly Color _color = Color.FromArgb(25, 0, 0, 255);
private WriteableBitmap _bitmap;
private int ColorToInt(Color c)
{
return c.A << 24 | c.R << 16 | c.G << 8 | c.B;
}

The WriteableBitmap uses pre-multiplied alpha internally, so when you convert a color you have to take that into account and multiply your color channels with alpha.
You can simply use the ConvertColor method that comes with WBX or roll your own similar to this:
public static int ConvertColor(Color color)
{
var col = 0;
if (color.A != 0)
{
var a = color.A + 1;
col = (color.A << 24)
| ((byte)((color.R * a) >> 8) << 16)
| ((byte)((color.G * a) >> 8) << 8)
| ((byte)((color.B * a) >> 8));
}
return col;
}

Related

When i can access to SDL_Rendrerer after maximizing window?

I try to redraw window only when is need, but when window is resize in a hop (for example maximize), SDL_Renderer is not usable in new size some time after action.
Here is my simple example code:
#include <SDL2/SDL.h>
bool redraw = true;
void draw(SDL_Renderer* renderer, SDL_Rect& rect)
{
SDL_SetRenderDrawColor(renderer, 0, 0, 50, 0xFF);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 90, 90, 90, 0xFF);
SDL_RenderDrawLine(renderer, 0, 0, rect.w, rect.h);
SDL_RenderPresent(renderer);
redraw = false;
}
SDL_Rect resize(const SDL_Event& event)
{
int win_w = (int) event.window.data1;
int win_h = (int) event.window.data2;
SDL_Rect rect = {0, 0, win_w, win_h};
redraw = true;
return rect;
}
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Maximize test",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 450, 0);
SDL_SetWindowResizable(window, SDL_TRUE);
SDL_Renderer* renderer = SDL_CreateRenderer(
window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool running = true;
SDL_Event event;
SDL_Rect rect = {0, 0, 800, 450};
while (running) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_RESIZED:
rect = resize(event);
break;
}
break;
}
if (redraw) {
draw(renderer, rect);
}
}
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
return 0;
}
At first, I try to get new renderer size SDL_GetRendererOutputSize in same result like getting size from event.
When I try to resize window with typical mouse motion actions, it works fine. But maximize or window manager resizing to one screen side does not work.
I try to use different event like SDL_WINDOWEVENT_SIZE_CHANGED, but with same result.
And yes, normally, I checks all SDL calls, with SDL_RenderDrawLine but without any errors.

Not getting resize event

First, make a list of the events that I want my window to receive, then I create my
window and after that I run in a while loop this event handler. My goal here is to print hello when the window is resized, and I don't understand why it doesn't. Here is the code :
uint32_t value_list[] = {
XCB_NONE,
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_RESIZE_REDIRECT,
};
xcb_create_window(
result->connection,
XCB_COPY_FROM_PARENT,
result->window,
screen->root,
0, 0, width, height,
0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
XCB_CW_EVENT_MASK,
value_list);
and
if(intern_window->event) {
switch(intern_window->event->response_type & ~0x80) {
case XCB_EXPOSE: {
xcb_flush(intern_window->connection);
break;
}
case XCB_CLIENT_MESSAGE: {
if( ((xcb_client_message_event_t*)intern_window->event)->data.data32[0] == intern_window->delete_reply->atom ) {
intern_window->closing = true;
free(intern_window->delete_reply);
}
break;
}
case XCB_RESIZE_REQUEST: {
puts("Hello");
break;
}
}
}
uint32_t value_list[] = {
XCB_NONE,
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_RESIZE_REDIRECT,
};
xcb_create_window(
result->connection,
XCB_COPY_FROM_PARENT,
result->window,
screen->root,
0, 0, width, height,
0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
XCB_CW_EVENT_MASK,
value_list);
So, value_list[0] is XCB_NONE and value_list[1] is the event mask you want. You then use just XCB_CW_EVENT_MASK, thus value_list[0] is your event mask and value_list[1] is ignored.
You are not getting the events since you did not ask for them.

Changing opacity of each shape seperately in an array p5.js

I'm new to coding. I created a simple code and I need help with targeting each of the elements (each rectangle) in the array seperately. My goal is to change the opacity or transparency of each of the rectangles.
I can simply do fill(0, 255, 100, 50)and add an alpha value but this changes all of the rectangles..
I want to change the transparency - Alpha values: 50, 100, 150, 200, 250 respectively for each rectangle.
I tried to create an array for it and implement it to the rectangles but I can't seem to do it.
Here is the code, any help is appreciated :)
function setup() {
createCanvas(500, 110);
}
function draw() {
background(0, 100, 180);
stroke(2);
rectMode(CENTER);
for (var i = 0; i < 5; i++) {
fill(0,255, 100);
rect((i+1)*80, 50, 50, 50, 15);
}
}
You can dynamically define a color (including alpha attribute) using the color() function.
Here is a working example: https://editor.p5js.org/chen-ni/sketches/aWnKXEYh1
var alphaValues = [50, 100, 150, 200, 250];
function setup() {
createCanvas(500, 110);
}
function draw() {
background(0, 100, 180);
stroke(2);
rectMode(CENTER);
for (var i = 0; i < alphaValues.length; i++) {
var _alpha = alphaValues[i];
var _color = color(0, 255, 100, _alpha);
fill(_color);
rect((i + 1) * 80, 50, 50, 50, 15);
}
}

(GDI) AlphaBlend

This question is follow up Win32 (GDI) - Set Opacity of STATIC Control
My problem is that my alpha blending function is not working and I was wondering if someone help me out?
Here is the Setup WndProc:
case WM_PAINT:
OnChildPaint(BeginPaint(hWnd, &ps));
EndPaint(hWnd, &ps);
break;
My OnChildPaint function:
BOOL
OnChildPaint(HDC i_hDC)
{
HDC hMemDC;
HGDIOBJ hOldObj;
HBITMAP hBitmap;
BLENDFUNCTION blendFunc_s = {AC_SRC_OVER, 0, 128, AC_SRC_ALPHA};
hMemDC = CreateCompatibleDC(i_hDC);
hBitmap = CreateCompatibleBitmap(hMemDC, 100, 100);
/* hBrush = CreateSolidBrush(RGB(255, 0, 0)); */
hOldObj = SelectObject(hMemDC, hBitmap);
BitBlt(i_hDC, 10, 100, 100, 100, hMemDC, 0, 0, SRCCOPY);
AlphaBlend(i_hDC, 10, 100, 100, 100, hMemDC, 10, 100, 100, 100, blendFunc_s);
SelectObject(hMemDC, hOldObj);
DeleteObject(hMemDC);
return TRUE;
}
Have that in mind that I'm not working with actual Bitmap Image (There is no Image).
Thanks

ListView scrollbar flickering

I am coding my first program with GUI using only pure WinAPI. But I faced some strange problem.
There are 2 ListView elements on the form to output some values. When scrollbar appears on second ListView, all child objects on the form disappears. And scrollbar of that ListView is flickering. And when I push on that ListView all get back to normal. I don't know what to do.
But this problem applies only to the second ListView element, hListViewCh on the form. There is all ok with the first element.
Here is the code:
case WM_CREATE:
{
GetClientRect(hWnd, &Rect);
h_Chk1 = CreateWindow(TEXT("button"), TEXT("Graphic"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
Rect.right - 550,
300 + 10,
100,
20,
hWnd, (HMENU)0xCB01, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
h_Chk2 = CreateWindow(TEXT("button"), TEXT("Diagram"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
Rect.right - 550,
300 + 35,
100,
20,
hWnd, (HMENU)0xCB02, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
CheckDlgButton(hWnd, 0xCB01, BST_UNCHECKED);
CheckDlgButton(hWnd, 0xCB02, BST_UNCHECKED);
hListViewCh = CreateWindow(
WC_LISTVIEW,
_T("MyList"),
LVS_REPORT|WS_CHILD|WS_VISIBLE,
Rect.right - 265,
377,
250,
200,
hWnd, (HMENU)listViewCh, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
//--
LVCOLUMN lvColumn = {0};
lvColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.pszText = "№";
lvColumn.cx = 30;
ListView_InsertColumn(hListViewCh, 0, &lvColumn);
lvColumn.pszText = "Property";
lvColumn.cx = 70;
ListView_InsertColumn(hListViewCh, 1, &lvColumn);
lvColumn.pszText = "Value";
lvColumn.cx = 120;
ListView_InsertColumn(hListViewCh, 2, &lvColumn);
//--
hListView = CreateWindow(
WC_LISTVIEW,
_T("Set of variate values"),
LVS_REPORT|WS_CHILD|WS_VISIBLE,
Rect.right - 550,
Rect.top + 15,
535,
275,
hWnd,
(HMENU)listView,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
//--
lvColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.pszText = "No";
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.cx = 43;
ListView_InsertColumn(hListView, 0, &lvColumn);
//--
lvColumn.pszText = "[ a[i-1] , a[i] )";
lvColumn.cx = 151;
ListView_InsertColumn(hListView, 1, &lvColumn);
//--
lvColumn.pszText = "xi";
lvColumn.cx = 85;
ListView_InsertColumn(hListView, 2, &lvColumn);
//--
lvColumn.pszText = "ni";
ListView_InsertColumn(hListView, 3, &lvColumn);
//--
lvColumn.pszText = "V";
ListView_InsertColumn(hListView, 4, &lvColumn);
//--
lvColumn.pszText = "EV";
ListView_InsertColumn(hListView, 5, &lvColumn);
break;
}
There is some redraw functions in WM_PAINT to make ListViews move with a window on maximizing.
//-- LISTVIEW POSITION
SetWindowPos(hListViewCh, NULL,\
Rect.right - 265,
312,
250,
200,
SWP_NOSIZE);
//-- LISTVIEW POSITION
SetWindowPos(hListView, NULL,\
Rect.right - 550,\
Rect.top + 15,\
535,\
340,\
SWP_NOSIZE|SWP_NOZORDER);
//--
Resizing child windows in a WM_PAINT is simply wrong and I suspect this to be a big part of your problems.
The code to position the child windows should be run in response to the WM_WINDOWPOSCHANGED message.

Resources