Using SetDIBitsToDevice with RGB array. Is it faster than BitBlt? - windows

I have an array defined as:
COLORREF* array = (COLORREF*)malloc(SCR_WIDTH * SCR_HEIGHT * sizeof(COLORREF));
An algorithm updates this array with RGB colors continuously.
I'm just looking for a fast way to display this image on the screen, in particular BitBlt vs. SetDIBitsToDevice.
I've been successful using BitBlt:
map = CreateBitmap(SCR_WIDTH, SCR_HEIGHT, 1, 32, (void*)array);
src = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(src, map);
BitBlt(hdc, 0, 0, SCR_WIDTH, SCR_HEIGHT, src, 0, 0, SRCCOPY);
SelectObject(src, oldBitmap);
DeleteDC(src);
DeleteObject(map);
However, I think that SetDIBitsToDevice would be faster since you can draw the pixels directly to the screen without the need to create a compatible DC (correct me if I'm wrong).
The problem that I'm having is that SetDIBitsToDevice needs these two arguments and I can't find how to obtain/create them from the RGB array:
const VOID *lpvBits,
const BITMAPINFO *lpbmi,
Any help is appreciated. I'm also open to suggestions that could work even faster (preferably using WINGDI).
Thanks a lot!

Related

Texture crop replacement in OpenGL ES 2.0?

I am trying to upgrade code which uses OpenGLES1 to ES2. The conversion is more or less understandable however for these lines I could not find alternative in ES2. Not even sure why it is necessary.
GLint crop[4] = { 0, h, w, -h };
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop);
if it is for drawing animation then use UV coordinates, it is faster.
If you need part of the texture use
Bitmap newbitmap = Bitmap.createBitmap(oldbitmap, x,y,w,h)
GLUtils.texImage2D(GL_TEXTURE_2D, 0, newbitmap , 0);

How can I properly create an array texture in OpenGL (Go)?

I have a total of two textures, the first is used as a framebuffer to work with inside a computeshader, which is later blitted using BlitFramebuffer(...). The second is supposed to be an OpenGL array texture, which is used to look up textures and copy them onto the framebuffer. It's created in the following way:
var texarray uint32
gl.GenTextures(1, &texarray)
gl.ActiveTexture(gl.TEXTURE0 + 1)
gl.BindTexture(gl.TEXTURE_2D_ARRAY, texarray)
gl.TexParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
gl.TexImage3D(
gl.TEXTURE_2D_ARRAY,
0,
gl.RGBA8,
16,
16,
22*48,
0,
gl.RGBA, gl.UNSIGNED_BYTE,
gl.Ptr(sheet.Pix))
gl.BindImageTexture(1, texarray, 0, false, 0, gl.READ_ONLY, gl.RGBA8)
sheet.Pix is just the pixel array of an image loaded as a *image.NRGBA
The compute-shader looks like this:
#version 430
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img;
layout(binding = 1) uniform sampler2DArray texAtlas;
void main() {
ivec2 iCoords = ivec2(gl_GlobalInvocationID.xy);
vec4 c = texture(texAtlas, vec3(iCoords.x%16, iCoords.y%16, 7));
imageStore(img, iCoords, c);
}
When i run the program however, the result is just a window filled with the same color:
So my question is: What did I do wrong during the shader creation and what needs to be corrected?
For any open code questions, here's the corresponding repo
vec4 c = texture(texAtlas, vec3(iCoords.x%16, iCoords.y%16, 7))
That can't work. texture samples the texture at normalized coordinates, so the texture is in [0,1] (in the st domain, the third dimension is the layer and is correct here), coordinates outside of that ar handled via the GL_WRAP_... modes you specified (repeat, clamp to edge, clamp to border). Since int % 16 is always an integer, and even with repetition only the fractional part of the coordinate will matter, you are basically sampling the same texel over and over again.
If you need the full texture sampling (texture filtering, sRGB conversions etc.), you have to use the normalized coordinates instead. But if you only want to access individual texel data, you can use texelFetch and keep the integer data instead.
Note, since you set the texture filter to GL_LINEAR, you seem to want filtering, however, your coordinates appear as if you would want at to access the texel centers, so if you're going the texture route , thenvec3(vec2(iCoords.xy)/vec2(16) + vec2(1.0/32.0) , layer) would be the proper normalization to reach the texel centers (together with GL_REPEAT), but then, the GL_LINEAR filtering would yield identical results to GL_NEAREST.

