FreeImage: why does it not work with cairo? - c++

Here is the code:
bool bLoaded = false;
FreeImage_Initialise();
FIBITMAP* img = FreeImage_Load(FIF_PNG, "imageSave.png", 0);
FreeImage_Unload(img);
FreeImage_DeInitialise();
int w, h;
//cr = cairo_create(image);
cairo_surface_t *image = cairo_image_surface_create_from_png("/root/test1/FreeImage/imageSave.png");
w = cairo_image_surface_get_width(image);
h = cairo_image_surface_get_height(image);
cout << "width " << w << " height " << h;
cairo_surface_write_to_png(image, "image2.png");
cairo_surface_destroy(image);
When I use FreeImage, the output of width and heigt is always 0, but when I comment this 4 line, the cairo works
FreeImage_Initialise();
FIBITMAP* img = FreeImage_Load(FIF_PNG, "imageSave.png", 0);
FreeImage_Unload(img);
FreeImage_DeInitialise();
How can I use this both library? Please help!

Related

How to convert screenshot to uint8_t array

I'm trying to somehow get screenshot from uint8 array of RGB, but for example this code doesn't work:
#include <torch/torch.h>
#include <iostream>
#include <Windows.h>
#include <gdiplus.h>
#include <gdipluspixelformats.h> // PixelFormat24bppRGB
#include <vector>
#include <cstdlib>
#pragma comment(lib, "gdiplus.lib")
int main()
{
Gdiplus::GdiplusStartupInput input;
ULONG_PTR token;
Gdiplus::GdiplusStartup(&token, &input, NULL);
const int mWidth = 1920;
const int mHeight = 1080;
std::vector<uint8_t> pixels;
Gdiplus::BitmapData bmpData;
DWORD start = GetTickCount64();
HDC hdcScreen = GetDC(NULL);
BITMAPINFO bmpInfo;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = mWidth;
bmpInfo.bmiHeader.biHeight = mHeight;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = BI_RGB;
HDC scComDC = CreateCompatibleDC(hdcScreen);
BitBlt(
scComDC,
0,0,
mWidth,
mHeight,
hdcScreen,
0,0,
SRCCOPY
);
LPDWORD lpPixel;
HBITMAP display = CreateDIBSection(scComDC, &bmpInfo, DIB_RGB_COLORS, (void**)&lpPixel, NULL, 0);
ReleaseDC(NULL,hdcScreen);
DeleteDC(scComDC);
LOGPALETTE lpPalette;
lpPalette.palVersion = 0x0300;
lpPalette.palNumEntries = 1;
lpPalette.palPalEntry[0].peRed =
lpPalette.palPalEntry[0].peGreen =
lpPalette.palPalEntry[0].peBlue =
lpPalette.palPalEntry[0].peFlags = NULL;
HPALETTE hPalette = CreatePalette(&lpPalette);
auto image = Gdiplus::Bitmap::FromHBITMAP(display, hPalette);
int bWidth = image->GetWidth();
int bHeight = image->GetHeight();
std::cout << image << std::endl;
std::cout << bWidth << std::endl;
std::cout << bHeight << std::endl;
auto stride = 3 * bWidth;
pixels.resize(stride * bHeight);
Gdiplus::Rect rect(0, 0, bWidth, bHeight);
image->LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat24bppRGB, &bmpData);
for (int y = 0; y < bHeight; ++y) {
memcpy(pixels.data() + y * stride, (byte*)bmpData.Scan0 + y * bmpData.Stride, stride);
}
image->UnlockBits(&bmpData);
DWORD end = GetTickCount64();
std::cout << end - start << "ms\n";
while (true){
int inint;
std::cin >> inint;
if (inint == -1) {
break;
}
std::cout << ">> " << +pixels[inint*3]
<< "," << +pixels[inint * 3 + 1]
<< "," << +pixels[inint * 3 + 2]
<< "\n";
}
Gdiplus::GdiplusShutdown(token);
//system("PAUSE");
return 1;
}
I cannot successfully convert pixels to vector by running this program. It returns 0,0,0 indicating that all pixels are black.
I think I'm right around memcpy, since I was able to array successfully with
auto image = Gdiplus::Bitmap::FromFile(L"C:\sample.jpg");
but when I use Bitmap::FromHBITMAP(display, hPalette);, it doesn't work at all.
get screenshot from uint8 array of RGB

cannot work out why SDL2 streaming texture is black

