hi

hello
i need some help in my uni project in opengl!
i need a code to keep the rendering after each drawing in the appliction screen ,and after the drawing save the whole image as an image file…help me please

glReadPixels just before swap, then write the raw data using any image library you like (or do it by hand if you prefer).

i am writing a code to handle the hand written text or image,in my code there is a menu on the page and we have options in the menu to enable writing and eraser and anther options,when i write using the mouse then use the eraser ,just when i select erase the whole window is cleared and starting new page!
i need to keep it on the screen and erase what ever i want,and then save the whole image as in image file! :slight_smile:

what do you mean by this “then write the raw data using any image library you like (or do it by hand if you prefer).”???

If you want to save it as a image file, then you need to use some library such as DevIL
http://openil.sourceforge.net

it supports many formats : bmp, jpeg, gif, png, tiff, tga, dds, etc

thax for the replay every body :slight_smile:

i found a written code using GDI+ library,but i don’t know how to install it and correctly include t in my code any help??

GDI is seperate from OpenGL, and as far as I know, you dont have to install it as it comes with windows.

Basically, GDI is the method windows uses to do some basic drawing on the screen. OpenGL is a more advanced library that uses the Graphics Card to do it. OpenGL has many more ‘features’, and deals with 3D graphics primarily while GDI only handles 2D.

If you can, get something like C++ Builder, which is a drag-and-drop visual IDE that makes GDI programming very easy. It provides a ‘PaintBox’ component that you can draw on using just a few lines of code using what it calls a ‘canvas’ class.

Something like this:
PaintBox1->Canvas->MoveTo(20, 15);
PaintBox1->Canvas->LineTo(255, 82);

In addition, it also has another object called the Bitmap object, which also has a canvas that you can draw do, but more importantly, it can allow you to save and load from files, like so:

Graphics::TBitmap*
bitmap = new Graphics::TBitmap;
bitmap->Canvas->CopyRect(dest, PaintBox1->Canvas, src);
bitmap->SaveToFile(“form.bmp”);

Here are some documents to help make it clearer:
http://www.yevol.com/en/bcb/Lesson12.htm
http://bcbjournal.org/articles/vol2/9805/Capturing_a_form_to_disk.htm

I hope that helps

Kind regards,
Fugi

thax alot that will help :slight_smile:

i have some written code to capture an opengl svreen shoot but it have some errors i dont know where is the proplem would you help me please!!! i real need to save the rendering images as a image file!
// gdi test.cpp : Defines the entry point for the console application.
//

#include “stdafx.h”
#include <windows.h>
#include <stdio.h>
#include <glut.h>
#include “C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\gdiplus.h”
using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes

ImageCodecInfo* pImageCodecInfo = NULL;

GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure

pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure

GetImageEncoders(num, size, pImageCodecInfo);

for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}

free(pImageCodecInfo);
return -1; // Failure
}

bool CaptureScreenShot(int nWidth, int nHeight, const std::wstring& szDestFile,const std::wstring& szEncoderString)
{
UINT *pixels=new UINT[nWidth * nHeight];
memset(pixels, 0, sizeof(UINT)nWidthnHeight);

glFlush(); glFinish();

glReadPixels(0,0,nWidth,nHeight,GL_BGRA_EXT,GL_UNSIGNED_BYTE,pixels);

if(NULL==pixels)
	return false;

// Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

{
// Create the dest image
Bitmap DestBmp(nWidth,nHeight,PixelFormat32bppARGB);

Rect rect1(0, 0, nWidth, nHeight);

BitmapData bitmapData;
memset( &bitmapData, 0, sizeof(bitmapData));
DestBmp.LockBits( 
	&rect1, 
	ImageLockModeRead,
	PixelFormat32bppARGB,
	&bitmapData );

int nStride1 = bitmapData.Stride;
if( nStride1 &lt; 0 )
	nStride1 = -nStride1;

UINT* DestPixels = (UINT*)bitmapData.Scan0;

if( !DestPixels )
{
	delete [] pixels;
	return false;
}

for(UINT row = 0; row &lt; bitmapData.Height; ++row)
{
	for(UINT col = 0; col &lt; bitmapData.Width; ++col)
	{
		 DestPixels[row * nStride1 / 4 + col] = pixels[row * nWidth + col];
	}
}

DestBmp.UnlockBits( 
	&bitmapData );

delete [] pixels;
pixels = NULL;

DestBmp.RotateFlip( RotateNoneFlipY );

CLSID Clsid;
int result = GetEncoderClsid(szEncoderString.c_str(), &Clsid);

if( result &lt; 0 )
	return false;

Status status = DestBmp.Save( szDestFile.c_str(), &Clsid );
}
// Shutdown GDI+
GdiplusShutdown(gdiplusToken);

return true;

}

