SDL2 SDL_GetWindowSurface returns surface with unknown pixel format - window

Not sure why the SDL_GetWindowSurface is returning a surface with an unknown pixel format.
Outputs:
Window pixel format SDL_PIXELFORMAT_RGB888
Surface pixel format SDL_PIXELFORMAT_UNKNOWN
Code follows:
char message[256]="";
SDL_Rect rc;
SDL_Window *myWindow;
SDL_Renderer *myRenderer;
SDL_Surface *mySurface;
SDL_Texture *myTexture;
rc.x=100;
rc.y=100;
rc.w=CWState->WindowSize.x;
rc.h=CWState->WindowSize.y;
//Initialize SDL
if(SDL_Init(SDL_INIT_VIDEO) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
return false;
}
myWindow = SDL_CreateWindow("myWindow", rc.x, rc.y, rc.w, rc.h, 0);
mySurface = SDL_GetWindowSurface( myWindow );
myRenderer = SDL_CreateRenderer(myWindow, -1, SDL_RENDERER_PRESENTVSYNC);
myTexture = SDL_CreateTexture(myRenderer,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMING,rc.w, rc.h);
SDL_SetTextureBlendMode(myTexture,SDL_BLENDMODE_NONE);
sprintf(message, "Window pixel format %s\n", SDL_GetPixelFormatName(SDL_GetWindowPixelFormat(myWindow)));
puts(message);
sprintf(message, "Surface pixel format %s\n", SDL_GetPixelFormatName(mySurface->format));
puts(message);
Also if my Window pixel format is RGB888 should I create the texture with the same format to avoid conversions?

Related

How do find out the width and height of the text without using surface in SDL2?

I wanted to create a separate function where I could just send a string and it will render the text appropriately so that I didn't need to copy-paste same stuff. The function I came up with is in the following.
void renderText(SDL_Renderer* renderer, char* text,
char* font_name, int font_size,
SDL_Color color, SDL_Rect text_area)
{
/* If TTF was not initialized initialize it */
if (!TTF_WasInit()) {
if (TTF_Init() < 0) {
printf("Error initializing TTF: %s\n", SDL_GetError());
return EXIT_FAILURE;
}
}
TTF_Font* font = TTF_OpenFont(font_name, font_size);
if (font == NULL) {
printf("Error opening font: %s\n", SDL_GetError());
return;
}
SDL_Surface* surface = TTF_RenderText_Blended(font, text, color);
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (!texture) {
printf("error creating texture: %s\n", SDL_GetError());
TTF_CloseFont(font);
return;
}
SDL_RenderCopy(renderer, message, NULL, &text_area);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
TTF_CloseFont(font);
}
Now, sometimes I want to align the text with the window for which I need to know the height and width of the surface that contains the text so that I can use something like (WINDOW_WIDTH - surfaceText->w) / 2 or (WINDOW_HEIGHT - surfaceText->h) / 2. But there is no way to know the height and width of the surface containing the text without creating the surface. And if I end up needing to create the surface then the separation of this function would not live upto its objective.
How do I find out the height and width of the surface containing the text without actually creating the surface in SDL2_ttf library?
You can pass the string to the TTF_SizeText() function, which is defined:
int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h)
The documentation for this function states:
Calculate the resulting surface size of the LATIN1 encoded text rendered using font. No actual rendering is done, however correct kerning is done to get the actual width. The height returned in h is the same as you can get using 3.3.10 TTF_FontHeight.
Then, once you have the dimensions of the string, you can call your rendering function with the necessary information to align it.
There are also TTF_SizeUTF8() and TTF_SizeUNICODE() versions for different encodings.

Unexpected failure when using XCreateImage with LodePNG

