C++ GDIPlus Bitmap lockbits results WrongState(8) - c++

I'm trying to get rect. of diffent area between two Bitmap* objects. When i pass 2 bitmap* it can run lockbits for first frame but it cannot do it for second bitmap.
Rect GetRecDifference(Bitmap* currentFrame, Bitmap* previousFrame) {
if (previousFrame == NULL) {
previousFrame = currentFrame;
}
else {
return Rect(0, 0, 0, 0);
}
BitmapData* bd1 = new BitmapData;
Rect rect1(0, 0, currentFrame->GetWidth(), currentFrame->GetHeight());
currentFrame->LockBits(&rect1, ImageLockModeRead, PixelFormat32bppARGB, bd1);
BitmapData* bd2 = new BitmapData;
Rect rect2(0, 0, previousFrame->GetWidth(), previousFrame->GetHeight());
previousFrame->LockBits(&rect2, ImageLockModeRead, PixelFormat32bppARGB, bd2);
It can run for first one (bd1*) load status ok and last result is shows ok. but when it comes to bd2 it shows status as WrongState(8).
Is this because i copy current pointer to previous one ? What's reason can be for wrong state error ? Do i need to clear some parts from memory ?

The problem is that you are trying to lock the same image twice, this
previousFrame = currentFrame;
means that both your pointers are pointing to the same image.
Instead you need a scheme that keeps two images in memory at once. Something like the following
Bitmap* current = NULL;
Bitmap* previous = NULL;
while (something)
{
current = getNextImage(); // get the new image
if (current && previous)
{
// process current and previous images
...
}
delete previous; // delete the previous image, not needed anymore
previous = current; // save the current image as the previous
}
delete previous; // one image left over, delete it as well
Not the only way to do it, but hopefully you get the idea.

Related

CImage : copying 8bit JPEGs gives a black image

The following code extract I am loading an 300DPI 8-bit JPEG and then trying to write it out again in a Fresh instance of a CImage also as a JPEG.
But I end up with a black image with the correct dimensions.
Can someone explain why that is?
Ignore the commented out brush lines I'll get over that mental hurdle later.
If I hard code the bppGraphic to 24 it does copy the picture (to a DPI of 96) resulting in a smaller file size. I can live with this, I guess I am just curious.
Update 07-Nov-2018
So I added the indendented 'if' statement and it still came out black. The colorCountIMAGE comes out at 20. (The IsIndexed lines were to help me with an ASSERT issue I found in the SetColorTable - but it went away)
I think I may just force in all 24 bit.
Thanks
4GLGuy
PS This is all being done in VS2017.
char filePath[256] = "C:\\temp\\b64-one.jpg";
CImage imageGRAPHIC, imageJPG;
HRESULT retval;
bool result;
retval = imageGRAPHIC.Load(filePath);
if (retval != S_OK) {
throw FALSE;
}
int xGRAPHIC, yGRAPHIC, bppGRAPHIC = 0;
xGRAPHIC = imageGRAPHIC.GetWidth();
yGRAPHIC = imageGRAPHIC.GetHeight();
bppGRAPHIC = imageGRAPHIC.GetBPP();
//Create my target JPG same size and bit depth specifying
//that there is no alpha channel (dwflag last param)
result = imageJPG.Create(xGRAPHIC, yGRAPHIC, bppGRAPHIC, 0);
auto dcJPEG = imageJPG.GetDC();
if (bppGRAPHIC <= 8)
{
result = imageJPG.IsIndexed();
result = imageGRAPHIC.IsIndexed();
auto dcIMAGE = imageGRAPHIC.GetDC();
int colorCountIMAGE = GetDeviceCaps(dcIMAGE, NUMCOLORS);
RGBQUAD* coltblIMAGE = new RGBQUAD[colorCountIMAGE];
imageGRAPHIC.GetColorTable(0, colorCountIMAGE, &coltblIMAGE[0]);
imageJPG.SetColorTable(0, colorCountIMAGE, &coltblIMAGE[0]);
}
//Let there be white - 8 bit depth with 24 bit brush - no worky
//CRect rect{ 0, 0, xGRAPHIC, yGRAPHIC };
//HBRUSH white = CreateSolidBrush(RGB(255, 255, 255));
//FillRect(dcJPEG, &rect, white);
result = imageGRAPHIC.Draw(dcJPEG, 0, 0);
retval = imageJPG.Save(filePath, Gdiplus::ImageFormatJPEG);
if (retval != S_OK) {
throw FALSE;
}

MFT Frame Extraction in c++

I have working solution to extract frames from a video in c++ at github. Problem is its very slow. What I am doing is I am using a timer and playing video and whenever frame is ready I convert it into bitmap and saves it and seek to next position . This is not the right approach I think, there must be another way of pulling out frames. Please go through Github project and suggest any changes.
following is my Timer function
if (m_spMediaEngine != nullptr)
{
LONGLONG pts;
if (m_spMediaEngine->OnVideoStreamTick(&pts) == S_OK)
{
// new frame available at the media engine so get it
ComPtr<ID3D11Texture2D> spTextureDst;
MEDIA::ThrowIfFailed(
m_d3dDevice->CreateTexture2D(
&CD3D11_TEXTURE2D_DESC(
DXGI_FORMAT_B8G8R8A8_UNORM,
m_rcTarget.right, // Width
m_rcTarget.bottom, // Height
1, // MipLevels
1, // ArraySize
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET
),
nullptr,
&spTextureDst
)
);
if (FAILED(
m_spMediaEngine->TransferVideoFrame(spTextureDst.Get(), nullptr, &m_rcTarget, &m_bkgColor)
))
{
return;
}
Position = Position + interval;
SetPlaybackPosition(Position);
ComPtr<IDXGISurface2> surface;
MEDIA::ThrowIfFailed(
spTextureDst.Get()->QueryInterface(
__uuidof(IDXGISurface2), &surface)
);
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
96,
96
);
m_d2dContext->CreateBitmapFromDxgiSurface(surface.Get(), &bitmapProperties, &bitmap);
SaveBitmapToFile();
}
}
My Question is : Is this the right and only way of extracting frames ?
I would do something along the lines of converting it to a hashsum and storing that, which should speed it up. For example, you could create a class to hold a specific instance of a hash, (or create a linked list for those hashes), and then extract a frame and hash it using dhash http://www.hackerfactor.com/blog/index.php?/archives/2013/01/21.html