void main (){

	wchar_t FullPath[MAX_PATH];
		memset( FullPath, 0, sizeof(FullPath) );
		std::wstring szExePath;
		if (::GetModuleFileNameW( NULL, FullPath, sizeof(wchar_t)*MAX_PATH))
		{
			szExePath = FullPath;
			
			int pos = szExePath.rfind( L'\\' );
			
			if( -1 != pos )
			{
				szExePath = szExePath.substr(0,pos+1);
			}
		}

		std::wstring szDestFile = szExePath;
		szDestFile += L"somepic.png";

		RECT rect;
		memset(&rect,0,sizeof(rect));
		GetClientRect(g_hWnd,&rect);
		
		CaptureScreenShot(
			rect.right, 
			rect.bottom, 
			szDestFile,
			L"image/png");}

it have some errors

Which ones exactly ? more details please, use a debugger, etc

hi every body
i need a code to get/read data from a serial port(comport)
and a code to save my image rendering as an image file
help me plz plz plz

simple way .if you are using the windowv7 .you can try “printscreen” of the keyboard.
read it .and save it

no i need it in my code as a save button programmed when i press it will save the image as a file,i dont understand how to use “glreadpixels”

readpixels is quite simple, anyway here a tutorial that details how to do a GL screen capture to a TGA file :
http://www.lighthouse3d.com/opengl/terrain/index.php?tgalib

thank you,i hope that it will work :slight_smile:

the ‘tga.h’ file where can i find it to include it?

You know, there is a nice link on the left conveniently named “source code” which points to this :
http://www.lighthouse3d.com/opengl/terrain/terrain1.zip

thank you :smiley:
what would i do with out ur help? this project is driven me crazy

hi agian
i have tested the code in the link,bt i don’t how can i sepcify in which file it will be saved!!!what should i invoke in the main just

tgaSave(“test”, 200, 200,-9,0 );!!!
PLEASE HELP ME
HERE IS THE CODE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include “tga.h”

// this variable is used for image series
static int savedImages=0;

// load the image header fields. We only keep those that matter!
void tgaLoadHeader(FILE *file, tgaInfo *info) {

unsigned char cGarbage;
short int iGarbage;

fread(&cGarbage, sizeof(unsigned char), 1, file);
fread(&cGarbage, sizeof(unsigned char), 1, file);

// type must be 2 or 3
fread(&info->type, sizeof(unsigned char), 1, file);

fread(&iGarbage, sizeof(short int), 1, file);
fread(&iGarbage, sizeof(short int), 1, file);
fread(&cGarbage, sizeof(unsigned char), 1, file);
fread(&iGarbage, sizeof(short int), 1, file);
fread(&iGarbage, sizeof(short int), 1, file);

fread(&info-&gt;width, sizeof(short int), 1, file);
fread(&info-&gt;height, sizeof(short int), 1, file);
fread(&info-&gt;pixelDepth, sizeof(unsigned char), 1, file);

fread(&cGarbage, sizeof(unsigned char), 1, file);

}

// loads the image pixels. You shouldn’t call this function
// directly
void tgaLoadImageData(FILE *file, tgaInfo *info) {

int mode,total,i;
unsigned char aux;

// mode equal the number of components for each pixel
mode = info->pixelDepth / 8;
// total is the number of bytes we’ll have to read
total = info->height * info->width * mode;

fread(info-&gt;imageData,sizeof(unsigned char),total,file);

// mode=3 or 4 implies that the image is RGB(A). However TGA
// stores it as BGR(A) so we’ll have to swap R and B.
if (mode >= 3)
for (i=0; i < total; i+= mode) {
aux = info->imageData[i];
info->imageData[i] = info->imageData[i+2];
info->imageData[i+2] = aux;
}
}

// this is the function to call when we want to load
// an image
tgaInfo * tgaLoad(char *filename) {

FILE *file;
tgaInfo *info;
int mode,total;

// allocate memory for the info struct and check!
info = (tgaInfo *)malloc(sizeof(tgaInfo));
if (info == NULL)
return(NULL);

// open the file for reading (binary mode)
file = fopen(filename, “rb”);
if (file == NULL) {
info->status = TGA_ERROR_FILE_OPEN;
return(info);
}

// load the header
tgaLoadHeader(file,info);

// check for errors when loading the header
if (ferror(file)) {
info->status = TGA_ERROR_READING_FILE;
fclose(file);
return(info);
}

// check if the image is color indexed
if (info->type == 1) {
info->status = TGA_ERROR_INDEXED_COLOR;
fclose(file);
return(info);
}
// check for other types (compressed images)
if ((info->type != 2) && (info->type !=3)) {
info->status = TGA_ERROR_COMPRESSED_FILE;
fclose(file);
return(info);
}

// mode equals the number of image components
mode = info->pixelDepth / 8;
// total is the number of bytes to read
total = info->height * info->width * mode;
// allocate memory for image pixels
info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
total);

