SendInput() for keyboard - only lowercase - winapi

I have following code:
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = 'A'; // tried 0x41, ( UCHAR )VkKeyScan( 'A' )
SendInput( 1, &Input, sizeof( INPUT ) );
but it generates me only 'a'. How to force it to generate upper case as well?
Thanks.

EDIT: some modifications according to rodrigo answer in comments.
INPUT Input = { 0 };
// shift key down
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = VK_LSHIFT;
SendInput( 1, &Input, sizeof( INPUT ) );
// 'a' key down
Input.type = INPUT_KEYBOARD;
Input.ki.wVk = 'A';
SendInput( 1, &Input, sizeof( INPUT ) );
// 'a' key release
Input.type = INPUT_KEYBOARD;
Input.ki.dwFlags = KEYEVENTF_KEYUP;
Input.ki.wVk = 'A';
SendInput( 1, &Input, sizeof( INPUT ) );
// shift key release
Input.type = INPUT_KEYBOARD;
Input.ki.dwFlags = KEYEVENTF_KEYUP;
Input.ki.wVk = VK_LSHIFT;
SendInput( 1, &Input, sizeof( INPUT ) );
EDIT: here is another code with an example of turning caps/shift off after sending letter:
INPUT Event = { 0 };
const SHORT key = VkKeyScan('a');
const UINT mappedKey = MapVirtualKey( LOBYTE( key ), 0 );
// Press shift key
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = MapVirtualKey( VK_LSHIFT, 0 );
SendInput( 1, &Event, sizeof( Event ) );
// upper case 'A'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey;
SendInput( 1, &Event, sizeof( Event ) );
// release upper case 'A'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = mappedKey;
SendInput( 1, &Event, sizeof( Event ) );
// Release shift key
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = MapVirtualKey( VK_LSHIFT, 0 );
SendInput( 1, &Event, sizeof( Event ) );
const SHORT key1 = VkKeyScan('A');
const UINT mappedKey1 = MapVirtualKey( LOBYTE( key1 ), 0 );
// lower case 'a'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey1;
SendInput( 1, &Event, sizeof( Event ) );
// release lower case 'a'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = mappedKey1;
SendInput( 1, &Event, sizeof( Event ) );
explanation here (I hope the explanation is correct): SendInput() for keyboard - only uppercase

Related

Windows.h GDI - BITMAPINFO alloca indicates failure

I want to create an image from the desktop and set it to gray using BITMAPINFO, but it keeps showing me the warning, "Warning C6255 _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead".
I would appreciate any advice.
HBITMAP CreateGreyscaleBitmap(int cx, int cy)
{
BITMAPINFO* pbmi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = cx;
pbmi->bmiHeader.biHeight = cy;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 8;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 0;
pbmi->bmiHeader.biXPelsPerMeter = 14173;
pbmi->bmiHeader.biYPelsPerMeter = 14173;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
for (int i = 0; i < 256; i++)
{
pbmi->bmiColors[i].rgbRed = i;
pbmi->bmiColors[i].rgbGreen = i;
pbmi->bmiColors[i].rgbBlue = i;
pbmi->bmiColors[i].rgbReserved = 0;
}
PVOID pv;
return CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pv, NULL, 0);
}

Creating 24-bit BITMAP in Winapi

