Enlarging bitmap in c - c

The following code takes in a bmp and enlarges it, rotates it or flips it. Everything is working properly except when i call the enlarge command line. the pictures comes up but it does not look any bigger.
This is the enlarge funtions:
int enlarge(PIXEL* original, int rows, int cols, int scale,
PIXEL** new, int* newrows, int* newcols)
{
int row, col, i, j;
if((rows<=0)|| (cols<=0))
{
return -1;
}
*newrows=rows * scale;
*newcols=cols * scale;
*new=(PIXEL*)malloc((scale*rows)*(scale*cols)*sizeof(PIXEL));
for(row=0;row<rows;row++)
{
for(col=0;col<cols;col++)
{
PIXEL *o=original + row*cols +col;
for(j=0; j<scale;j++)
{
for(i=0; i<scale;i++)
{
PIXEL *n=(*new)+(row*scale+i)*(*newcols)+(col*scale+j);
*n=*o;
}
}
}
}
/* THIS IS THE METHOD THAT YOU SHOULD WRITE */
return 0;
}
and this is the main function:
int degree, scale;
int is_rotate=0, is_scale=0, is_flip=0;
char *inputFile=NULL, *outputFile=NULL;
int r, c, check;
PIXEL *b, *nb;
int nr,nc;
int error;
//readFile("example.bmp",&r,&c,&b);
while((check=getopt(argc,argv,"s:r:o:f")) != -1)
{
switch (check)
{
case 's':
is_scale=is_scale+1;
//enlarge(nb,nr,nc,optarg,&nb,&nr,&nc);
scale=atoi(optarg);
if(is_scale==2)
{
printf("bmptool: -s: scale can only be called once in commmand line");
error=1;
}
if(scale<0)
{
printf("bmptool: -s : the scale must be a positive integer");
error=1;
}
//printf("This is working s");
break;
case 'r':
is_rotate= is_rotate+1;
//rotate(b,r,c,optarg,&b,&r,&c);
degree=atoi(optarg);
if(is_rotate==2)
{
printf("bmptool: -r: rotation can only be called once in commmand line");
error=1;
}
if(degree%90 != 0)
{
printf("bmptool: -r: the degree of rotation must be a multiple of 90");
error=1;
}
//printf("this is working r");
break;
case 'f':
is_flip=is_flip+1;
if(is_flip==2)
{
printf("bmptool: -f: flip can only be called once in command line");
}
break;
case 'o':
outputFile=(optarg);
//printf(outputFile);
//readFile(outputFile,&r,&c,&b);
break;
}
}
if(error==1)
{
return 0;
}
if(is_rotate==0 && is_scale==1 && is_flip==0)
{
enlarge(nb,nr,nc,scale,&nb,&nr,&nc);
writeFile(inputFile,r,c,b);
}
I only added the if statement that contains the enlarge. Thanks in advance for the help.