I am trying to draw individual pixels to an SDL2 streaming texture. I am attempting to store my pixels in a std::vector and then lock my texture, update the texture then unlock, pass it to the renderer and the present it.
However, I am always getting a black screen. I have tried several permutations of the below code but I am at a loss.
#include "pch.h"
#include "Window.h"
Window::Window(unsigned int width, unsigned int height) :
m_width(width), m_height(height)
{
if (SDL_Init(SDL_INIT_VIDEO || SDL_INIT_TIMER) < 0)
{
std::cout << "SDL failed to initilize correct. Error: "
<< SDL_GetError << std::endl;
}
m_window = SDL_CreateWindow("Cotton Rasterizer - Hardeep Bahia 2021", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_width, m_height, 0);
if (m_window == NULL)
{
std::cout << "Window failed to initilize: " << SDL_GetError << std::endl;
}
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_TARGETTEXTURE);
if (m_renderer == NULL)
{
std::cout << "Renderer failed to initilize: " << SDL_GetError << std::endl;
}
m_texture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, m_width, m_height);
if (m_texture == NULL)
{
std::cout << "Texture failed to initilize: " << SDL_GetError << std::endl;
}
auto p_format = SDL_GetWindowPixelFormat(m_window);
m_pixel_format = SDL_AllocFormat(p_format);
}
Window::~Window()
{
SDL_FreeFormat(m_pixel_format);
SDL_DestroyTexture(m_texture);
SDL_DestroyRenderer(m_renderer);
SDL_DestroyWindow(m_window);
}
void Window::test()
{
SDL_Rect filledRect = { m_width / 4, m_height / 4, m_width / 2, m_height / 2 };
SDL_SetRenderDrawColor(m_renderer, 255, 0, 0, 255);
SDL_RenderFillRect(m_renderer, &filledRect);
}
void Window::present()
{
SDL_RenderPresent(m_renderer);
}
void Window::clear()
{
SDL_SetRenderDrawColor(m_renderer, 0.f, 0.f, 0.f, 255.f);
SDL_RenderClear(m_renderer);
}
void Window::draw(const std::vector<Pixel>& i_pixels)
{
int pitch {(m_width * 4)};
std::vector<Uint32> pixels(m_width * m_height * 4, 0);
Uint32 color = SDL_MapRGBA(m_pixel_format, 255, 255, 255, 255);
for (auto& a : i_pixels)
{
unsigned int offset = (m_width * 4 * a.m_position.y) + a.m_position.x * 4;
pixels[offset + 0] = 255;
pixels[offset + 1] = 255;
pixels[offset + 2] = 255;
pixels[offset + 3] = 255;
}
unsigned char* locked_pixels{};
SDL_LockTexture(m_texture, NULL, reinterpret_cast<void **> (&locked_pixels) , &pitch);
std::memcpy(locked_pixels, pixels.data(), pixels.size());
SDL_UpdateTexture(m_texture, NULL, pixels.data(), pitch);
SDL_UnlockTexture(m_texture);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
}
My test function does draw, and is visible on the screen but it does not use the texture.
Resolved it by changing the draw function to as follow:
void Window::draw(const std::vector<Pixel>& i_pixels)
{
std::vector<unsigned char>pixels(m_width * m_height * 4, 0);
for (auto& i : i_pixels)
{
unsigned int x = i.m_position.x;
unsigned int y = i.m_position.y;
const unsigned int offset = (m_width * 4 * y) + (x * 4);
pixels[offset] = 255;
pixels[offset + 1] = 255;
pixels[offset + 2] = 255;
pixels[offset + 3] = 255;
}
unsigned char* lockedpixels = nullptr;
int pitch = (m_width * 4);
SDL_LockTexture(m_texture, NULL, reinterpret_cast<void**>(&lockedpixels), &pitch);
std::memcpy(lockedpixels, pixels.data(), pixels.size());
SDL_UpdateTexture(m_texture, NULL, pixels.data(), m_width * 4);
SDL_UnlockTexture(m_texture);
SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
}

OpenCV c++ hwnd2mat(screenshot) -> blobFromImage : Error