// check to make sure we have the memory required
if (info->imageData == NULL) {
info->status = TGA_ERROR_MEMORY;
fclose(file);
return(info);
}
// finally load the image pixels
tgaLoadImageData(file,info);

// check for errors when reading the pixels
if (ferror(file)) {
info->status = TGA_ERROR_READING_FILE;
fclose(file);
return(info);
}
fclose(file);
info->status = TGA_OK;
return(info);
}

// converts RGB to greyscale
void tgaRGBtogreyscale(tgaInfo *info) {

int mode,i,j;

unsigned char *newImageData;

// if the image is already greyscale do nothing
if (info->pixelDepth == 8)
return;

// compute the number of actual components
mode = info->pixelDepth / 8;

// allocate an array for the new image data
newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
info->height * info->width);
if (newImageData == NULL) {
return;
}

// convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
newImageData[j] =
(unsigned char)(0.30 * info->imageData[i] +
0.59 * info->imageData[i+1] +
0.11 * info->imageData[i+2]);

//free old image data
free(info->imageData);

// reassign pixelDepth and type according to the new image type
info->pixelDepth = 8;
info->type = 3;
// reassing imageData to the new array.
info->imageData = newImageData;
}

// takes a screen shot and saves it to a TGA image
int tgaGrabScreenSeries(char *filename, int xmin,int ymin, int xmax, int ymax) {

int w, h;
unsigned char *imageData;

// compute width and heidth of the image
w = xmax - xmin;
h = ymax - ymin;

// allocate memory for the pixels
imageData = (unsigned char *)malloc(sizeof(unsigned char) * w * h * 4);

// read the pixels from the frame buffer
glReadPixels(xmin,ymin,xmax,ymax,GL_RGBA,GL_UNSIGNED_BYTE, (GLvoid *)imageData);

// save the image
return(tgaSaveSeries(filename,w,h,32,imageData));
}

// saves an array of pixels as a TGA image
int tgaSave( char *filename,
short int width,
short int height,
unsigned char pixelDepth,
unsigned char *imageData) {

unsigned char cGarbage = 0, type,mode,aux;
short int iGarbage = 0;
int i;
FILE *file;

// open file and check for errors
file = fopen(filename, “wb”);
if (file == NULL) {
return(TGA_ERROR_FILE_OPEN);
}

// compute image type: 2 for RGB(A), 3 for greyscale
mode = pixelDepth / 8;
if ((pixelDepth == 24) || (pixelDepth == 32))
type = 2;
else
type = 3;

// write the header
fwrite(&cGarbage, sizeof(unsigned char), 1, file);
fwrite(&cGarbage, sizeof(unsigned char), 1, file);

fwrite(&type, sizeof(unsigned char), 1, file);

fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&cGarbage, sizeof(unsigned char), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);
fwrite(&iGarbage, sizeof(short int), 1, file);

fwrite(&width, sizeof(short int), 1, file);
fwrite(&height, sizeof(short int), 1, file);
fwrite(&pixelDepth, sizeof(unsigned char), 1, file);

fwrite(&cGarbage, sizeof(unsigned char), 1, file);

// convert the image data from RGB(a) to BGR(A)
if (mode >= 3)
for (i=0; i < width * height * mode ; i+= mode) {
aux = imageData[i];
imageData[i] = imageData[i+2];
imageData[i+2] = aux;
}

// save the image data
fwrite(imageData, sizeof(unsigned char),
width * height * mode, file);
fclose(file);
// release the memory
free(imageData);

return(TGA_OK);

}

// saves a series of files with names “filenameX.tga”
int tgaSaveSeries(char *filename,
short int width,
short int height,
unsigned char pixelDepth,
unsigned char *imageData) {

char *newFilename;
int status;

// compute the new filename by adding the
// series number and the extension
newFilename = (char *)malloc(sizeof(char) * strlen(filename)+8);

sprintf(newFilename,"%s%d.tga",filename,savedImages);

// save the image
status = tgaSave(newFilename,width,height,pixelDepth,imageData);

//increase the counter
if (status == TGA_OK)
savedImages++;
free(newFilename);
return(status);
}

// releases the memory used for the image
void tgaDestroy(tgaInfo *info) {

if (info != NULL) {
	if (info-&gt;imageData != NULL)
		free(info-&gt;imageData);
	free(info);
}

}