I am starting with SDL, and I was reading the introduction, and I am trying the drawPixel method they have. What I am doing is a ppm viewer, so far I have the rgb values in an array and are correctly stored (i checked them by printing the array and making sure they correspond to their position in the ppm file) and I want to use SDL to draw the picture. So far the code I've written is (this is the main.cpp file, if ppm.hpp and ppm.cpp are needed please tell me so to add them)
#include <iostream>
#include <SDL/SDL.h>
#include "ppm.hpp"
using namespace std;
void drawPixel (SDL_Surface*, Uint8, Uint8, Uint8, int, int);
int main (int argc, char** argv) {
PPM ppm ("res/cake.ppm");
if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0) {
cerr << "Unable to init SDL: " << SDL_GetError() << endl;
exit(1);
}
atexit(SDL_Quit); // to automatically call SDL_Quit() when the program terminates
SDL_Surface* screen;
screen = SDL_SetVideoMode(ppm.width(), ppm.height(), 32, SDL_SWSURFACE);
if (screen == nullptr) {
cerr << "Unable to set " << ppm.width() << "x" << ppm.height() << " video: " << SDL_GetError() << endl;
exit(1);
}
for (int i = 0; i < ppm.width(); i++) {
for(int j = 0; j < ppm.height(); j++) {
drawPixel(screen, ppm.red(i,j), ppm.green(i,j), ppm.blue(i,j), i, j);
}
}
return 0;
}
void drawPixel (SDL_Surface* screen, Uint8 R, Uint8 G, Uint8 B, int x, int y) {
Uint32 color = SDL_MapRGB(screen->format, R, G, B);
if (SDL_MUSTLOCK(screen)) {
if (SDL_LockSurface(screen) < 0) {
return;
}
}
switch (screen->format->BytesPerPixel) {
case 1: { // Assuming 8-bpp
Uint8* bufp;
bufp = (Uint8*)screen->pixels + y * screen->pitch + x;
*bufp = color;
}
break;
case 2: { // Probably 15-bpp or 16-bpp
Uint16 *bufp;
bufp = (Uint16*)screen->pixels + y * screen->pitch / 2 + x;
*bufp = color;
}
break;
case 3: { // Slow 24-bpp mode, usually not used
Uint8* bufp;
bufp = (Uint8*)screen->pixels + y * screen->pitch + x;
*(bufp + screen->format->Rshift / 8) = R;
*(bufp + screen->format->Gshift / 8) = G;
*(bufp + screen->format->Bshift / 8) = B;
}
break;
case 4: { // Probably 32-bpp
Uint32* bufp;
bufp = (Uint32*)screen->pixels + y * screen->pitch / 4 + x;
*bufp = color;
}
break;
}
if (SDL_MUSTLOCK(screen)) {
SDL_UnlockSurface(screen);
}
SDL_UpdateRect(screen, x, y, 1, 1);
}
The drawPixel is as is provided by the introduction, now the ppm file I am trying to use is called cake.ppm and its 720x540, however when I build and run this code, I get the application is not responding. I tried it on a smaller ppm file which is 426x299 and it showed a window with colors being put on the window.
Why is it not working on the cake.ppm file and on others it works? Is it due to size?
When I try the ppm file, the second one 426x299 or other ppm files, the colors come totally different, why is that?
When I run the app, after the pixels are put, the window closes, how can I keep it?
Attempting at a file squares.ppm, here is what it should be:
But this is what I'm getting
Related
I have code that are to paint a BMP image on a TPaintBox on a VCL form in a C++ application.
Everything works fine as long as I only have one image to paint, on one form. When I create a second form, I get sporadic access violations.
The code is called from a thread and I'm using the Synchronize function in order to synchronize with the main VCL thread as this
void TCameraForm::loadImage(FramePtr frame)
{
syncing s;
s.aFrame = frame;
s.theForm = this;
//Synchronize with UI thread
TThread::Synchronize(0, &s.fn);
}
In the code, a FramePtr is a shared pointer to one individual 'frame', holding a device dependent bitmap.
The syncing variable is a structure, holding the code for the actual painting:
//This is a trick to use VCL's TThread::Synchronize function "with parameters"
//Thanks to Mr. R. Lebeau for sharing this trick.
struct syncing
{
FramePtr aFrame;
TCameraForm* theForm;
int tag;
void __fastcall fn()
{
try
{
//Create a device dependent bitmap
BitMap aBitMap(aFrame);
//Get the bitmap memory into a TMemoryStream
TMemoryStream* ms = new TMemoryStream();
int bytes = ms->Write(aBitmap.getBuffer()->mMemoryBuffer, aBitmap.getBuffer()->mBufferSize);
ms->Position = 0;
//Create a TPicture object that will be used for drawing on the paintbox
TBitmap* tbm = new TBitmap();
tbm->LoadFromStream(ms);
TRect stretchedRect(getStretchedDimensions(tbm->Width, tbm->Height, theForm->PaintBox1->Width, theForm->PaintBox1->Height));
theForm->PaintBox1->Canvas->StretchDraw(stretchedRect, tbm);
delete ms;
delete tbm;
}
catch(...)
{
Log(lError) << "Exception occured in the CameraFrame sync function";
}
}
};
The debugger mainly stops on creation of the bitmap.
I'm using BCC builder 10.3.2 and the classic compiler.
The bitmap class looks like this:
Header
class BitMap
{
public:
BitMap(FramePtr aFrame);
BitMap(unsigned long width, unsigned long height, ColorCode c, ImageMemoryBuffer& buf);
ImageMemoryBuffer* getBuffer();
~BitMap();
bool write(const string& file);
protected:
unsigned int mWidth;
unsigned int mHeight;
ColorCode mColorCode;
ImageMemoryBuffer mImageMemoryBuffer;
bool create();
bool release();
};
And CPP:
enum { THREE_CHANNEL = 0xC,};
enum { BMP_HEADER_SIZE = 54, };
enum { ALIGNMENT_SIZE = 4, };
namespace ai
{
BitMap::BitMap(FramePtr aFrame)
:
mWidth(0),
mHeight(0),
mColorCode(ColorCodeMono8),
mImageMemoryBuffer()
{
aFrame->GetImageSize(mImageMemoryBuffer.mBufferSize);
aFrame->GetWidth(mWidth);
aFrame->GetHeight(mHeight);
VmbPixelFormatType ePixelFormat = VmbPixelFormatMono8;
aFrame->GetPixelFormat(ePixelFormat);
if((ePixelFormat != VmbPixelFormatMono8) && (ePixelFormat != VmbPixelFormatRgb8))
{
throw(MVRException("Invalid pixel format: " + toString(ePixelFormat)));
}
mColorCode = (ePixelFormat == VmbPixelFormatRgb8) ? ColorCodeRGB24 : ColorCodeMono8;
VmbUchar_t *pImage = NULL;
if (aFrame->GetImage(pImage) != VmbErrorSuccess)
{
throw(MVRException("Failed \"getting\" image"));
}
mImageMemoryBuffer.mMemoryBuffer = (unsigned char*) pImage;
if(!create())
{
Log(lError) << "There was an error creating the bitmap";
throw(MVRException("Failed creating Bitmap"));
}
}
BitMap::BitMap(unsigned long width, unsigned long height, ColorCode c, ImageMemoryBuffer& buf)
:
mWidth(width),
mHeight(height),
mColorCode(c),
mImageMemoryBuffer(buf)
{
if(!create())
{
Log(lError) << "There was an error creating the bitmap";
throw(MVRException("Failed creating bitmap"));
}
}
BitMap::~BitMap()
{
if(!release())
{
Log(lError) << "There was an error releasing the bitmap";
}
}
ImageMemoryBuffer* BitMap::getBuffer()
{
return &mImageMemoryBuffer;
}
bool BitMap::create()
{
try
{
unsigned char nNumColors; // Number of colors of our image
unsigned char nPadLength; // The padding we need to align the bitmap ALIGNMENT_SIZE
unsigned long nPaletteSize = 0; // The size of the bitmap's palette
unsigned long nHeaderSize; // The size of the bitmap's header
unsigned long nFileSize; // The size of the bitmap file
unsigned char* pBitmapBuffer; // A buffer we use for creating the bitmap
unsigned char* pCurBitmapBuf; // A cursor to move over "pBitmapBuffer"
unsigned char* pCurSrc; // A cursor to move over the given buffer "pBuffer"
unsigned long px; // A single pixel for storing transformed color information
unsigned long x; // The horizontal position within our image
unsigned long y; // The vertical position within our image
unsigned long i; // Counter for some iteration
// The bitmap header
char fileHeader[14] = { 'B','M', // Default
0,0,0,0, // File size
0,0,0,0, // Reserved
0,0,0,0 }; // Offset to image content
char infoHeader[40] = { 40,0,0,0, // Size of info header
0,0,0,0, // Width
0,0,0,0, // Height
1,0, // Default
0, 0 }; // bpp
if ( 0 == mImageMemoryBuffer.mBufferSize || 0 == mWidth || 0 == mHeight )
{
Log(lError) << "Zero bitmap buffer, width ot height in Bitmap constructor";
return false;
}
if ( mColorCode == (mColorCode & THREE_CHANNEL) )
{
nNumColors = 3;
}
else
{
nNumColors = 1;
}
// Bitmap padding always is a multiple of four Bytes. If data is not we need to pad with zeros.
nPadLength = (mWidth * nNumColors) % ALIGNMENT_SIZE;
if ( 0 != nPadLength )
{
nPadLength = ALIGNMENT_SIZE - nPadLength;
}
if ( ColorCodeRGB24 != mColorCode )
{
nPaletteSize = 256;
}
nHeaderSize = BMP_HEADER_SIZE + nPaletteSize * 4;
pBitmapBuffer = (unsigned char*)malloc( nHeaderSize + mImageMemoryBuffer.mBufferSize + (nPadLength * mHeight) );
nFileSize = nHeaderSize + mImageMemoryBuffer.mBufferSize + (nPadLength * mHeight);
// File size
fileHeader[ 2] = (char)(nFileSize);
fileHeader[ 3] = (char)(nFileSize >> 8);
fileHeader[ 4] = (char)(nFileSize >> 16);
fileHeader[ 5] = (char)(nFileSize >> 24);
// Offset to image content
fileHeader[10] = (char)(nHeaderSize);
fileHeader[11] = (char)(nHeaderSize >> 8);
fileHeader[12] = (char)(nHeaderSize >> 16);
fileHeader[13] = (char)(nHeaderSize >> 24);
// Width
infoHeader[ 4] = (char)(mWidth);
infoHeader[ 5] = (char)(mWidth >> 8);
infoHeader[ 6] = (char)(mWidth >> 16);
infoHeader[ 7] = (char)(mWidth >> 24);
// Height (has to be negative for a top down image)
infoHeader[ 8] = (char)(-(long)mHeight);
infoHeader[ 9] = (char)(-(long)mHeight >> 8);
infoHeader[10] = (char)(-(long)mHeight >> 16);
infoHeader[11] = (char)(-(long)mHeight >> 24);
// bpp
infoHeader[14] = 8 * nNumColors;
// Image size
infoHeader[20] = (char)(mImageMemoryBuffer.mBufferSize);
infoHeader[21] = (char)(mImageMemoryBuffer.mBufferSize >> 8);
infoHeader[22] = (char)(mImageMemoryBuffer.mBufferSize >> 16);
infoHeader[23] = (char)(mImageMemoryBuffer.mBufferSize >> 24);
// Palette size
infoHeader[32] = (char)(nPaletteSize);
infoHeader[33] = (char)(nPaletteSize >> 8);
infoHeader[34] = (char)(nPaletteSize >> 16);
infoHeader[35] = (char)(nPaletteSize >> 24);
// Used colors
infoHeader[36] = (char)(nPaletteSize);
infoHeader[37] = (char)(nPaletteSize >> 8);
infoHeader[38] = (char)(nPaletteSize >> 16);
infoHeader[39] = (char)(nPaletteSize >> 24);
// Write header
pCurBitmapBuf = pBitmapBuffer;
memcpy(pCurBitmapBuf, fileHeader, 14);
pCurBitmapBuf += 14;
memcpy(pCurBitmapBuf, infoHeader, 40);
pCurBitmapBuf += 40;
for(i = 0; i < nPaletteSize; ++i)
{
pCurBitmapBuf[0] = (char)(i);
pCurBitmapBuf[1] = (char)(i);
pCurBitmapBuf[2] = (char)(i);
pCurBitmapBuf[3] = 0;
pCurBitmapBuf += 4;
}
// RGB -> BGR (a Windows bitmap is BGR)
if(mColorCode == ColorCodeRGB24)
{
pCurSrc = (unsigned char*) mImageMemoryBuffer.mMemoryBuffer;
for(y=0; y < mHeight; ++y, pCurBitmapBuf += nPadLength )
{
for (x = 0; x < mWidth; ++x, pCurSrc += 3, pCurBitmapBuf += 3)
{
px = 0;
// Create a 4 Byte structure to store ARGB (we don't use A)
px = px | (pCurSrc[0] << 16) | (pCurSrc[1] << 8) | pCurSrc[2];
// Due to endianess ARGB is stored as BGRA
// and we only have to write the first three Bytes
memcpy( pCurBitmapBuf, &px, 3 );
}
// Add padding at the end of each row
memset( pCurBitmapBuf, 0, nPadLength );
}
mColorCode = ColorCodeBGR24;
}
// Mono8
else
{
if(nPadLength == 0)
{
memcpy( pCurBitmapBuf, mImageMemoryBuffer.mMemoryBuffer, mImageMemoryBuffer.mBufferSize );
}
else
{
pCurSrc = (unsigned char*)mImageMemoryBuffer.mMemoryBuffer;
for (y=0; y < mHeight; ++y, pCurSrc += mWidth * nNumColors)
{
// Write a single row of colored pixels
memcpy( pCurBitmapBuf, pCurSrc, mWidth * nNumColors );
pCurBitmapBuf += mWidth * nNumColors;
// Write padding pixels
memset(pCurBitmapBuf, 0, nPadLength);
pCurBitmapBuf += nPadLength;
}
}
}
mImageMemoryBuffer.mMemoryBuffer = pBitmapBuffer;
mImageMemoryBuffer.mBufferSize = nFileSize;
return true;
}
catch(...)
{
Log(lError) << "Exception in creation of bitmap create function";
return false;
}
}
bool BitMap::release()
{
try
{
if (mImageMemoryBuffer.mMemoryBuffer != NULL && mImageMemoryBuffer.mBufferSize > 0)
{
free(mImageMemoryBuffer.mMemoryBuffer);
mImageMemoryBuffer.mMemoryBuffer = NULL;
}
return true;
}
catch(...)
{
return false;
}
}
bool BitMap::write(const string& fName)
{
if (mImageMemoryBuffer.mMemoryBuffer == NULL)
{
return false;
}
FILE *file = fopen(fName.c_str(), "wb");
if(!file)
{
Log(lError) << "Failed opening file: " << fName;
return false;
}
fwrite(mImageMemoryBuffer.mMemoryBuffer, 1, mImageMemoryBuffer.mBufferSize, file );
fclose(file);
return true;
}
}
UPDATE: The above code works fine when executed by one thread. The problem occurs when several threads are involved. I have located the problem happening when the memcpy function is called in the creation of the bitmap (not the TBitmap), supporting this. So main problem is that the same memory is being manipulated by two or more threads at the same time.
For the above code, where would it be appropriate to incorporate a Mutex, in order to prevent the memory corruption? Or could one use another technique?
Im using assimp to load 3D models.
My models have embedded textures ("I guess"). But I have two problems:
I can't find a way to actually get the texture file path ...
The pcData doensn't seems to be anything.
I can't not even print the width or height of the texture.
printing the texturefile I get that usual format *0 *1 and so On.
But when I try to print the scene->mTextures[atoi(texturefile.C_Str())]->mFileName I get nothing...same thing with texture pcData.
here's the code:
uint32_t textureCount = scene->mMaterials[i]->GetTextureCount(aiTextureType_DIFFUSE);
for (uint32_t c = 0; c < textureCount ; c++) {
scene->mMaterials[i]->GetTexture(aiTextureType_DIFFUSE, c, &texturefile);
std::cout << "\n textureFile : " << texturefile.C_Str() << std::endl;
std::cout <<"\nTextura : "<< scene->mTextures[atoi(texturefile.C_Str())]<<std::endl;
aiTexture *texture = scene->mTextures[atoi(texturefile.C_Str())];
int w = texture->mWidth;
int h = texture->mHeight;
if (texture == NULL) {
std::cout << "\n TextureNull\n";
}
else {
std::cout << "\n textureNotNull\n";
}
uint32_t *data = reinterpret_cast<uint32_t* >(texture->pcData);
createTextureImage(data, w, h, materials[i].texturesImages[c]);
//createTextureImageView(materials[i].texturesImagesViews[c], materials[i].texturesImages[c]);
//createTextureSampler(materials[i].texturesSamplers[c]);
// void createTextureImage(uint32_t* pixels,int texWidth,int texHeight,VkImage textureImage) {
}
}
When working with the lastest master the following code shall work for you:
aiMaterial material = scene->mMaterials[index];
aiString texture_file;
material->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), texture_file);
if(auto texture = scene->GetEmbeddedTexture(texture_file.C_Str())) {
//returned pointer is not null, read texture from memory
} else {
//regular file, check if it exists and read it
}
In older versions you have to look for a special token:
aiMaterial material = scene->mMaterials[index];
aiString texture_file;
material->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), texture_file);
if('*' == texture_file.data[0]) {
//embedded texture, get index from string and access scene->mTextures
} else {
//regular file, check if it exists and read it
}
Hope that helps to understand the concept.
So I'm using SDL_image to load heightmap and create terrain in my OpenGL app.
That's how I initialize SDL_image:
int flags = IMG_INIT_PNG;
int initted = IMG_Init(flags);
if((initted & flags) != flags) {
printf("IMG_Init: Failed to init required jpg and png support!\n");
printf("IMG_Init: %s\n", IMG_GetError());
return;
}
Load(filename);
...And this is my Load function:
void Load(string filename) {
img = IMG_Load(filename.c_str());
if(!img) {
printf("IMG_Load: %s\n", IMG_GetError());
return;
}
printf("IMG_Load: %s\n", IMG_GetError());
xsize = img->w;
ysize = img->h;
SDL_LockSurface(img);
imgData = (Uint32*)img->pixels;
SDL_UnlockSurface(img);
}
Then, in my Terrain class where I'm preparing my vertex buffer I'm reading pixel values with this method:
Uint32 getPixel(int x, int y) {
SDL_LockSurface(img);
int bpp = img->format->BytesPerPixel;
//cout << "bpp " << bpp << "\n";
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)img->pixels + y * img->pitch + x * bpp;
SDL_UnlockSurface(img);
switch(bpp) {
case 1:
return *p;
break;
case 2:
return *(Uint16 *)p;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;
case 4:
return *(Uint32 *)p;
break;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
...and it turns out that every time I run the program img->format->BytesPerPixel returns a random value... What the heck? Does anyone have any idea? This should only return 1, 2, 3 or 4.
OK, I was just being stupid... But if anyone ever has a problem like me: I was including wrong version of SDL_image... #include <SDL/SDL_image.h> instead of #include <SDL2/SDL_image.h>. Everything now works as expected :)
I got a problem with changing console size. This is my code:
BOOL setConsole(int x, int y)
{
hStdin = GetStdHandle(STD_INPUT_HANDLE);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE ||
hStdout == INVALID_HANDLE_VALUE)
{
MessageBox(NULL, TEXT("GetStdHandle"),
TEXT("Console Error"), MB_OK);
return false;
}
SMALL_RECT windowSize = {0, 0, x-1, y-1};
// Change the console window size:
SetConsoleWindowInfo(hStdout, TRUE, &windowSize);
COORD c = { x, y};
//Change the internal buffer size:
SetConsoleScreenBufferSize(hStdout, c);
SetConsoleDisplayMode(hStdout,CONSOLE_FULLSCREEN_MODE, &c);
return true;
}
It works perfectly fine, when I try to enlarge the console. When one parameter is smaller than previous one nothing happens. What is wrong?
#edit: after some tests I noticed, that resizing(reducing) is possible if I change one parameter at once. Example(assume console is 100x100)
setConsole(90,90); //dosen't work.
setConsole(90,100);
setConsole(90,90); // works perfectly
WHY?!
SetConsoleScreenBufferSize changes the size of the internal buffer of the console.
Changing it has no effect on the console windows extent.
Call SetConsoleWindowInfo if you need an effect on the visible part of the console (buffer).
The window buffer cannot be smaller than the internal buffer , and decreasing it will also decrease the internal buffer,
but not the other way around.
If you call SetConsoleScreenBufferSize with illegal value in COORDS (e.g. too little height/width) then you get an
error, usually 87 'invalid argument'.
Try this code:
#include <iostream>
#include <windows.h>
using namespace std;
void SetWindow(int Width, int Height)
{
_COORD coord;
coord.X = Width;
coord.Y = Height;
_SMALL_RECT Rect;
Rect.Top = 0;
Rect.Left = 0;
Rect.Bottom = Height - 1;
Rect.Right = Width - 1;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); // Get Handle
SetConsoleScreenBufferSize(Handle, coord); // Set Buffer Size
SetConsoleWindowInfo(Handle, TRUE, &Rect); // Set Window Size
}
int main(void)
{
SetWindow(80,40);
int dx=1,i=5,l=0;
while(l<5)
{
i=i+dx;
if( (i<1) || (i>10)){ dx=-dx; l++;}
SetWindow(10*i,5*i);
Sleep(100);
}
cout<<" \nPress any key to continue\n";
cin.ignore();
cin.get();
return 0;
}
Late to the party ...
As far as can be devised from MSDN and a few tests, the screen buffer can't be set smaller than the window's extent or the window's extent made bigger than the screen buffer.
One hack is to shrink the window to a minimal before changing the buffer size :
static void
set_console_size(HANDLE screen_buffer, SHORT width, SHORT height)
{
assert(screen_buffer != NULL);
assert(width > 0);
assert(height > 0);
COORD const size = { width, height };
BOOL success;
SMALL_RECT const minimal_window = { 0, 0, 1, 1 };
success = SetConsoleWindowInfo(screen_buffer, TRUE, &minimal_window);
CHECK(success);
success = SetConsoleScreenBufferSize(screen_buffer, size);
CHECK(success);
SMALL_RECT const window = { 0, 0, size.X - 1, size.Y - 1 };
success = SetConsoleWindowInfo(screen_buffer, TRUE, &window);
CHECK(success);
}
try this code:
system("mode 650");
I modified the code provided by 'Software_Designer' on Oct 15' 12 and created a command line utility to set the console size and scroll buffers.
I compiled it using DEV C++ (http://www.bloodshed.net/devcpp.html).
An executable is included in https://sourceforge.net/projects/wa2l-wintools/. I hope this helps.
/*
* consolesize.cpp - set console size and buffer dimensions
*
* [00] 02.07.2016 CWa Initial Version
*
* inspired by: http://stackoverflow.com/questions/12900713/reducing-console-size
*
*/
#include <iostream>
#include <windows.h>
using namespace std;
// SetWindow(Width,Height,WidthBuffer,HeightBuffer) -- set console size and buffer dimensions
//
void SetWindow(int Width, int Height, int WidthBuffer, int HeightBuffer) {
_COORD coord;
coord.X = WidthBuffer;
coord.Y = HeightBuffer;
_SMALL_RECT Rect;
Rect.Top = 0;
Rect.Left = 0;
Rect.Bottom = Height - 1;
Rect.Right = Width - 1;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); // Get Handle
SetConsoleScreenBufferSize(Handle, coord); // Set Buffer Size
SetConsoleWindowInfo(Handle, TRUE, &Rect); // Set Window Size
} // SetWindow
// main(Width,Height,WidthBuffer,HeightBuffer) -- main
//
int main(int argc, char *argv[]) {
int width = 80;
int height = 25;
int wbuffer = width + 200;
int hbuffer = height + 1000;
if ( argc == 5 ){
width = atoi(argv[1]);
height = atoi(argv[2]);
wbuffer = atoi(argv[3]);
hbuffer = atoi(argv[4]);
} else if ( argc > 1 ) {
cout << "Usage: " << argv[0] << " [ width height bufferwidth bufferheight ]" << endl << endl;
cout << " Where" << endl;
cout << " width console width" << endl;
cout << " height console height" << endl;
cout << " bufferwidth scroll buffer width" << endl;
cout << " bufferheight scroll buffer height" << endl;
return 4;
}
SetWindow(width,height,wbuffer,hbuffer);
return 0;
}
/* So, tiny recap --
SetConsoleScreenBufferSize(): fails if buffer width and height
are less than the width and height of the current screen window
rectangle.
SetConsoleWindowInfo(): fails if the specified window rectangle
is larger than the boundaries of the screen buffer.
Setting the correct one 1st (buffer or window rectangle) would
solve much in a screen resize, but that's hard to know because
calls to GetConsoleScreenBufferInfo() fail easily, and so you cannot
reliably discover the current screen rectangle and/or buffer size,
and hence you cannot know if you'll be setting the screen rectangle
larger or smaller than the current size, and in turn you can't
always know which function to call 1st.
WORKAROUND:
Sloppy solution but super-reliable...
- Set the buffer 1st to something uncommonly large -- like 1000x1000.
- Then set the window rectangle to the actual desired size.
- Finally, set the window buffer to the actual desired size
(matching the screen rectangle) */
int set_screen_size(int requested_wdth, int requested_hgt)
{
SMALL_RECT srWindowRect; /* hold the new console size */
COORD coordBuffer;
BOOL bsuccess = FALSE, wsuccess = FALSE;
srWindowRect.Left = 0;
srWindowRect.Right = requested_wdth-1;
srWindowRect.Top = 0;
srWindowRect.Bottom = requested_hgt-1;
/*set buffer oversize -- like 1000x1000 (500x500 and less
could do too)*/
coordBuffer.X = coordBuffer.Y = 1000;
bsuccess = SetConsoleScreenBufferSize(hConOut, coordBuffer);
wsuccess = SetConsoleWindowInfo(hConOut, TRUE, &srWindowRect);
coordBuffer.X = requested_wdth;
coordBuffer.Y = requested_hgt;
bsuccess = SetConsoleScreenBufferSize(hConOut, coordBuffer);
/* ... */
}
I am working on USB WebCamera using OpenCv in Qt.The code works fine for taking images, saving images etc. But randomly it generates error "VIDIOC_QUERYCTRL: Input/output error" causing my whole qt application to shutdown.
Actually The Scenario of my application is as follow:
In MainWindow.c, I have a pushbutton, which is when pressed starts the camera:
void MainWindow::on_pushButton_continue_pressed()
{
camcapture = new CamCapture( imgResolution, defaultPath, this);
connect(camcapture, SIGNAL(imgChange(QString)), this, SLOT(changeImg(QString)));
camcapture->show();
}
and Here is piece of my CamCapture Class:
CamCapture::CamCapture( int Resolution, QString path, QWidget *parent) :
QFrame(parent),
ui(new Ui::CamCapture), timer_(this), counter_(0)
{
ui->setupUi(this);
/*----some variable initialization---*/
camInit();
timer_.start(100);
connect(&timer_,SIGNAL(timeout()), this,SLOT(captureLoop()));
}
void CamCapture::camInit()
{
capture_ = cvCaptureFromCAM(0);
if (!capture_)
{
qDebug()<<"cannot get webcam...";
ui->label_image->setText("No webcam!");
ui->label_image->setAlignment(Qt::AlignCenter);
buttonActiveStatus( false, false, false );
return;
}
cvGrabFrame(capture_); // Grabs frame from camera or file
image_ = cvRetrieveFrame(capture_); // Gets the image grabbed with cvGrabFrame
qDebug() << "image size : " << image_->width << "x" << image_->height;
qDebug() << "\n" << ui->label_image->x();
qDebug() << "\n" << ui->label_image->y();
}
QImage CamCapture::Ipl2QImage(const IplImage *newImage)
{
QImage qtemp;
if (newImage && cvGetSize(newImage).width > 0)
{
int x;
int y;
char* data = newImage->imageData;
qtemp= QImage(newImage->width, newImage->height,QImage::Format_RGB32 );
for( y = 0; y < newImage->height; y++, data +=newImage->widthStep )
for( x = 0; x < newImage->width; x++)
{
uint *p = (uint*)qtemp.scanLine (y) + x;
*p = qRgb(data[x * newImage->nChannels+2],
data[x * newImage->nChannels+1],data[x * newImage- >nChannels]);
}
}
return qtemp;
}
void CamCapture::captureLoop()
{
if ( !capture_ )
{
return;
}
cvGrabFrame(capture_);
image_ = cvRetrieveFrame(capture_);
if (image_)
{
counter_ ++;
qImage_ = Ipl2QImage(image_);
ui->label_image- >setPixmap(QPixmap::fromImage(qImage_.scaled(width(),height()),Qt::AutoColor));
}
}
void CamCapture::on_pushButton_cancel_pressed()
{
cvReleaseCapture( &capture_ );
cvDestroyAllWindows();
delay(100);
qDebug() << "nb frames :" << counter_;
CamCapture::close();
}
void CamCapture::on_pushButton_capture_pressed()
{
savePath = _imgPath;
timer_.stop();
frame = cvQueryFrame(capture_); // Gets the image grabbed with cvGrabFrame
}
void CamCapture::on_pushButton_retake_pressed()
{
timer_.start(100);
captureLoop();
}
void CamCapture::on_pushButton_save_pressed()
{
int iwidth = _imgWidth * _imgResolution * scaledFactor;
int iheight = _imgHeight * _imgResolution * scaledFactor;
QString str = savePath;
IplImage *small;
small = cvCreateImage(cvSize(iwidth,iheight), 8, 3);
cvResize(frame, small);
cvSaveImage(savePath.toUtf8().constData(),small);
delay(100);
_imgNum++;
emit imgChange(savePath);
on_pushButton_cancel_pressed();
}
The above code randomly generates error ( causing my application shutdowm ) as follow:
Debugging starts
&"warning: GDB: Failed to set controlling terminal: Invalid argument\n"
Corrupt JPEG data: bad Huffman code
image size : 640 x 480
5
10
nb frames : 11
VIDIOC_QUERYCTRL: Input/output error
Debugging has finished
Commonly, the Error is generated Either while pressing pushButton_continue from MainWindow.c or While pressing pushButton_Save from CamCapture.c
Unable to find any solution on google.
Need some suggestions/help/link to solve this issue.
Thanks in advance.