I am working on screen capture object recognition system.
My code:
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/dnn.hpp"
#include <opencv2/core/utils/trace.hpp>
#include <Windows.h>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::dnn;
Mat hwnd2mat(HWND hwnd) {
HDC hwindowDC,hwindowCompatibleDC;
int height,width,srcheight,srcwidth;
HBITMAP hbwindow;
Mat src;
BITMAPINFOHEADER bi;
hwindowDC=GetDC(hwnd);
hwindowCompatibleDC=CreateCompatibleDC(hwindowDC);
SetStretchBltMode(hwindowCompatibleDC,COLORONCOLOR);
RECT windowsize; // get the height and width of the screen
GetClientRect(hwnd, &windowsize);
srcheight = windowsize.bottom;
srcwidth = windowsize.right;
height = windowsize.bottom/1; //change this to whatever size you want to resize to
width = windowsize.right/1;
src.create(height,width,CV_8UC4);
// create a bitmap
hbwindow = CreateCompatibleBitmap( hwindowDC, width, height);
bi.biSize = sizeof(BITMAPINFOHEADER); //http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
bi.biWidth = width;
bi.biHeight = -height; //this is the line that makes it draw upside down or not
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// use the previously created device context with the bitmap
SelectObject(hwindowCompatibleDC, hbwindow);
// copy from the window device context to the bitmap device context
StretchBlt( hwindowCompatibleDC, 0,0, width, height, hwindowDC, 0, 0,srcwidth,srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
GetDIBits(hwindowCompatibleDC,hbwindow,0,height,src.data,(BITMAPINFO *)&bi,DIB_RGB_COLORS); //copy from hwindowCompatibleDC to hbwindow
// avoid memory leak
DeleteObject (hbwindow);
DeleteDC(hwindowCompatibleDC);
ReleaseDC(hwnd, hwindowDC);
return src;
}
string CLASSES[] = {"background", "aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair", "cow", "diningtable",
"dog", "horse", "motorbike", "person", "pottedplant", "sheep",
"sofa", "train", "tvmonitor"};
float confidenceThreshold = 0.2;
int main(int argc, char **argv) {
CV_TRACE_FUNCTION();
String modelTxt = "resources/Caffe/MobileNetSSD_deploy.prototxt";
String modelBin = "resources/Caffe/MobileNetSSD_deploy.caffemodel";
Net net = readNetFromCaffe(modelTxt, modelBin);
if (net.empty()) {
std::cerr << "Can't load network by using the following files: " << std::endl;
std::cerr << "prototxt: " << modelTxt << std::endl;
std::cerr << "caffemodel: " << modelBin << std::endl;
exit(-1);
}
HWND hwndDesktop = GetDesktopWindow();
// namedWindow("output", WINDOW_NORMAL); // Zeby mozna bylo zmieniac rozmiar okna "real-time"
int key = 0;
// while( key != 27 ) {
Mat frame = hwnd2mat(hwndDesktop);
// resize(frame, frame, Size(800, 450));
// Mat frame = imread("resources/auto.png");
Mat img2;
resize(frame, img2, Size(300,300));
Mat inputBlob = blobFromImage(img2, 0.007843, Size(300,300), Scalar(127.5, 127.5, 127.5), false);
net.setInput(inputBlob, "data");
Mat detection = net.forward("detection_out");
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
ostringstream ss;
for (int i = 0; i < detectionMat.rows; i++) {
float confidence = detectionMat.at<float>(i, 2);
if (confidence > confidenceThreshold) {
int idx = static_cast<int>(detectionMat.at<float>(i, 1));
int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);
int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);
int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);
int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);
Rect object((int)xLeftBottom, (int)yLeftBottom,
(int)(xRightTop - xLeftBottom),
(int)(yRightTop - yLeftBottom));
rectangle(frame, object, Scalar(0, 255, 0), 2);
cout << CLASSES[idx] << ": " << confidence << endl;
ss.str("");
ss << confidence;
String conf(ss.str());
String label = CLASSES[idx] + ": " + conf;
int baseLine = 0;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
putText(frame, label, Point(xLeftBottom, yLeftBottom-10),
FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0,255,0));
}
}
imshow("output", frame);
// key = waitKey(60);
waitKey();
// }
}
When i use exteranl image everything works fine but when i use function called hwnd2mat it throws me exception:
Error: Assertion failed (inputs[0]->size[1] % blobs[0].size[1] == 0) in forward
I don't know what does it mean. I tried to resize image but it doesnt work.
I am using OpenCV-3.4.1 and MobileNetSSD model.
Thanks in advance.
Ok, i finally did it!
Code for taking screenshots:
Mat getScreenshot() {
HWND hwnd = GetDesktopWindow();
HDC hwindowDC,hwindowCompatibleDC;
int height,width,srcheight,srcwidth;
HBITMAP hbwindow;
Mat src;
BITMAPINFOHEADER bi;
hwindowDC=GetDC(hwnd);
hwindowCompatibleDC=CreateCompatibleDC(hwindowDC);
SetStretchBltMode(hwindowCompatibleDC,COLORONCOLOR);
RECT windowsize; // get the height and width of the screen
GetClientRect(hwnd, &windowsize);
srcheight = windowsize.bottom;
srcwidth = windowsize.right;
height = windowsize.bottom/1; //change this to whatever size you want to resize to
width = windowsize.right/1;
src.create(height,width,CV_8UC3); // This was problem
// create a bitmap
int iBits = GetDeviceCaps(hwindowDC, BITSPIXEL) * GetDeviceCaps(hwindowDC, PLANES);
WORD wBitCount;
if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else
wBitCount = 24;
hbwindow = CreateCompatibleBitmap( hwindowDC, width, height);
bi.biSize = sizeof(BITMAPINFOHEADER); //http://msdn.microsoft.com/en-us/library/windows/window/dd183402%28v=vs.85%29.aspx
bi.biWidth = width;
bi.biHeight = -height; //this is the line that makes it draw upside down or not
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 256;
bi.biClrImportant = 0;
// use the previously created device context with the bitmap
SelectObject(hwindowCompatibleDC, hbwindow);
// copy from the window device context to the bitmap device context
StretchBlt( hwindowCompatibleDC, 0,0, width, height, hwindowDC, 0, 0,srcwidth,srcheight, SRCCOPY); //change SRCCOPY to NOTSRCCOPY for wacky colors !
GetDIBits(hwindowCompatibleDC,hbwindow,0,height,src.data,(BITMAPINFO *)&bi,DIB_RGB_COLORS); //copy from hwindowCompatibleDC to hbwindow
// avoid memory leak
DeleteObject (hbwindow);
DeleteDC(hwindowCompatibleDC);
ReleaseDC(hwnd, hwindowDC);
return src;
}