Try this:
int enlarge(PIXEL* original, int rows, int cols, float scale,
PIXEL** enlarged, int* newrows, int* newcols)
{
int row, col;
if((rows<=0)|| (cols<=0))
{
return -1;
}
(*newrows)=(int)((float)rows * scale);
(*newcols)=(int)((float)cols * scale);
*enlarged=(PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
for(row=0;row<(*newrows);row++)
{
for(col=0;col<(*newcols);col++)
{
(*enlarged)[row * (*newcols) + col] = original[(row * rows / (*newrows)) * cols + col * cols / (*newcols)];
}
}
/* THIS IS THE METHOD THAT YOU SHOULD WRITE */
return 0;
}
NOTE: i change scale type to float in order to you could scale in any factor, but you could change to int with any problem
You must pass newrows and newcols by ref (not pointer)
EDIT: function usage
scale = 2.0f;
readFile("example.bmp",&r,&c,&b);
enlarge(b,r,c,scale,&nb,&nr,&nc);
writeFile("enlarge.bmp",nr,nc,nb);
free(nb);

If this is a standard Windows bitmap, then newrows must be of a scanline size. A bitmap image consists of scanlines. A scanline consists of pixels. A pixel consists of one or more components (colors).
A scanline must be a multiple of 4 bytes. So after the last component of the last pixel of a scanline, there may follow some unused bytes.
So your scaled bitmap must have scanlines of the appropriate size. See also
Dealing with padding in a BMP file in C of how to calculate scanline sizes and iterate over an image.
Note also that if you just "scale" with an integer, you can scale 1, 2, 3... integer times (100%, 200%,...). Scaling with non-integers requires smearing the pixels out over the new width and hight. Numerous algorithms and ready-to-use code are available on the internet.

Related

How to check the conditions for neighbours?

I am stubborn about trying to solve as much as I can myself. However I think that I've reached an impasse.
I have to write code for a simple version for game of life on a 20x20 grid. The conditions are:
A cell which has 0 or 1 living neighbours dies next generation.
A cell which has 2 or 3 living neighbours lives next generation.
A cell which has 4 or more living neighbours dies next generation.
A empty cell which has exactly 3 living neighbours becomes a live
cell next generation.
My particular problem is how to write the algoritm that performs the above said operations.
I have not tried much since I'm out of ideas. I did hope to get some ideas which might give me a extra push into finishing my function that updates the world/field.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Constants, representation of states */
#define ALIVE 'X'
#define DEAD '.'
/* Declaration of data structure */
typedef struct{
char current;
char next;
} cell;
/* Declaration of functions */
void initField(const int rows, const int cols, cell field[rows][cols]);
void loadGlider(const int rows, const int cols, cell field[rows][cols]);
void loadSemaphore(const int rows, const int cols, cell field[rows][cols]);
void loadRandom(const int rows, const int cols, cell field[rows][cols]);
void loadCustom(const int rows, const int cols, cell field[rows][cols]);
void printWorld(const int rows, const int cols, cell field[rows][cols]);
void evolve(const int rows,const int cols,cell field[rows][cols]);
/* Function: main
* Description: Start and run games, interact with the user.
* Input: About what initial structure and whether to step or exit.
* Output: Information to the user, and the game field in each step.
*/
int main(void) {
const int rows = 20;
const int cols = 20;
cell field[rows][cols];
initField(rows,cols, field);
printWorld(rows,cols,field);
return 0;
}
/* Function: initField
* Description: Initialize all the cells to dead, then asks the user about
* which structure to load, and finally load the structure.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void initField(const int rows, const int cols, cell field[rows][cols]) {
for (int r = 0 ; r < rows ; r++) {
for (int c = 0 ; c < cols ; c++) {
field[r][c].current = DEAD;
}
}
printf("Select field spec to load ([G]lider, [S]emaphore, [R]andom ");
printf("or [C]ustom): ");
int ch = getchar();
/* Ignore following newline */
if (ch != '\n') {
getchar();
}
switch (ch) {
case 'g':
case 'G':
loadGlider(rows, cols, field);
break;
case 's':
case 'S':
loadSemaphore(rows, cols, field);
break;
case 'r':
case 'R':
loadRandom(rows, cols, field);
break;
case 'c':
case 'C':
default:
loadCustom(rows, cols, field);
break;
}
}
/* Function: loadGlider
* Description: Inserts a glider into the field.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void loadGlider(const int rows, const int cols, cell field[rows][cols]) {
field[0][1].current = ALIVE;
field[1][2].current = ALIVE;
field[2][0].current = ALIVE;
field[2][1].current = ALIVE;
field[2][2].current = ALIVE;
}
/* Function: loadSemaphore
* Description: Inserts a semaphore into the field.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void loadSemaphore(const int rows, const int cols, cell field[rows][cols]) {
field[8][1].current = ALIVE;
field[8][2].current = ALIVE;
field[8][3].current = ALIVE;
}
/* Function: loadRandom
* Description: Inserts a random structure into the field.
* Input: The field array and its size.
* Output: The field array is updated. There is a 50 % chance that a cell
* is alive.
*/
void loadRandom(const int rows, const int cols, cell field[rows][cols]) {
}
/* Function: loadCustom
* Description: Lets the user specify a structure that then is inserted into
* the field.
* Input: The field array and its size.
* Output: The field array is updated.
*/
void loadCustom(const int rows, const int cols, cell field[rows][cols]) {
printf("Give custom format string: ");
do {
int r, c;
scanf("%d,%d", &r, &c);
field[r][c].current = ALIVE;
} while (getchar() != '\n');
}
/* Function: printWorld
* Description: Prints the current field
* Input: The field array and its size.
* Output: The field array is updated.
*/
void printWorld(const int rows, const int cols, cell field[rows][cols]){
char c = '\n';
while(c == '\n'){
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%c ", field[i][j].current);
}
printf("\n");
}
c = getchar();
if(c != '\n'){
break;
}
}
void evolve(const int rows,const int cols,cell field[rows][cols]){
for(int i = 0;i<rows;i++){
for(int j =0;j<cols;j++){
if()
}
}
}
You can see above all current progress. All the functions except for
printWorld() and evolve() are pre-made and should remain as they are.
This is my current progress for evolve, it is not much.
void evolve(const int rows,const int cols,cell field[rows][cols]){
for(int i = 0;i<rows;i++){
for(int j =0;j<cols;j++){
if()
}
}
}
All I have done is to write two nested for-loops which makes sure to check every cell.
But I am not sure however how to proceed and implement the conditions above. Any ideas on how to check neighbours for each cell?
English is not my first language. So I apologise in advance for any grammatical error. And if you have trouble understanding what I want, ask, and I'll clarify.
I would also add a disclaimer that the function: printWorld is not finished since it still requires the function evolve.
All I have done is to write two nested for-loops which makes sure to check every cell.
Well that's a start.
But I am not sure however how to proceed and implement the conditions above. Any ideas on how to check neighbours for each cell?
The evolve() function receives the field, apparently describinbg the current state of the board and the next state. It would appear that the data for a cell with indices i, j would be in field[i][j]. So the main question is: which cells are the neighbors of that one? But that shouldn't be hard. They are the eight cells other than (i, j) each of whose indices differs by at most 1 from i or j, respectively. That is, (i - 1, j - 1), (i - 1, j), (i - 1, j + 1), (i, j - 1), etc.. Work out an example if you need to do, with actual cell indices, for one cell.
So it seems you would count the live population of all the neighbor cells, and use that in combination with whether the current cell is alive, to determine and record how that cell will evolve.
Do note that the edges and corners are special cases: they do not have neighbors on at least one side, and you must not try to examine the neighbors that do not exist. You should be able to accomplish that by checking whether the neighbor cell indices are in bounds before trying to access them.