I'm using the following code in order to convert my ImageMagick image to 32-bit HBITMAP:
BITMAP bitmap;
std::memset(&bitmap, 0, sizeof(bitmap));
bitmap.bmType = 0;
bitmap.bmWidth = image->image()->columns;
bitmap.bmHeight = image->image()->rows;
bitmap.bmWidthBytes = 4 * bitmap.bmWidth;
bitmap.bmPlanes = 1;
bitmap.bmBitsPixel = 32;
bitmap.bmBits = NULL;
const size_t size = bitmap.bmWidthBytes * bitmap.bmHeight;
auto buffer = (HANDLE)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
RGBQUAD *bitmap_bits = (RGBQUAD *) GlobalLock((HGLOBAL) buffer);
register RGBQUAD *q = bitmap_bits;
for (size_t y = 0; y < image->image()->rows; y++)
{
register auto p = GetVirtualPixels(image->image(), 0, y, image->image()->columns, 1, exception);
if (!p) break;
for (size_t x = 0; x < image->image()->columns; x++)
{
q->rgbRed = ScaleQuantumToChar(GetPixelRed(image->image(), p));
q->rgbGreen = ScaleQuantumToChar(GetPixelGreen(image->image(), p));
q->rgbBlue = ScaleQuantumToChar(GetPixelBlue(image->image(), p));
q->rgbReserved = 0;
p += GetPixelChannels(image->image());
q++;
}
}
bitmap.bmBits = bitmap_bits;
HBITMAP hbmp = CreateBitmapIndirect(&bitmap);
It works well, but I'd like to save some memory by using images with lower depth. Unfortunately I'm not even able to make it work with 24-bit images. I modified my code to look like this:
BITMAP bitmap;
std::memset(&bitmap, 0, sizeof(bitmap));
bitmap.bmType = 0;
bitmap.bmWidth = image->image()->columns;
bitmap.bmHeight = image->image()->rows;
bitmap.bmWidthBytes = ((bitmap.bmWidth * 24 + 31) / 32) * 4;
bitmap.bmPlanes = 1;
bitmap.bmBitsPixel = 24;
bitmap.bmBits = NULL;
const size_t length = bitmap.bmWidthBytes * bitmap.bmHeight;
auto buffer = (HANDLE)GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, length);
RGBTRIPLE *bitmap_bits = (RGBTRIPLE *) GlobalLock((HGLOBAL) buffer);
register RGBTRIPLE *q = bitmap_bits;
for (size_t y = 0; y < image->image()->rows; y++)
{
register auto p = GetVirtualPixels(image->image(), 0, y, image->image()->columns, 1, exception);
if (!p) break;
for (size_t x = 0; x < image->image()->columns; x++)
{
q->rgbtRed = ScaleQuantumToChar(GetPixelRed(image->image(), p));
q->rgbtGreen = ScaleQuantumToChar(GetPixelGreen(image->image(), p));
q->rgbtBlue = ScaleQuantumToChar(GetPixelBlue(image->image(), p));
p += GetPixelChannels(image->image());
q++;
}
}
bitmap.bmBits = bitmap_bits;
HBITMAP hbmp = CreateBitmapIndirect(&bitmap);
But it seems that this code cannot produce valid bitmap. What am I doing wrong?
You are not taking the stride/alignment into account. Each row needs to be DWORD aligned.
Calculating Surface Stride
In an uncompressed bitmap, the stride is the number of bytes needed to go from the start of one row of pixels to the start of the next row. The image format defines a minimum stride for an image. In addition, the graphics hardware might require a larger stride for the surface that contains the image.
For uncompressed RGB formats, the minimum stride is always the image width in bytes, rounded up to the nearest DWORD. You can use the following formula to calculate the stride:
stride = ((((biWidth * biBitCount) + 31) & ~31) >> 3)
You need to fix the way you access the RGBTRIPLEs in the buffer.
Before the "x loop" you should do something like q = (RGBTRIPLE*) (((char*)bitmap_bits) + (y * bitmap.bmWidthBytes));
CreateBitmapIndirect creates a DDB which is perhaps not the best choice, create a DIB instead:
#define CalcStride(w, bpp) ( ((((w) * (bpp)) + 31) & ~31) >> 3 )
static void SetPixel24(UINT w, void*bits, UINT x, UINT y, COLORREF cr)
{
RGBTRIPLE*p = ((RGBTRIPLE*) ( ((char*)bits) + (y * CalcStride(w, 24)) )) + x;
p->rgbtRed = GetRValue(cr);
p->rgbtGreen = GetGValue(cr);
p->rgbtBlue = GetBValue(cr);
}
void Silly24BPPExample()
{
HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, WC_STATIC, 0, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_OVERLAPPEDWINDOW|SS_BITMAP|SS_REALSIZECONTROL, 0, 0, 99, 99, 0, 0, 0, 0);
const INT w = 4, h = 4, bpp = 24;
BITMAPINFO bi;
ZeroMemory(&bi, sizeof(bi));
BITMAPINFOHEADER&bih = bi.bmiHeader;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = w, bih.biHeight = -h;
bih.biPlanes = 1, bih.biBitCount = bpp;
bih.biCompression = BI_RGB;
void*bits;
HBITMAP hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &bits, NULL, 0);
for (UINT x = 0; x < w; ++x)
for (UINT y = 0; y < h; ++y)
SetPixel24(w, bits, x, y, RGB(255, 0, 0)); // All red
SetPixel24(w, bits, 0, 0, RGB(0, 0, 255)); // except one blue
SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hBmp);
for (MSG msg; IsWindow(hWnd) && GetMessage(&msg, 0, 0, 0); ) DispatchMessage(&msg);
// DeleteObject(...)
}