SDL2: libpng error: IDAT: chunk data is too large

I'm following this tutorial on SDL2 for GameDev and I have run into this error while attempting to load PNG.
Here is my code:
void Game::Init(const char * title, int x_pos, int y_pos, int width, int height, bool fullscreen)
{
int flags = 0;
if (fullscreen) {
flags = SDL_WINDOW_FULLSCREEN;
}
if (SDL_Init(SDL_INIT_EVERYTHING) == 0) {
std::cout << "Subsystems Initialized" << std::endl;
window = SDL_CreateWindow(title, x_pos, y_pos, width, height, flags);
if (window) {
std::cout << "Window Created..." << std::endl;
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
std::cout << "Renderer Created..." << std::endl;
}
is_running = 1;
}
SDL_Surface * buf_surface = IMG_Load("assets/potato.png");
std::cout << SDL_GetError() << std::endl;
potato_texture = SDL_CreateTextureFromSurface(renderer, buf_surface);
SDL_FreeSurface(buf_surface);
}
This is the error:
libpng error: IDAT: chunk data is too large
Error reading the PNG file.
Any suggestions?
PS this is my first time posting sorry if I did anything wrong.

How do I draw a transparent or semi-transparent rectangle on top of an opaque one in SDL2?

Here's my code to draw SDL_Rect objects rect and rect2:
#include <iostream>
#include <SDL2/SDL.h>
int main(){
SDL_Window *window= SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);
if(window == 0)
std::cout << SDL_GetError() << std::endl;
SDL_Renderer *renderer= SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(renderer == NULL)
std::cout << SDL_GetError() << std::endl;
SDL_Rect rect;
rect.x= 100;
rect.y= 100;
rect.w= 100;
rect.h= 100;
SDL_Rect rect2;
rect2.x= 150;
rect2.y= 150;
rect2.w= 100;
rect2.h= 100;
while(true){
Uint8 r,g,b,a;
r= 32;
g= 32;
b= 32;
a= 255;
if(SDL_SetRenderDrawColor(renderer, r, g, b, a) == -1)
std::cout << SDL_GetError() << std::endl;
if(SDL_RenderClear(renderer) == -1)
std::cout << SDL_GetError() << std::endl;
r= 255;
g= 255;
b= 255;
a= 255;
if(SDL_SetRenderDrawColor(renderer, r, g, b, a) == -1)
std::cout << SDL_GetError() << std::endl;
if(SDL_RenderFillRect(renderer, &rect) == -1)
std::cout << SDL_GetError() << std::endl;
r= 100;
g= 100;
b= 100;
a= 0;
if(SDL_SetRenderDrawColor(renderer, r, g, b, a) == -1)
std::cout << SDL_GetError() << std::endl;
if(SDL_RenderFillRect(renderer, &rect2) == -1)
std::cout << SDL_GetError() << std::endl;
SDL_RenderPresent(renderer);
}
return 0;
}
While I can draw rect to SDL_Renderer object renderer just fine, if I add rect2 it is always opaque, blocking view of rect. Even though I set rect2's alpha to 0, it still shows up opaque, blocking rect from view.
How do I fix this so rect2 is more transparent?
All you need to do is call
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
after creating your renderer to enable alpha blending with RenderDraw functions. (SDL documentation)