I am trying to add a background image to a X11 window, in Linux. I use the simple LodePNG to decode the PNG image into raw data (RGBA) then I try to set the window background.
What happens is that the window shows up for a while then it unexpectedly closes back. If I comment out the XCreateImage and XPutImage function (including the destructors) the window shows up correctly, so the window creation is not a problem.
My code looks like this:
// Headers here (xlib, lodepng) ...
// Global vars ...
Display *display;
Window window;
int window_width = 640;
int window_height = 480;
// Entry point, initialization, window creation ...
int main(int argc, char* argv[]) {
vector<unsigned char> image; //the raw pixels
unsigned width, height;
// Decode
unsigned error = lodepng::decode(image, width, height, "bg.png");
// If there's no error continue
if(!error)
{
Pixmap pixmap = XCreatePixmap
(
display,
XDefaultRootWindow(display),
width,
height,
DefaultDepth(display, 0)
);
XGCValues gr_values;
GC gr_context = XCreateGC
(
display,
window,
GCBackground,
&gr_values
);
// Here is where it fails !!!
unsigned rowbytes = 0;
XImage *ximage = XCreateImage
(
display,
CopyFromParent,
32,
XYPixmap,
0,
(char*)image.data(),
width,
height,
32,
rowbytes
);
XPutImage(
display,
pixmap,
gr_context,
ximage,
0, 0,
0, 0,
window_width,
window_height
);
XSetWindowBackgroundPixmap(display, window, pixmap);
XFreePixmap(display, pixmap);
XFreeGC(display, gr_context);
XDestroyImage(ximage);
}
}
After I decode the PNG I can see that I get the correct width and height of the image. The size of the raw data (image variable) is always 819200, no matter what image I choose, which is a bit weird and I wonder if LodePNG is not loading the image correctly (yet it gives no error and correct width and height). Other causes of this problem, I don't know. I don't get any error message, the window just closes after being saw a little bit. Maybe some of the arguments of XCreateImage is wrong but I can't figure out which.

load then write image