Unable to read a maze of chars and put it into a bidimensional array

I am making a maze solving game. There is a function in the middle of the game that saves the progress and prints everything into the file. But now i want to read the maze, the character, etc from the file and put it into a bidimensional array but i am not being able to do so.
The array is declared globally (because of its use in several functions) and it is maze[30][30]. N is also declared globally as a variable size but at this point it should be 10. filePath too and it gives the name of the file.
This is how they are declared globally.
int N = 10;
char* filePath = "./save.txt";
char maze[30][30];
This is the read function:
void ler()
{
int i, j;
ex=1; ey=0;
sx=N-2; sy=N-1;
int aux;
FILE *fp = fopen(filePath, "r");
if (fp == NULL)
{
printf("Unable to perform.");
return;
}
system("cls");
for(i=0 ; i<N ; i++)
{
for(j=0 ; j<N ; j++)
{
fscanf(fp, "%c", maze[j][i]);
}
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf("%c", maze[j][i]); //Double print just for visuals
printf("%c", maze[j][i]);
}
printf("\n");
}
fclose(fp);
}
This is the save function:
void save(char maze[30][30]){
int i,j;
FILE *fp = fopen(filePath, "w");
if(fp==NULL){
printf("Unable to perform.");
return;
}
for(i=0 ; i<N ; i++){
for(j=0 ; j<N ; j++){
fprintf(fp, "%c", maze[j][i]);
fprintf(fp, "%c", maze[j][i]);
}
fprintf(fp, "\n", maze[j][i]);
}
fclose(fp);}
At this point it should only be possible to print the maze but it is not doing even that.
What save.txt file looks like after saving
The weird II is the caharcter and the other is like a highscore thing.
Using multidimensional arrays in C is actually more pain than they're worth. A much better option is to use a structure with a dynamically allocated array describing the maze, and accessor functions to examine and change the maze cells. Instead of putting markers in the maze data, you can put start/end/current location coordinates in the structure.
(I do realize that this does not answer the OP's stated question, but this is an answer to the underlying problem OP is trying to solve.)
Consider the following example. It limits the maze size to 255×255, but because each coordinate and maze cell is always just one byte, the save files are portable between architectures, as there is no byte order (endianness) to worry about. (You, as the programmer, do need to choose to use only codes 0..255 in the maze, though, to keep the data portable; the functions below won't enforce that.)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
unsigned char row;
unsigned char col;
} mazepoint;
typedef struct {
unsigned char rows;
unsigned char cols;
unsigned char *cell;
mazepoint player;
} maze;
#define OUTSIDE 0
static inline unsigned char maze_get(maze *const m,
const int row,
const int col)
{
if (m &&
row >= 0 && row < (int)(m->rows) &&
col >= 0 && col < (int)(m->cols))
return m->cell[ (size_t)col + (size_t)(m->cols) * (size_t)row ];
else
return OUTSIDE;
}
static inline unsigned char maze_set(maze *const m,
const int row,
const int col,
const unsigned char val)
{
if (m &&
row >= 0 && row < (int)(m->rows) &&
col >= 0 && col < (int)(m->cols))
return m->cell[ (size_t)col + (size_t)(m->cols) * (size_t)row ] = val;
else
return OUTSIDE;
}
static inline void maze_free(maze *const m)
{
if (m) {
free(m->cell);
m->rows = 0;
m->cols = 0;
m->cell = NULL;
}
}
int maze_create(maze *const m,
const int rows,
const int cols)
{
size_t cells = (size_t)rows * (size_t)cols;
unsigned char *cell;
if (!m)
return -1; /* NULL reference to a maze variable! */
if (rows < 1 || rows > 255 ||
cols < 1 || cols > 255)
return -1; /* Invalid number of rows or columns! */
cell = malloc(cells); /* sizeof (unsigned char) == 1. */
if (!cell)
return -1;
/* Initialize all maze cells to OUTSIDE. */
memset(cell, OUTSIDE, cells);
m->rows = rows;
m->cols = cols;
m->cell = cell;
/* Let's initialize player location to upper left corner. */
m->player.row = 0;
m->player.col = 0;
return 0; /* Success. */
}
int maze_save(maze *const m, const char *filename)
{
size_t cells;
FILE *out;
if (!m || m->rows < 1 || m->cols < 1)
return -1; /* No maze to save! */
if (!filename || !filename[0])
return -1; /* NULL or empty filename! */
cells = (size_t)(m->rows) * (size_t)(m->cols);
out = fopen(filename, "wb");
if (!out)
return -1; /* Cannot open file for writing! */
do {
/* First byte is the number of rows. */
if (fputc(m->rows, out) == EOF)
break;
/* Second byte is the number of columns. */
if (fputc(m->cols, out) == EOF)
break;
/* rows*cols bytes of maze data follows. */
if (fwrite(m->cell, 1, cells, out) != cells)
break;
/* Player location follows. */
if (fputc(m->player.row, out) == EOF)
break;
if (fputc(m->player.col, out) == EOF)
break;
/* You can save additional data at this point. */
/* That completes the save file. Ensure it is correctly saved. */
if (fflush(out))
break;
if (fclose(out))
break;
/* Maze successfully saved. */
return 0;
} while (0);
/* Save failed. */
fclose(out);
remove(filename);
return -1;
}
int maze_load(maze *const m, const char *filename)
{
size_t cells;
unsigned char *cell;
int rows, cols, r, c;
FILE *in;
if (!m)
return -1; /* No reference to a maze variable to load into! */
/* Just in case, we clear the maze first. Might help finding bugs! */
m->rows = 0;
m->cols = 0;
m->cell = NULL;
if (!filename || !filename[0])
return -1; /* NULL or empty filename! */
in = fopen(filename, "rb");
if (!in)
return -1; /* Cannot open file for reading. */
rows = fgetc(in);
cols = fgetc(in);
if (rows == EOF || rows < 1 || rows > 255 ||
cols == EOF || cols < 1 || cols > 255) {
fclose(in);
return -1; /* Not a saved maze! */
}
cells = (size_t)(rows) * (size_t)(cols);
cell = malloc(cells);
if (!cell) {
fclose(in);
return -1; /* Not enough memory available! */
}
do {
/* Read maze cell data. */
if (fread(cell, 1, cells, in) != cells)
break;
/* Player location. */
r = fgetc(in);
c = fgetc(in);
if (r == EOF || r < 0 || r > 255 ||
c == EOF || c < 0 || c > 255)
break;
m->player.row = r;
m->player.col = c;
/* Load other saved data here. */
/* All data read successfully. */
fclose(in);
m->rows = rows;
m->cols = cols;
m->cell = cell;
return 0;
} while (0);
/* Read error. */
fclose(in);
free(cell);
return -1;
}
In your own program, you'd create a maze thus:
maze m;
/* Create a 20-row, 30-column maze. */
if (maze_create(&m, 20, 30)) {
/* Failed to create maze! Show an error message. */
exit(EXIT_FAILURE);
}
To save the maze to say maze.dat, you use
m.player.row = /* row where the player is */
m.player.col = /* column where the player is */
if (maze_save(&m, "maze.dat")) {
/* Failed! Show an error message. */
exit(EXIT_FAILURE);
}
If you look at the example code, you can add additional data, especially points like the player place, to be saved and loaded along with the maze cells themselves.
To destroy a maze when it is no longer needed, use
maze_free(&m);
To load a saved maze, say from maze.dat, use
if (maze_load(&m, "maze.dat")) {
/* Failed! Show an error message. */
exit(EXIT_FAILURE);
}
/* Restore player place from m.player.row and m.player.col */
The accessor function maze_get() is not limited to the valid coordinates (0 through rows-1 or cols-1, inclusive). If you examine outside the maze itself, it will just return the value of the OUTSIDE macro. For example,
if (maze_get(&m, row, col) == 5) {
/* That cell has value 5 */
} else {
/* Either the cell has a different value,
or row,col is outside the maze. */
}
Similarly, you can try to set any cell value safely. It will only "stick" if it is within the valid maze coordinate range, however; elsewhere it will return OUTSIDE:
if (maze_set(&m, row, col, 5) == 5) {
/* Changed cell value to 5 */
} else {
/* row,col is outside the maze. */
}
The reason I wrote the accessor macros that way, is that it makes rendering only a part of the maze very simple. If the view is viewrows by viewcols in size, centered at row and col, then you can render the view using a simple loop:
const int top = row - viewrows / 2;
const int left = col - viewcols / 2;
int vr, vc;
for (vr = 0; vr < viewrows; vr++) {
for (vc = 0; vc < viewcols; vc++) {
const unsigned char v = maze_get(&m, top+vr, left+vc);
/* Draw v at row vr, col vc */
}
}
and the cells are even drawn in the same order as you read this text; from top to bottom, left to right.
Note that instead of using the maze cell values for character codes, you should use a lookup table instead. For example,
int cell_char[256];
Instead of printing cell values directly, you'd print the corresponding cell_char, for example
fputc(cell_char[maze_get(&m, row, col)], stdout);
That way you can group e.g. different wall characters into a consecutive range, or even use the individual bits in the 8-bit cell value as identifiers. The maze cells then describe the logical contents in that maze cell, rather than its visual representation, with the logical-to-visual mapping in a separate array.
If you used Gtk+, you could have an array of GtkImage pointers,
GtkImage *cell_image[256] = {0}; /* All NULL by default */
or using SDL, you could have the maze cells as textures you can render,
SDL_Texture *cell_texture[256] = {0}; /* All NULL by default */
and in both cases, read them from either one large image (say, divided into 16×16 exact same size rectangles), or from individual image files.
For example, you could decide that the four least significant bits in the cell value specify whether movement from that cell up (previous row), down (next row), left (previous column), or right (next column) is possible:
#define CAN_GO_UP(value) ((value) & (1 << 0)) /* == 1 */
#define CAN_GO_DOWN(value) ((value) & (1 << 1)) /* == 2 */
#define CAN_GO_LEFT(value) ((value) & (1 << 2)) /* == 4 */
#define CAN_GO_RIGHT(value) ((value) & (1 << 3)) /* == 8 */
Note that this allows you to do "trap walls": passages that only work one way. Maze cell values that are multiples of 16 (0, 16, 32, 48, 64, 80, 96, ..., 208, 224, and 240) represent completely blocked cells: no way out. +1 allows passage up; +2 allows passage down; +3 allows passage up and down; +4 allows passage left; +5 allows passage left and up; +6 allows passage left and down; +7 allows passage up, left, and down; +8 allows passage right; +9 allows passage up and right; +10 allows passage down and right; +11 allows passage up, down, and right; +12 allows passage left and right; +13 allows passage up, left, and right; +14 allows passage down, left, and right; and +15 allows passage up, down, left, and right.
I would personally also recommend using the wide version of the ncurses library (ncursesw). (I do not use Windows, so I am not exactly sure how you install and use it in windows, but the ncurses home page does have downloads when using mingw.)
Then, you would have a much wider variety of glyphs you could use. (When using UTF-8 locales, potentially the entire Unicode glyph set -- the Box Drawing block especially would be useful for maze drawing, and most of those glyphs are also available in the old CP437 codepage, which means they should work both in Windows and non-Windows terminals nicely.)
In that case, you'd probably use
cchar_t cell_char[256];
As I mentioned above, you could even do a graphical version (perhaps later on, extending your terminal version?) in C using SDL or GTK+. (Note that the above separation between logical maze cell content value and the visual describing the cell also means you can, at runtime, choose between "themes", by having more than one set of cell images. That allows you to start with crude informational versions, for debugging, and then add visual goodness.)
The approach shown in this answers allows you to start with a simple terminal-based game, and if you decide you want to, add support for graphical UI, with image-based maze cells, without having to rewrite any of your core maze code.

Writing an image to a text/raw file in C

#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char **T;
int H[256];
int I[256][256];
int i,j,a,aux[256];
FILE *fp=fopen("Collines400300.ima","rb");
FILE *fp1=fopen("image4.raw","wb");
int height = 300;
int width = 400;
T=(unsigned char**)malloc(height*sizeof(unsigned char*));
for(i=0;i<height;i++)
{
if (feof(fp))
{
//handle error... could just malloc and memset to zero's
break;
}
T[i]=(unsigned char*)malloc(width*sizeof(unsigned char*));
fread(T[i],1,400,fp);
}
for(i=0;i<256;i++)
H[i]=0;
//filling up the histogram
for(i=0;i<300;i++)
{
for(j=0;j<400;j++)
H[T[i][j]]++;
}
//printing out the values of each gray scale value in the histogram
for(i=0;i<256;i++)
printf("%d ",H[i]);
//converting the values from a scale of 3000 to a scaale of 256 to fit in our new image
for(i=0;i<256;i++)
{
a=(H[i]+6)/12;
aux[i]=a;
}
//initialising the 2D image to white
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
I[i][j]=255;
}
//the loop to make the graph for my histogram. This is where the problem is.
for(i=0;i<256;i++)
{
for(j=254;j>254-aux[i];j--)
{
I[j][i]=0;
fwrite(I[i],1,aux[i],fp1);
}
}
fclose(fp);
fclose(fp1);
return 0;
}
Given an image I am supposed to make a histogram of the image, which I did. Then make a graph of the histogram in a 2D image and write it to a file. I am not getting the graph I want, but a very blurry image with no sense to it. Thank you for any help beforehand.
I[j][i]=0; fwrite(I[i],1,aux[i],fp1); Did you mean to write the column row to file here? It doesn't work that way. You are modifying an element in (column number i) row number j in memory and then writing row number i to file.