Releasing data from a char* in C++

I'm pulling data from a uEye industrial camera, and am retrieving images through the camera's API.
My code looks something like this:
bool get_image(char*& img)
{
void *pMemVoid; //pointer to where the image is stored
// Takes an image from the camera. If successful, returns true, otherwise
// returns false
if (is_GetImageMem(hCam, &pMemVoid) == IS_SUCCESS){
img = (char*) pMemVoid;
pMemVoid = NULL;
return true;
}
else
return false;
}
I'm retrieving a image data, and if it is successful, it returns true, otherwise returns false.
The problem is I believe I'm leaking memory with img = (char*) pMemVoid, because I'm repeatedly calling this function and not releasing this data. How do I release the memory that is assigned to img?
EDIT:
I'm initializing the camera in a function that uses is_AllocImageMem:
// Global variables for camera functions
HIDS hCam = 0;
char* ppcImgMem;
int pid;
/* Initializes the uEye camera. If camera initialization is successful, it
* returns true, otherwise returns false */
bool init_camera()
{
int nRet = is_InitCamera (&hCam, NULL);
is_AllocImageMem(hCam,752, 480, 1 ,&ppcImgMem, &pid);
is_SetImageMem(hCam, ppcImgMem, pid);
is_SetDisplayMode (hCam, IS_SET_DM_DIB);
is_SetColorMode (hCam, IS_CM_MONO8);
int pnCol , pnColMode;
is_GetColorDepth(hCam, &pnCol , &pnColMode);
is_CaptureVideo(hCam, IS_WAIT);
if (nRet != IS_SUCCESS)
{
if (nRet == IS_STARTER_FW_UPLOAD_NEEDED)
{
hCam = hCam | IS_ALLOW_STARTER_FW_UPLOAD;
nRet = is_InitCamera (&hCam, NULL);
}
cout << "camera failed to initialize " << endl;
return false;
}
else
return true;
}
The API Documentation seems to suggest that there's a corresponding is_FreeImageMem function. Have you tried that?
Edit: It looks like is_GetImageMem may not allocate memory. From its description:
is_GetImageMem() returns the starting address of the image memory last used for image capturing.
Are you calling is_AllocImageMem anywhere?
I ran valgrind on the code, the output had roughly 16,000,000 bytes possibly lost, and roughly 20,000,000 bytes indirectly lost.
When the image was retrieved from get_image and assigned to img, img was assigned as data to an OpenCV IplImage like this:
IplImage* src = cvCreateImage(cvSize(752,480), IPL_DEPTH_8U, 1);
src -> imageData = img;
The IplImage was being retained, so I had to call cvReleaseImage on the IplImage stored in memory. Now valgrind reports that indirectly lost are at 0, and possibly lost at about 1,600,000. Still havn't accounted for the 1.6 million, but I think the IplImage contributed significantly to the memory leak