I read image using opencv and save it again, but when I read it later the data not be the same, that I mean after I read the image I save it, then copy the saved image and read the data inside this image but the data will not the same as before, I write small code to do the following
1- read image
2- save the image
3- save image data into text file
4- read the saved image fro step 2
5- compare the values of the image to the values of the text file and print them together
my code is
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <time.h>
#include <stdint.h>
#include "highgui.h"
IplImage *PlainImage=0,*CipherImage=0,*DecPlainImage=0;
void func_printimage()
{
// create a window
cvNamedWindow("Plain Image",CV_WINDOW_AUTOSIZE);
cvMoveWindow("Plain Image", 800, 600);
// show the image
cvShowImage("Plain Image", PlainImage );
// wait for a key
cvNamedWindow("Cipher Image",CV_WINDOW_AUTOSIZE);
cvMoveWindow("Cipher Image", 800, 600);
// show the image
cvShowImage("Cipher Image", CipherImage );
cvSaveImage("CipherImage.jpg",CipherImage,0);
cvWaitKey(0);
}
int main()
{
//i j and k used as counters
int i,j,step,dep,k,ch,L,C,P,sum=0;
uchar *data_byte;
//Define CPU time parameters for each Layer
PlainImage=cvLoadImage("PlainImage.jpg",3);
CipherImage=cvLoadImage("PlainImage.jpg",3);
L = PlainImage->height;
C = PlainImage->width;
P = PlainImage->nChannels;
step = PlainImage->widthStep;
data_byte=CipherImage->imageData;
printf("Image Information are:\nL=%d\n",L);
printf("C=%d\n",C);
printf("P=%d\n",P);
system("pause");
FILE *f1;
f1 = fopen ("cipher1.txt", "wt");
fprintf(f1,"%d\t%d\t%d\t%d\t",L,C,P,CipherImage->depth);
for(k=0;k<L*C*P;k++)
{
fprintf(f1,"%d\t",data_byte[k]);
}
fclose (f1);
func_printimage();
for(k=0;k<L*C*P;k++)
{
data_byte[k]=0;
}
f1 = fopen ("cipher1.txt", "rt");
fscanf (f1,"%d", &L);
fscanf (f1,"%d", &C);
fscanf (f1,"%d", &P);
fscanf (f1,"%d", &dep);
CipherImage=cvLoadImage("CipherImage.jpg",3);
data_byte=CipherImage->imageData;
printf("Image Information are:\nL=%d\n",L);
printf("C=%d\n",C);
printf("P=%d\n",P);
system("pause");
for(k=0;k<L*C*P;k++)
{
fscanf (f1,"%d", &i);
sum+=abs(i-data_byte[k]);
printf("i=%d data=%d\n",i,data_byte[k]);
}
printf("difference=%d\n",sum);
fclose (f1);
system("pause");
return 0;
}
//End of the main Program
jpg images use Lossy Compression.
You should use png images.
Here in this post i will show you that how to Load an image from your chosen directory and then convert it into gray color, and then store the new one(modified) image in a directory C:\Images.
The code is given below:
#include <cv.h>
#include <highgui.h>,
using namespace cv;
int main( )
{
Mat img;
img = imread(“C:\\prado.jpg”, 1 );
if( !img.data )
{
printf( ” No image data \n ” );
return -1;
}
else
prinf(“Your program is working well”);
Mat gray_image;
cvtColor( img, gray_image, CV_RGB2GRAY );
imwrite( “C://images/Gray_Image.jpg”, gray_image);
imshow( “real image”, img);
imshow( “Gray image”, gray_image);
waitKey(0);
return 0;
}
EXPLANATION:
Mat img = imread(“C:\\prado.jpg”, 1 );
this means to get image from my directory and store it in Mat object which is “img” here, actually Mat object store the data of any image.
cvtColor( img, gray_image, CV_RGB2GRAY );
This line convert the originial (RGB) into other color image(GRAY)
imwrite( “C://images/Gray_Image.jpg”, gray_image);
This one store the new modified image which have been store in Mat object “gray_image” in the directory C://images/ you can chose your own directory

UINT16 monochrome image to 8bit monochrome Qimage using freeImage

I want to convert a UINT16 monochrome image to a 8 bits image, in C++.
I have that image in a
char *buffer;
I'd like to give the new converted buffer to a QImage (Qt).
I'm trying with freeImagePlus
fipImage fimage;
if (fimage.loadfromMemory(...) == false)
//error
loadfromMemory needs a fipMemoryIO adress:
loadfromMemory(fipMemoryIO &memIO, int flag = 0)
So I do
fipImage fimage;
BYTE *buf = (BYTE*)malloc(gimage.GetBufferLength() * sizeof(BYTE));
// 'buf' is empty, I have to fill it with 'buffer' content
// how can I do it?
fipMemoryIO memIO(buf, gimage.GetBufferLength());
fimage.loadFromMemory(memIO);
if (fimage.convertTo8Bits() == true)
cout << "Good";
Then I would do something like
fimage.saveToMemory(...
or
fimage.saveToHandle(...
I don't understand what is a FREE_IMAGE_FORMAT, which is the first argument to any of those two functions. I can't find information of those types in the freeImage documentation.
Then I'd finish with
imageQt = new QImage(destiny, dimX, dimY, QImage::Format_Indexed8);
How can I fill 'buf' with the content of the initial buffer?
And get the data from the fipImage to a uchar* data for a QImage?
Thanks.
The conversion is simple to do in plain old C++, no need for external libraries unless they are significantly faster and you care about such a speedup. Below is how I'd do the conversion, at least as a first cut. The data is converted inside of the input buffer, since the output is smaller than the input.
QImage from16Bit(void * buffer, int width, int height) {
int size = width*height*2; // length of data in buffer, in bytes
quint8 * output = reinterpret_cast<quint8*>(buffer);
const quint16 * input = reinterpret_cast<const quint16*>(buffer);
if (!size) return QImage;
do {
*output++ = *input++ >> 8;
} while (size -= 2);
return QImage(output, width, height, QImage::Format_Indexed8);
}

Not able to capture image Opencv

Not able to capture Image, works in other laptop, my webcam is not able to open.But it works in other laptop.The output is "Error:Capture is Null"
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
// A Simple Camera Capture Framework
int main() {
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
if ( !capture ) {
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}
// Create a window in which the captured images will be presented
cvNamedWindow( "mywindow", CV_WINDOW_AUTOSIZE );
// Show the image captured from the camera in the window and repeat
while ( 1 ) {
// Get one frame
IplImage* frame = cvQueryFrame( capture );
if ( !frame ) {
fprintf( stderr, "ERROR: frame is null...\n" );
getchar();
break;
}
cvShowImage( "mywindow", frame );
// Do not release the frame!
//If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
//remove higher bits using AND operator
if ( (cvWaitKey(10) & 255) == 27 ) break;
}
// Release the capture device housekeeping
cvReleaseCapture( &capture );
cvDestroyWindow( "mywindow" );
return 0;
}
You may try different numbers in the place of CV_CAP_ANY.
It is also possible that your OpenCV is not installed appropriately, then you should reinstall it with libv4l as it is suggested here.
There is a slight chance that your camera is not compatible with OpenCV.
Try passing -1 instead of CV_CAP_ANY.

Resources