Take screenshot with openGL and save it as png

I'm trying to take a screenshot of full screen and save it as a png. I found a code here and modified it a bit. For the screenshot I use openGL and Glut and for the saving in png the gd library for c. All I'm getting is a black png and I can't figure out why. I searched in stackoverflow and found some posts, but unfortunately they didn't help. One of them was to use glReadBuffer( GL_FRONT); instead of glReadBuffer(GL_BACK); I tryed with both of them with no success. Here is my code:
int SVimage2file(char *filename){
int width = glutGet(GLUT_SCREEN_WIDTH);
int height = glutGet( GLUT_SCREEN_HEIGHT);
FILE *png;
GLubyte *OpenGLimage, *p;
gdImagePtr image;
unsigned int r, g, b;
int i,j,rgb;
png = fopen(filename, "wb");
if (png == NULL) {
printf("*** warning: unable to write to %s\n",filename);
return 1;
}
OpenGLimage = (GLubyte *) malloc(width * height * sizeof(GLubyte) * 3);
if(OpenGLimage == NULL){
printf("error allocating image:%s\n",filename);
exit(1);
}
printf("Saving to: %s .\n",filename);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadBuffer( GL_FRONT);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, OpenGLimage);
p = OpenGLimage;
image = gdImageCreateTrueColor(width,height);
for (i = height-1 ; i>=0; i--) {
for(j=0;j<width;j++){
r=*p++; g=*p++; b=*p++;
rgb = (r<<16)|(g<<8)|b;
//printf("the rgb color %d\n", rgb );
gdImageSetPixel(image,j,i,rgb);
}
}
gdImagePng(image,png);
fclose(png);
gdImageDestroy(image);
}
What is it that I'm missing?
You could use the devil image library and take a screeshot with:
void takeScreenshot(const char* screenshotFile)
{
ILuint imageID = ilGenImage();
ilBindImage(imageID);
ilutGLScreen();
ilEnable(IL_FILE_OVERWRITE);
ilSaveImage(screenshotFile);
ilDeleteImage(imageID);
printf("Screenshot saved to: %s\n", screenshotFile);
}
takeScreenshot("screenshot.png");
If you don't reject to use C++ library, you should try PNGwriter! It write the picture pixel by pixel and their RGB values. Since the PNGwriter start form left-up corner while the glReadPixels() start from left-bottom, your code while like:
GLfloat* OpenGLimage = new GLfloat[nPixels];
glReadPixels(0.0, 0.0, width, height,GL_RGB, GL_FLOAT, OpenGLimage);
pngwriter PNG(width, height, 1.0, fileName);
size_t x = 1; // start the top and leftmost point of the window
size_t y = 1;
double R, G, B;
for(size_t i=0; i<npixels; i++)
{
switch(i%3) //the OpenGLimage array look like [R1, G1, B1, R2, G2, B2,...]
{
case 2:
B = (double) pixels[i]; break;
case 1:
G = (double) pixels[i]; break;
case 0:
R = (double) pixels[i];
PNG.plot(x, y, R, G, B);
if( x == width )
{
x=1;
y++;
}
else
{ x++; }
break;
}
}
PNG.close();
PS. I had also try libgd, but it seems only convert one image file (in the hard disk or in memory) to another format of image. But I think it still useful while you want to convert many PNG file to GIF format to create a GIF animate.