OpenCV Stereo matching and disparity map

I am using the code sample for stereo matching that came with openCV source code, here:
/*
* stereo_match.cpp
* calibration
*
* Created by Victor Eruhimov on 1/18/10.
* Copyright 2010 Argus Corp. All rights reserved.
*
*/
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include <stdio.h>
using namespace cv;
static void print_help()
{
printf("\nDemo stereo matching converting L and R images into disparity and point clouds\n");
printf("\nUsage: stereo_match <left_image> <right_image> [--algorithm=bm|sgbm|hh|var] [--blocksize=<block_size>]\n"
"[--max-disparity=<max_disparity>] [--scale=scale_factor>] [-i <intrinsic_filename>] [-e <extrinsic_filename>]\n"
"[--no-display] [-o <disparity_image>] [-p <point_cloud_file>]\n");
}
static void saveXYZ(const char* filename, const Mat& mat)
{
const double max_z = 1.0e4;
FILE* fp = fopen(filename, "wt");
for(int y = 0; y < mat.rows; y++)
{
for(int x = 0; x < mat.cols; x++)
{
Vec3f point = mat.at<Vec3f>(y, x);
if(fabs(point[2] - max_z) < FLT_EPSILON || fabs(point[2]) > max_z) continue;
fprintf(fp, "%f %f %f\n", point[0], point[1], point[2]);
}
}
fclose(fp);
}
int main(int argc, char** argv)
{
const char* algorithm_opt = "--algorithm=";
const char* maxdisp_opt = "--max-disparity=";
const char* blocksize_opt = "--blocksize=";
const char* nodisplay_opt = "--no-display=";
const char* scale_opt = "--scale=";
if(argc < 3)
{
print_help();
return 0;
}
const char* img1_filename = 0;
const char* img2_filename = 0;
const char* intrinsic_filename = 0;
const char* extrinsic_filename = 0;
const char* disparity_filename = 0;
const char* point_cloud_filename = 0;
enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3 };
int alg = STEREO_SGBM;
int SADWindowSize = 0, numberOfDisparities = 0;
bool no_display = false;
float scale = 1.f;
StereoBM bm;
StereoSGBM sgbm;
StereoVar var;
for( int i = 1; i < argc; i++ )
{
if( argv[i][0] != '-' )
{
if( !img1_filename )
img1_filename = argv[i];
else
img2_filename = argv[i];
}
else if( strncmp(argv[i], algorithm_opt, strlen(algorithm_opt)) == 0 )
{
char* _alg = argv[i] + strlen(algorithm_opt);
alg = strcmp(_alg, "bm") == 0 ? STEREO_BM :
strcmp(_alg, "sgbm") == 0 ? STEREO_SGBM :
strcmp(_alg, "hh") == 0 ? STEREO_HH :
strcmp(_alg, "var") == 0 ? STEREO_VAR : -1;
if( alg < 0 )
{
printf("Command-line parameter error: Unknown stereo algorithm\n\n");
print_help();
return -1;
}
}
else if( strncmp(argv[i], maxdisp_opt, strlen(maxdisp_opt)) == 0 )
{
if( sscanf( argv[i] + strlen(maxdisp_opt), "%d", &numberOfDisparities ) != 1 ||
numberOfDisparities < 1 || numberOfDisparities % 16 != 0 )
{
printf("Command-line parameter error: The max disparity (--maxdisparity=<...>) must be a positive integer divisible by 16\n");
print_help();
return -1;
}
}
else if( strncmp(argv[i], blocksize_opt, strlen(blocksize_opt)) == 0 )
{
if( sscanf( argv[i] + strlen(blocksize_opt), "%d", &SADWindowSize ) != 1 ||
SADWindowSize < 1 || SADWindowSize % 2 != 1 )
{
printf("Command-line parameter error: The block size (--blocksize=<...>) must be a positive odd number\n");
return -1;
}
}
else if( strncmp(argv[i], scale_opt, strlen(scale_opt)) == 0 )
{
if( sscanf( argv[i] + strlen(scale_opt), "%f", &scale ) != 1 || scale < 0 )
{
printf("Command-line parameter error: The scale factor (--scale=<...>) must be a positive floating-point number\n");
return -1;
}
}
else if( strcmp(argv[i], nodisplay_opt) == 0 )
no_display = true;
else if( strcmp(argv[i], "-i" ) == 0 )
intrinsic_filename = argv[++i];
else if( strcmp(argv[i], "-e" ) == 0 )
extrinsic_filename = argv[++i];
else if( strcmp(argv[i], "-o" ) == 0 )
disparity_filename = argv[++i];
else if( strcmp(argv[i], "-p" ) == 0 )
point_cloud_filename = argv[++i];
else
{
printf("Command-line parameter error: unknown option %s\n", argv[i]);
return -1;
}
}
if( !img1_filename || !img2_filename )
{
printf("Command-line parameter error: both left and right images must be specified\n");
return -1;
}
if( (intrinsic_filename != 0) ^ (extrinsic_filename != 0) )
{
printf("Command-line parameter error: either both intrinsic and extrinsic parameters must be specified, or none of them (when the stereo pair is already rectified)\n");
return -1;
}
if( extrinsic_filename == 0 && point_cloud_filename )
{
printf("Command-line parameter error: extrinsic and intrinsic parameters must be specified to compute the point cloud\n");
return -1;
}
int color_mode = alg == STEREO_BM ? 0 : -1;
Mat img1 = imread(img1_filename, color_mode);
Mat img2 = imread(img2_filename, color_mode);
if( scale != 1.f )
{
Mat temp1, temp2;
int method = scale < 1 ? INTER_AREA : INTER_CUBIC;
resize(img1, temp1, Size(), scale, scale, method);
img1 = temp1;
resize(img2, temp2, Size(), scale, scale, method);
img2 = temp2;
}
Size img_size = img1.size();
Rect roi1, roi2;
Mat Q;
if( intrinsic_filename )
{
// reading intrinsic parameters
FileStorage fs(intrinsic_filename, CV_STORAGE_READ);
if(!fs.isOpened())
{
printf("Failed to open file %s\n", intrinsic_filename);
return -1;
}
Mat M1, D1, M2, D2;
fs["M1"] >> M1;
fs["D1"] >> D1;
fs["M2"] >> M2;
fs["D2"] >> D2;
M1 *= scale;
M2 *= scale;
fs.open(extrinsic_filename, CV_STORAGE_READ);
if(!fs.isOpened())
{
printf("Failed to open file %s\n", extrinsic_filename);
return -1;
}
Mat R, T, R1, P1, R2, P2;
fs["R"] >> R;
fs["T"] >> T;
stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 );
Mat map11, map12, map21, map22;
initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12);
initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map21, map22);
Mat img1r, img2r;
remap(img1, img1r, map11, map12, INTER_LINEAR);
remap(img2, img2r, map21, map22, INTER_LINEAR);
img1 = img1r;
img2 = img2r;
}
numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16;
bm.state->roi1 = roi1;
bm.state->roi2 = roi2;
bm.state->preFilterCap = 31;
bm.state->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9;
bm.state->minDisparity = 0;
bm.state->numberOfDisparities = numberOfDisparities;
bm.state->textureThreshold = 10;
bm.state->uniquenessRatio = 15;
bm.state->speckleWindowSize = 100;
bm.state->speckleRange = 32;
bm.state->disp12MaxDiff = 1;
sgbm.preFilterCap = 63;
sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
int cn = img1.channels();
sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
sgbm.minDisparity = 0;
sgbm.numberOfDisparities = numberOfDisparities;
sgbm.uniquenessRatio = 10;
sgbm.speckleWindowSize = bm.state->speckleWindowSize;
sgbm.speckleRange = bm.state->speckleRange;
sgbm.disp12MaxDiff = 1;
sgbm.fullDP = alg == STEREO_HH;
var.levels = 3; // ignored with USE_AUTO_PARAMS
var.pyrScale = 0.5; // ignored with USE_AUTO_PARAMS
var.nIt = 25;
var.minDisp = -numberOfDisparities;
var.maxDisp = 0;
var.poly_n = 3;
var.poly_sigma = 0.0;
var.fi = 15.0f;
var.lambda = 0.03f;
var.penalization = var.PENALIZATION_TICHONOV; // ignored with USE_AUTO_PARAMS
var.cycle = var.CYCLE_V; // ignored with USE_AUTO_PARAMS
var.flags = var.USE_SMART_ID | var.USE_AUTO_PARAMS | var.USE_INITIAL_DISPARITY | var.USE_MEDIAN_FILTERING ;
Mat disp, disp8;
//Mat img1p, img2p, dispp;
//copyMakeBorder(img1, img1p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
//copyMakeBorder(img2, img2p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
int64 t = getTickCount();
if( alg == STEREO_BM )
bm(img1, img2, disp);
else if( alg == STEREO_VAR ) {
var(img1, img2, disp);
}
else if( alg == STEREO_SGBM || alg == STEREO_HH )
sgbm(img1, img2, disp);
t = getTickCount() - t;
printf("Time elapsed: %fms\n", t*1000/getTickFrequency());
//disp = dispp.colRange(numberOfDisparities, img1p.cols);
if( alg != STEREO_VAR )
disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));
else
disp.convertTo(disp8, CV_8U);
if( !no_display )
{
namedWindow("left", 1);
imshow("left", img1);
namedWindow("right", 1);
imshow("right", img2);
namedWindow("disparity", 0);
imshow("disparity", disp8);
printf("press any key to continue...");
fflush(stdout);
waitKey();
printf("\n");
}
if(disparity_filename)
imwrite(disparity_filename, disp8);
if(point_cloud_filename)
{
printf("storing the point cloud...");
fflush(stdout);
Mat xyz;
reprojectImageTo3D(disp, xyz, Q, true);
saveXYZ(point_cloud_filename, xyz);
printf("\n");
}
return 0;
}
And I have tried all of the algorithms on the following set of images:
http://imageshack.com/a/img607/4641/utam.jpg (left)
http://imageshack.com/a/img62/5939/2hkc.jpg (right)
Here is my result:
http://imageshack.com/a/img856/4274/1n50.jpg
And here is the desired result:
http://i.stack.imgur.com/W9PBr.jpg
What could be the problem?
change parameters! For example, say bm, my experience is SADWindowSize and minDisparity really matters a lot! so you can add trackbars for each parameter and play with it until you get desired result. I've tried the same pair of images and it works fine. So all you need to do it try, try and try parameters.
I know it sounds crazy, but I had similar output when I was accidentally passing the same image as both the left and right input to the SGBMStereo algorithm. Just taking a shot in the dark...