How to draw TrueType fonts into an array of pixels in WinAPI?

There are some WinAPI functions that draw TrueType fonts into a windows GDI context.
I want to have this TrueType text written, but into my own 2-dimensional array of pixels (the one I just blit onto a window with just this code :)
int blit_mode = STRETCH_DELETESCANS;
void BlitFrame()
{
BITMAPINFO bmi = { {sizeof(BITMAPINFOHEADER), frame_size_x, -frame_size_y,1,32,BI_RGB,0,0,0,0,0}, {0,0,0,0} };
SetStretchBltMode(hdc, blit_mode);
int result = StretchDIBits(hdc,
0, 0, client_x, client_y,
0, 0, frame_size_x, frame_size_y,
frame_bitmap,
&bmi,
DIB_RGB_COLORS,
SRCCOPY);
}
This code is very messy in WinAPI and I couldn't find out (at least to this moment) how to do that.
How can I do that?
tnx Barmak Shemirani
i get your code and produced something like that
void BlitFrame2()
{
BITMAPINFO bmi = { {sizeof(BITMAPINFOHEADER), frame_size_x, -frame_size_y,1,32,BI_RGB,0,0,0,0,0}, {0,0,0,0} };
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP hbitmap = CreateBitmap(frame_size_x, frame_size_y, 1, 32, frame_bitmap);
HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
SetBkMode(memdc, TRANSPARENT);
SetTextColor(memdc, 0xffffff);
TextOut(memdc, 0, 0, "123", 3);
SelectObject(memdc, oldbmp);
GetDIBits(memdc, hbitmap, 0, frame_size_y, frame_bitmap, &bmi, 0);
DeleteObject(hbitmap);
DeleteDC(memdc);
// ReleaseDC(0, hdc);
SetStretchBltMode(hdc, blit_mode);
int result = StretchDIBits(hdc,
0, 0, client_x, client_y,
0, 0, frame_size_x, frame_size_y,
frame_bitmap,
&bmi,
DIB_RGB_COLORS,
SRCCOPY);
}
its adds stable text to my blitted frames, tnx
hovever i would get yet some question as i dont understand it
1) could maybe someone tell me a bit more how it works and where memory transfers are? do i have simple byte acces to this pixel table that is updated with drawed text? (for example to postprocess it)
2) it works but it gets slower quite noticably, for example when my oryginal frame was 2 ms (draw some bitmap sprite then blit) when using this tame grows up to 8 ms
3) can i move some of those calls outside of frame loop?
PS
when thinking on this i assume it works like that
1) it copies my pixel table in memdc at some point (where?)
2) it draws to this memdc those fonts
3) GetDIBits updates my oryginal pixel table with changed pixels (im not sure as to this hovever, but almost sure)
4) i blit it just like before
if so instead of one blit i get three (co it should be 3 times slower,
measurements show its more like 4 times, but maybe its an measurment error (2 and 8 may be 2.7 and 8.1 for example)
if this is three it would be ok, hovever i think i not always would need to get those table pixels reupdated from memdc, is there a way of
blitting it stright from memdc? (then it would be only two times slower instead of 3, still it is sad those fount routines cant just render stright into my own ram table - then it would be no slower at all) (isnt it really possible?)

OpenGL ES: Handle large amount matrixdata improve performance

I am using instancing in my OpenGL-app and since only one drawcall are made I have to calculate a larger matrix that consists of smaller matrices and that larger matrix is sent to the shader where gl_InstanceID can distinguish between successive matrices.
Its put on the bus with the following call
GLES30.glUniformMatrix4fv(mMVPMatrixHandleBall, nBalls, false, mMVPMatrixMajor, 0);
and in the shader the multiplication si made by
gl_Position = u_MVPMatrix[gl_InstanceID] * a_Position;
simple!
On the client-side the larger matrix is created by the following code:
private void setLargeMVPmatrix() {
int cnt = 0;
for (Iterator<Ball> shapeIterator = arrayListBalls.iterator(); shapeIterator.hasNext(); ) {
Ball ball = shapeIterator.next();
mModelMatrix = ball.getmModelMatrix();
//multipl.
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
//subst. in matrisdata i en större vektor dvs vi får en stor matris som innehhåller flera mindre matriser
for (int i = 0; i < CreateGLContext.MATRIX_SIZE; i++) {
mMVPMatrixMajor[i + CreateGLContext.MATRIX_SIZE * cnt] = mMVPMatrix[i];
}
cnt++;
}
}
If I have moving-objects on the screen, like bouncing balls, for instance 100 balls bouncing around it means I have to continously translate their positions each frame which in turn means I have to call this method every frame. And the consequence is that it becomes a real performance bottelneck. I know it by just commenting out the method just to see what happends - and a real performance boost but the balls doesnt not move any longer, of course.
So my question - Is there a soluition to this problem? If I use instancing, I have to send a large matrix according to above.
Edit:
I've even tried the following which I thought could at least partially solve my problem. In the drawMethod:
int cnt = 0;
for (Iterator <Ball> it = arrayListBalls.iterator(); it.hasNext();) {
Ball ball = it.next();
mModelMatrix = ball.getmModelMatrix();
//multipl.
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES30.glUniformMatrix4fv( (mMVPMatrixHandleBall + cnt), 1, false, mMVPMatrix, 0);
cnt++;
}
Thanks in advance!!!
If the data that change are positions and rotations then that's what you should update to the shader.
Doing most of matrix stuff at CPU is slow, unless the needed operations are tiny, like computing the new view and projection matrices, same for all objects, and they are cheap to pass as uniforms
For every frame I'd re-fill a BufferData, perhaps with the help of glMapBufferRange or glBufferSubData, with the new positions and rotations.
Then, in the shader, build the matrices needed and do matrices multiplication there.
If initial positions and rotations are needed to build new matrices, then you must also pass them in another buffer, although just update it for the first frame.
With the proper attributes order you read in the shader these positions and rotations. The gl_InstanceID is then not needed for gl_Position calculus, perhaps needed for other object property.
If you need help on how to build matrices inside the shaders, look for glRotate and glTranslate in OpenGL 2.1 docs where you can find the definitions.
Also note that passing a big matrix for all objects by an uniform may exceed the limit on the size for the whole uniform data.

What is the method to detect whether a given picture is human face or not?

Is there any simple algorithm to judge whether a given image is face or something else (without training hopefully)?
My thought is to construct the eigenvectors of each image, then apply some clustering method (for example k-means with k = 2). But I'm not sure what will be the best criteria to distinguish face/non-face even if a good clustering result is obtained?
Eigen decomposition reduces dimensionality in continues domain by finding directions in data space with high variance. K-means finds clusters in space with high density of points. You kind of mixing them together while completely ignoring how would you arrive at the face features on the first place (how would you scale, rotate and crop whatever you want to inspect either).
You don’t need to train Haar detectors since they are already trained for faces. They detect a face, not recognize its identity. ALl you need is to port the code together with a little file with parameters obtained after training (that was already performed) as Shiva suggested above.
Thoughtless copy-pasting of the code doesn’t make much sense though. Read a bit about Haar. Try to understand
Why they work - faces have features most pronounced on the intermediate spatial scale such as eyes, nose, brows. Too small (size of the pupil) or too large (size of the whole face) features are less useful.
why Haars are preferred to wavelets or Gabors - Haars are just raw (boxy) approximations of Gabors but since they can be quickly calculated with Integral images they are preferred to more precise but slower counterparts;
what are the restrictions - Haars have their own spatial scale and orientation but can be quickly recalculated for another scale.
How to train Haar classifier (the most exciting topic you are trying to avoid). Ada boost is the one way to train a more complex classifier consisting of several Haars. Finally to speed up processing you can ask a slightly different question instead of find me a face. Namely, you can try to quickly eliminate the areas in the image that cannot be a face. This is called a cascade classification. Study these aspects in a systematic way and you will learn more about face detection than you’d do from the code pasting.
You can use Haar classifier method for face detection in an image/video frame.
A sample code for finding faces in an images will be like this
int main(int argc, _TCHAR* argv[])
{
IplImage* img;
img = cvLoadImage( "dasl_hubo.jpg" );
CvMemStorage* storage = cvCreateMemStorage(0);
// Note that you must copy C:\Program Files\OpenCV\data\haarcascades\haarcascade_frontalface_alt2.xml or where opencv is installed
// to your working directory
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt2.xml" );
double scale = 1.3;
static CvScalar colors[] = { {{0,0,255}}, {{0,128,255}}, {{0,255,255}},
{{0,255,0}}, {{255,128,0}}, {{255,255,0}}, {{255,0,0}}, {{255,0,255}} };// this will draw rectangles of these colors around the detected faces.
// Detect objects
cvClearMemStorage( storage );
CvSeq* objects = cvHaarDetectObjects( img, cascade, storage, 1.1, 4, 0, cvSize( 40, 50 ));
CvRect* r;
// Loop through objects and draw boxes
for( int i = 0; i < (objects ? objects->total : 0 ); i++ ){
r = ( CvRect* )cvGetSeqElem( objects, i );
cvRectangle( img, cvPoint( r->x, r->y ), cvPoint( r->x + r->width, r->y + r->height ),
colors[i%8]);
}
cvNamedWindow( "Output" );
cvShowImage( "Output", img );
cvWaitKey();
cvReleaseImage( &img );
return 0;
}
visit these links to find more about face detection using harr cascades
drexel.edu
opencv documentation
presentation on Harr training and usages
Here is my opencv code in C++, it is simple to detect faces in an image with the help of Opencv haar-like feature, you may refer to the documents for the usage of some methods in it. I hope it helps.
CascadeClassifier face_cascade; //for read in haar-like faces database in opencv
std::vector<Rect> faces; //for storing detected faces
vector<Point2d> FaceCenter; //for storing centres of faces
Mat frame_gray = imread(“/Users/xxx/Desktop/xxx.jpg”, CV_8UC1); //read the image in gray-scale;
equalizeHist( frame_gray, frame_gray ); //histogram to extract the contrast
String face_cascade_name = "/Users/xxx/opencv-2.4.7/data/haarcascades/haarcascade_frontalface_alt.xml"; //path of the trained faces .xml file
if(!face_cascade.load(face_cascade_name)) //load the .xml
{
cout << "face_casacade.xml load error" << endl;
}
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0, Size(50, 50) ); //Detect faces in the image
for(size_t i = 0; i < faces.size(); i++)
{
Point2d center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5); //store centres of faces
FaceCenter.push_back(center);
int radius = cvRound( (eyes[j].width + eyes[j].height)*0.25 ); //circle the faces in the image, optional
ellipse( frame_gray, center, Size( eyes[j].width*0.5, eyes[j].height*0.25), 0, 0, 360, Scalar( 255, 0, 0 ), 2, 8, 0 );
}
imshow(“Faces Detection”, frame_gray); //show the result

Resources