Selection of primitives when clicked by mouse not working

I'm developing a solitary board game, which has a piece per square, and each piece can be of two colors. If I click a piece, the four adjacent ones (top, bottom, left and right) all change to the next color.
I'm having problems with detecting in which piece the mouse was clicked on.
I have the following code for the mouse callback:
GLuint selectBuf[BUFSIZE]; // BUFSIZE is defined to be 512
GLint hits;
GLint viewport[4];
if( ( state != GLUT_DOWN ) && ( button != GLUT_LEFT_BUTTON ) )
return;
glGetIntegerv (GL_VIEWPORT, viewport);
glSelectBuffer (BUFSIZE, selectBuf);
(void) glRenderMode (GL_SELECT);
glInitNames();
glPushName(0);
gluPickMatrix ((GLdouble) x, (GLdouble) y, 20.0,20.0, viewport);
draw(GL_SELECT); // the function that does the rendering of the pieces
hits = glRenderMode(GL_RENDER);
processHits (hits, selectBuf); // a function that displays the hits obtained
Now, the problem I have is that I don't quite know how to process the hits occurred which are on selectBuf. I have the following code for processHits:
void processHits (GLint hits, GLuint buffer[])
{
unsigned int i, j;
GLuint ii, jj, names, *ptr;
printf ("hits = %d\n", hits);
ptr = (GLuint *) buffer;
for(i = 0; i < hits; i++) {
printf("hit n. %d ---> %d",i, *(buffer+i));
}
}
Finally, in the draw function I have:
void draw(GLenum mode) {
glClear (GL_COLOR_BUFFER_BIT);
GLuint x,y;
int corPeca; //colourpiece in english
int corCasa; //colourHouse (each square has a diferent color, like checkers)
for (x =0; x < colunas; x++) { //columns
for(y=0; y < colunas; y++) {
if ( (tabuleiro[y*colunas+x].peca) == 1) //board
corPeca = 1;
else
corPeca = 2;
if((tabuleiro[y*colunas+x].quadrado)==1) //square
corCasa = 1;
else
corCasa = 2;
if (mode == GL_SELECT){
GLuint name = 4;
glLoadName(name);
}
desenhaCasa(x,y,corCasa); //draws square
desenhaPeca(x,y,corPeca, mode); //draws piece
}
}
}
Now, has you can see, I've just put 4 into the buffer with glLoadName. However when I pull the number out in processHits I always get 1. I know that's because of the structure of the buffer that gets the hits, but what is that structure and how can I access the number 4?
Thank you very much for helping me.
The structure of the selection buffer is a bit more complex than that. For each hit, a "hit record" consisting of several values is appended to the selection buffer. You can look at Question 20.020 in the OpenGL FAQ for details. In your case, where there is only one name on the stack at a time, the hit record will consist 4 values, with the name being the fourth one. So, in your processHits function, you should write
for(i = 0; i < hits; i++) {
printf("hit n. %d ---> %d",i, *(buffer+4*i+3));
}
Also, the size of your name buffer should probably be 4 times longer as well.

Resources