Kinect Facetracking C++ start up error

We are working with the Kinect to track faces for a schoolproject. We have set up Visual Studio 2012, and all the test programs are working correctly. However we are trying to run this code and it gives us an error. After many attempts to fix the code, it gives the following error:
"The application was unable to start correctly (0xc000007b).Click OK to close the application.
The good thing is that it's finally running. The bad thing is that the compiler doesn't throw any errors other than this vague error.
We are completely lost and we hope that someone can help us or point us into the right direction. Thanks in advance for helping us.
The code:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <NuiApi.h>
#include <FaceTrackLib.h>
#include <NuiSensor.h>
using namespace std;
HANDLE rgbStream;
HANDLE depthStream;
INuiSensor* sensor;
#define width 640
#define height 480
bool initKinect() {
// Get a working kinect sensor
int numSensors;
if (NuiGetSensorCount(&numSensors) < 0 || numSensors < 1) return false;
if (NuiCreateSensorByIndex(0, &sensor) < 0) return false;
// Initialize sensor
sensor->NuiInitialize(NUI_INITIALIZE_FLAG_USES_DEPTH | NUI_INITIALIZE_FLAG_USES_COLOR);
sensor->NuiImageStreamOpen(
NUI_IMAGE_TYPE_COLOR, // Depth camera or rgb camera?
NUI_IMAGE_RESOLUTION_640x480, // Image resolution
0, // Image stream flags, e.g. near mode
2, // Number of frames to buffer
NULL, // Event handle
&rgbStream);
// --------------- END CHANGED CODE -----------------
return true;
}
BYTE* dataEnd;
USHORT* dataEndD;
void getKinectDataD(){
NUI_IMAGE_FRAME imageFrame;
NUI_LOCKED_RECT LockedRect;
if (sensor->NuiImageStreamGetNextFrame(rgbStream, 0, &imageFrame) < 0) return;
INuiFrameTexture* texture = imageFrame.pFrameTexture;
texture->LockRect(0, &LockedRect, NULL, 0);
const USHORT* curr = (const USHORT*)LockedRect.pBits;
const USHORT* dataEnding = curr + (width*height);
if (LockedRect.Pitch != 0)
{
const BYTE* curr = (const BYTE*)LockedRect.pBits;
dataEnd = (BYTE*)(curr + (width*height) * 4);
}
while (curr < dataEnding) {
// Get depth in millimeters
USHORT depth = NuiDepthPixelToDepth(*curr++);
dataEndD = (USHORT*)depth;
// Draw a grayscale image of the depth:
// B,G,R are all set to depth%256, alpha set to 1.
}
texture->UnlockRect(0);
sensor->NuiImageStreamReleaseFrame(rgbStream, &imageFrame);
}
// This example assumes that the application provides
// void* cameraFrameBuffer, a buffer for an image, and that there is a method
// to fill the buffer with data from a camera, for example
// cameraObj.ProcessIO(cameraFrameBuffer)
int main(){
initKinect();
// Create an instance of a face tracker
IFTFaceTracker* pFT = FTCreateFaceTracker();
if (!pFT)
{
// Handle errors
}
// Initialize cameras configuration structures.
// IMPORTANT NOTE: resolutions and focal lengths must be accurate, since it affects tracking precision!
// It is better to use enums defined in NuiAPI.h
// Video camera config with width, height, focal length in pixels
// NUI_CAMERA_COLOR_NOMINAL_FOCAL_LENGTH_IN_PIXELS focal length is computed for 640x480 resolution
// If you use different resolutions, multiply this focal length by the scaling factor
FT_CAMERA_CONFIG videoCameraConfig = { 640, 480, NUI_CAMERA_COLOR_NOMINAL_FOCAL_LENGTH_IN_PIXELS };
// Depth camera config with width, height, focal length in pixels
// NUI_CAMERA_COLOR_NOMINAL_FOCAL_LENGTH_IN_PIXELS focal length is computed for 320x240 resolution
// If you use different resolutions, multiply this focal length by the scaling factor
FT_CAMERA_CONFIG depthCameraConfig = { 320, 240, NUI_CAMERA_DEPTH_NOMINAL_FOCAL_LENGTH_IN_PIXELS };
// Initialize the face tracker
HRESULT hr = pFT->Initialize(&videoCameraConfig, &depthCameraConfig, NULL, NULL);
if (FAILED(hr))
{
// Handle errors
}
// Create a face tracking result interface
IFTResult* pFTResult = NULL;
hr = pFT->CreateFTResult(&pFTResult);
if (FAILED(hr))
{
// Handle errors
}
// Prepare image interfaces that hold RGB and depth data
IFTImage* pColorFrame = FTCreateImage();
IFTImage* pDepthFrame = FTCreateImage();
if (!pColorFrame || !pDepthFrame)
{
// Handle errors
}
// Attach created interfaces to the RGB and depth buffers that are filled with
// corresponding RGB and depth frame data from Kinect cameras
pColorFrame->Attach(640, 480, dataEnd, FTIMAGEFORMAT_UINT8_R8G8B8, 640 * 3);
pDepthFrame->Attach(320, 240, dataEndD, FTIMAGEFORMAT_UINT16_D13P3, 320 * 2);
// You can also use Allocate() method in which case IFTImage interfaces own their memory.
// In this case use CopyTo() method to copy buffers
FT_SENSOR_DATA sensorData;
sensorData.ZoomFactor = 1.0f; // Not used must be 1.0
bool isFaceTracked = false;
// Track a face
while (true)
{
// Call Kinect API to fill videoCameraFrameBuffer and depthFrameBuffer with RGB and depth data
getKinectDataD();
// Check if we are already tracking a face
if (!isFaceTracked)
{
// Initiate face tracking.
// This call is more expensive and searches the input frame for a face.
hr = pFT->StartTracking(&sensorData, NULL, NULL, pFTResult);
if (SUCCEEDED(hr))
{
isFaceTracked = true;
}
else
{
// No faces found
isFaceTracked = false;
}
}
else
{
// Continue tracking. It uses a previously known face position.
// This call is less expensive than StartTracking()
hr = pFT->ContinueTracking(&sensorData, NULL, pFTResult);
if (FAILED(hr))
{
// Lost the face
isFaceTracked = false;
}
}
// Do something with pFTResult like visualize the mask, drive your 3D avatar,
// recognize facial expressions
}
// Clean up
pFTResult->Release();
pColorFrame->Release();
pDepthFrame->Release();
pFT->Release();
return 0;
}
We figured it out we used the wrong dll indeed, it runs without errors now. But we ran in to an another problem, we have no clue how to use the pFTResult and retrieve the face angles with use of "getFaceRect". Does somebody know how?