OpenCL image writes in OS X

I've been trying to write an OpenCL kernel that populates an OpenCL image with values. However, I've been having problems with some texels not being written to. I can't seem to get the write_image() function to write to texels with different x and y coordinates.
I've created a reduction program here. Hopefully this is straightforward enough to be readable:
#include <iostream>
#include <cassert>
#include <OpenCL/OpenCL.h>
const char* clSource[] = {
"kernel void set(write_only image2d_t image)\n",
"{\n",
" int x = get_global_id(0);\n",
" int y = get_global_id(1);\n",
" float4 result = float4(1.0, 1.0, 1.0, 1.0);\n",
" printf(\"Writing dimensions %d x %d: %d, %d, %d, %d\\n\", x, y,\n",
" (int)result.x*255, (int)result.y*255, (int)result.z*255, (int)result.w*255);\n",
" write_imagef(image, int2(x, y), result);\n",
"}\n",
};
int main(int argc, const char * argv[])
{
const unsigned int WIDTH = 3;
const unsigned int HEIGHT = 3;
cl_int clError;
cl_platform_id platform;
clError = clGetPlatformIDs(1, &platform, nullptr);
assert(clError == CL_SUCCESS);
cl_device_id device;
clError = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, nullptr);
assert(clError == CL_SUCCESS);
cl_context_properties properties[] = {
CL_CONTEXT_PLATFORM, (cl_context_properties)platform,
0
};
cl_context openCLContext = clCreateContext(properties, 1, &device, nullptr, nullptr, &clError);
assert(clError == CL_SUCCESS);
cl_command_queue commandQueue = clCreateCommandQueue(openCLContext, device, 0, &clError);
assert(clError == CL_SUCCESS);
cl_program program = clCreateProgramWithSource(openCLContext, sizeof(clSource) / sizeof(const char*), clSource, nullptr, &clError);
assert(clError == CL_SUCCESS);
clError = clBuildProgram(program, 1, &device, "", nullptr, nullptr);
assert(clError == CL_SUCCESS);
cl_kernel kernel = clCreateKernel(program, "set", &clError);
assert(clError == CL_SUCCESS);
cl_image_format imageFormat;
imageFormat.image_channel_data_type = CL_UNORM_INT8;
imageFormat.image_channel_order = CL_RGBA;
cl_image_desc imageDesc;
imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D;
imageDesc.image_width = WIDTH;
imageDesc.image_height = HEIGHT;
imageDesc.image_depth = 1;
imageDesc.image_array_size = 1;
imageDesc.image_row_pitch = 0;
imageDesc.image_slice_pitch = 0;
imageDesc.num_mip_levels = 0;
imageDesc.num_samples = 0;
imageDesc.buffer = nullptr;
cl_mem clTexture = clCreateImage(openCLContext, CL_MEM_WRITE_ONLY, &imageFormat, &imageDesc, nullptr, &clError);
assert(clError == CL_SUCCESS);
clError = clSetKernelArg(kernel, 0, sizeof(cl_mem), &clTexture);
assert(clError == CL_SUCCESS);
size_t globalWorkOffset[] = {0, 0, 0};
size_t globalWorkSize[] = {WIDTH, HEIGHT, 0};
size_t localWorkSize[] = {1, 1, 0};
cl_event event1;
clError = clEnqueueNDRangeKernel(commandQueue, kernel, 2, globalWorkOffset, globalWorkSize, localWorkSize, 0, nullptr, &event1);
assert(clError == CL_SUCCESS);
unsigned char* bitmap = new unsigned char[WIDTH * HEIGHT * 4];
size_t origin[] = {0, 0, 0};
size_t region[] = {WIDTH, HEIGHT, 1};
cl_event event2;
clError = clEnqueueReadImage(commandQueue, clTexture, CL_TRUE, origin, region, 0, 0, bitmap, 1, &event1, &event2);
std::cout << "============================================" << std::endl;
clError = clWaitForEvents(1, &event2);
assert(clError == CL_SUCCESS);
for (size_t i = 0; i < HEIGHT; ++i) {
for (size_t j = 0; j < WIDTH; ++j) {
std::cout << "Reading dimensions " << j << " x " << i << ": ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+0]) << ", ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+1]) << ", ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+2]) << ", ";
std::cout << static_cast<int>(bitmap[4*(i*WIDTH+j)+3]) << std::endl;
}
}
delete[] bitmap;
clError = clReleaseEvent(event1);
assert(clError == CL_SUCCESS);
clError = clReleaseEvent(event2);
assert(clError == CL_SUCCESS);
clError = clReleaseMemObject(clTexture);
assert(clError == CL_SUCCESS);
clError = clReleaseKernel(kernel);
assert(clError == CL_SUCCESS);
clError = clReleaseProgram(program);
assert(clError == CL_SUCCESS);
clError = clReleaseCommandQueue(commandQueue);
assert(clError == CL_SUCCESS);
clError = clReleaseDevice(device);
assert(clError == CL_SUCCESS);
clError = clReleaseContext(openCLContext);
assert(clError == CL_SUCCESS);
return 0;
}
After all that, here is the output on OS X (10.9):
Writing dimensions 0 x 0: 255, 255, 255, 255
Writing dimensions 1 x 0: 255, 255, 255, 255
Writing dimensions 2 x 0: 255, 255, 255, 255
Writing dimensions 0 x 1: 255, 255, 255, 255
Writing dimensions 1 x 1: 255, 255, 255, 255
Writing dimensions 2 x 1: 255, 255, 255, 255
Writing dimensions 0 x 2: 255, 255, 255, 255
Writing dimensions 1 x 2: 255, 255, 255, 255
Writing dimensions 2 x 2: 255, 255, 255, 255
============================================
Reading dimensions 0 x 0: 255, 255, 255, 255
Reading dimensions 1 x 0: 0, 0, 0, 0
Reading dimensions 2 x 0: 0, 0, 0, 0
Reading dimensions 0 x 1: 0, 0, 0, 0
Reading dimensions 1 x 1: 255, 255, 255, 255
Reading dimensions 2 x 1: 0, 0, 0, 0
Reading dimensions 0 x 2: 0, 0, 0, 0
Reading dimensions 1 x 2: 0, 0, 0, 0
Reading dimensions 2 x 2: 255, 255, 255, 255
Program ended with exit code: 0
I get the same result on a ATI Radeon HD 5750 as I do on a NVIDIA GeForce GT 650M.
OpenCL to OpenGL texture problems and opencl image2d_t doesn't write back values seem to have similar problems, but neither of those have anything that helps me.
Am I doing something wrong? Or are image writes simply not supported on Mavericks drivers?
The issue is in the way that you are constructing vector values. Instead of this:
typeN(a, b, ..., k)
You should be doing this:
(typeN)(a, b, ..., k)
The former actually causes a compilation error on non-Apple platforms, so I'm not actually sure how Apple's compiler is interpreting that code.
So, for your kernel, the two relevant lines that need to be changed are these:
float4 result = float4(1.0, 1.0, 1.0, 1.0);
...
write_imagef(image, int2(x, y), result);
Which should now become:
float4 result = (float4)(1.0, 1.0, 1.0, 1.0);
...
write_imagef(image, (int2)(x, y), result);
I was able to compile and run your program successfully with the following kernel change:
const char* clSource[] = {
"__kernel void set(write_only image2d_t image)\n",
"{\n",
" int x = get_global_id(0);\n",
" int y = get_global_id(1);\n",
" float4 result = (float4)(1.0, 1.0, 1.0, 1.0);\n",
" printf(\"Writing dimensions %d x %d: %d, %d, %d, %d\\n\", x, y,\n",
" (int)result.x*255, (int)result.y*255, (int)result.z*255, (int)result.w*255);\n",
" write_imagef(image, (int2)(x, y), result);\n",
"}\n",
};
As an example you cannot write float4(1.0.... but you must write it as C style typecast (float4). I have no idea why it even compiled cleanly with your drivers.
Another really weird issue in the output is that your output seems to come from the case where WIDTH and HEIGHT on line 23 were 3. Is the output from a version where it indeed is 3?
Regardless it works fine after the changes.

CreateDIBSection + 16 bit system color

This code works perfect on 32 bit system color (Windows 7),
but it doesn't work on 16 bit color - menu bitmaps not transparent!!!:
...
HBITMAP rv = rgb(hsrc, 16);
...
HBITMAP rgb(HBITMAP hsrc, WORD wBitsPixel) {
HBITMAP hold = NULL;
HDC hdcsrc = NULL, hdc = NULL;
BITMAP bmp = {0};
HBITMAP dib = NULL;
UCHAR *dst = NULL, *src = NULL, *tmp = NULL;
UCHAR alpha;
int bpl;
ULONG x, y;
DWORD bmp_size = 0;
HANDLE hdib = NULL;
char *lpbitmap = NULL;
int rv = 0;
hdc = GetDC(m_hMainDlg);
hdcsrc = CreateCompatibleDC(hdc);
hold = (HBITMAP)SelectObject(hdcsrc, hsrc);
rv = GetObject(hsrc, sizeof(BITMAP), &bmp);
BITMAPINFOHEADER bi = {0};
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;;
bi.biHeight = bmp.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitsPixel;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bmp_size = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
hdib = GlobalAlloc(GHND, bmp_size);
lpbitmap = (char *)GlobalLock(hdib);
/* Get bits of source bitmap. */
GetDIBits(hdcsrc, hsrc, 0, bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
/* For destination bitmap */
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
bmi.bmiHeader.biWidth = bmp.bmWidth;
bmi.bmiHeader.biHeight = bmp.bmHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = wBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
dib = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&dst, NULL, 0);
bpl = 4 * bmp.bmWidth; /* bytes per line */
src = (UCHAR *)lpbitmap;
for (y = 0; y < bmp.bmHeight; y++, src += bpl) {
tmp = src;
for (x = 0; x < bmp.bmWidth; x++) {
alpha = tmp[3];
dst[0] = tmp[0] * alpha / 255;
dst[1] = tmp[1] * alpha / 255;
dst[2] = tmp[2] * alpha / 255;
dst[3] = alpha;
dst += 4;
tmp += 4;
}
}
// free resources
ReleaseDC(m_hMainDlg, hdc);
SelectObject(hdcsrc, hold);
DeleteDC(hdcsrc);
GlobalUnlock(hdib);
GlobalFree(hdib);
return dib;
}

Resources