Error adding images to CImageList(MFC)

I am adding images to a CImageList using the following code:
CImageList ImageList;
ImageList.Create(64, 64, ILC_COLOR32, 0, 1);
Find image path and load image . . .
HBITMAP hBitmap = LoadBitmapFromFile(finder.GetFilePath(), NULL, 64, 64);
int nImage = ImageList.Add(CBitmap::FromHandle(hBitmap), RGB(0,0,0));
HBITMAP LoadBitmapFromFile(const char* pszFilePath, HDC hDC, long lMaxHeight, long lMaxWidth)
{
// Macro that MFC needs to manage its state within a DLL
AFX_MANAGE_STATE(AfxGetStaticModuleState())
// The item object which will be used to read in the file
CxImage image;
// Load the image from the file
if(image.Load(pszFilePath))
{
ResizeImage(image, lMaxHeight, lMaxWidth);
// Get a handle to a bitmap version of the image which the given DC can use
return image.MakeBitmap(hDC);
}
return NULL;
}
void ResizeImage(CxImage& image, long lMaxHeight, long lMaxWidth)
{
const DWORD ulImgHeight = image.GetHeight();
const DWORD ulImgWidth = image.GetWidth();
long nHeightDif = ulImgHeight - lMaxHeight;
long nWidthDif = ulImgWidth - lMaxWidth;
if(nHeightDif > 0 || nWidthDif > 0)
{
double rScaleFactor = 1.0;
if(nHeightDif > nWidthDif)
rScaleFactor = (double)lMaxHeight / (double)ulImgHeight;
else
rScaleFactor = (double)lMaxWidth / (double)ulImgWidth;
long nNewHeight = (long)(ulImgHeight * rScaleFactor);
long nNewWidth = (long)(ulImgWidth * rScaleFactor);
image.Resample2(nNewWidth, nNewHeight);
}
}
The Add method appears to add the image but will repeatedly return the same index value for the new image. When the image list is displayed in a list box, the same image appears for all images that were added and returned the same index, but the filename appearing below the image on the list is correct.
I have tried several things to determine wnat is happening all to no avail. This problem does not appear to be tied to the image size, or shape (h. vs. w.). I have verified that the correct image is attached to the HBITMAP that the image is loaded onto by displaying the image on a picture control, but the image on the list control is incorrect.
If I add the images using:
int nImage = ImageList.Add(CBitmap::FromHandle(hBitmap), (CBitmap *)NULL);
none of the duplicated images are loaded. Instead of the repeating index Add returns -1. I can find no documentation for the errors on a CImageList. Does anyone know what might be happening?