When we have an IplImage, how can we save it so we can use it later, or view it as an image outside of our code (such as via png, or jpeg)?
As a code example, I have the following:
void SaveImage()
{
CvSize size;
IplImage *rgb_img;
int i = 0;
size.height = HEIGHT;
size.width = WIDTH;
rgb_img = cvCreateImageHeader(size, IPL_DEPTH_8U, 3);
rgb_img->imageData = my_device.ColorBuffer;
rgb_img->imageDataOrigin = rgb_img->imageData;
/*for (i = 2; i < rgb_img->imageSize; i+= 3)
{
// confirming all values print correctly
printf("%d, ", rgb_img->imageData[i]);
}*/
cvSaveImage("foo.png",rgb_img);
}
I have printed out all of the values in the commented out for loop, and it seems like the data is in the buffer correctly. Using cvShowImage to display the image also works correctly, so it seems like the structure of the image is fine.
void SaveImage()
{
CvSize size;
IplImage *rgb_img;
int i = 0;
size.height = HEIGHT;
size.width = WIDTH;
rgb_img = cvCreateImageHeader(size, IPL_DEPTH_8U, 3);
rgb_img->imageData = my_device.ColorBuffer;
// You should NOT have the line below or OpenCV will try to deallocate your data
//rgb_img->imageDataOrigin = rgb_img->imageData;
for (i = 0; i < size.height; i++)
{
for (j = 0;j < size.width; j++)
{
// confirming all values print correctly
printf("%c, ", rgb_img->imageData[i*width + j]);
}
}
cvSaveImage("foo.png",rgb_img);
}
Running this should not crash.
Some problems with your code
You use %f to print but IPL_DEPTH_8U is 1-byte uchar
To save:
cvSaveImage(outFileName,img)
If you wanted to check it had saved, you could do the following:
if(!cvSaveImage(outFileName,img)) printf("Could not save: %s\n",outFileName);
Taken from http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html#SECTION00052000000000000000 - top result on Google for "opencv write iplimage".
Related
I have came across a problem that while reading from a file, I couldn't give my variables a proper value.
I have used a similar approach at a previous project, the only difference is that there I was only supposed to store the height and width of a matrix, and now I also have to store an additional line before I can store the height and width values.
Code:
int fromMountain = 0, fromWater = 0, fromSand = 0, height = 0, width = 0;
char **terrain;
void readFiles() {
inFile = fopen("be.txt", "r");
outFile = fopen("ki.txt", "w");
}
void storeData() {
fscanf(inFile, "%d %d %d\n", &fromMountain, &fromWater, &fromSand);
fscanf(inFile, "%d %d\n", &height, &width);
terrain = (char**)malloc(height*sizeof(char*));
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
fscanf(inFile, "%c", &terrain[i][j]);
}
}
}
void testPrint() {
printf("%d %d %d\n", fromMountain, fromWater, fromSand);
printf("%d %d\n", height, width);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
printf("%c", terrain[i][j]);
}
printf("\n");
}
}
Output:
Code doesn't seem to run properly, there is no output.
Source file:
1 2 2
10 10
~00000000A
00000000AA
00~~~A00XX
000~0A0000
000000000~
A00000000~
000000000~
0000~00000
00000X0000
0A0A000AAA
I have tried changing things up a bit and make my integer variables char type.
That didn't seem to help anything, nothing has changed. Output was still non-existent and I got nowhere closer to a proper solution.
Any form of help is appreciated! :)
Alright, so here's the thing, anyone looking for something similar.
It is not enough to allocate memory for your variable, **terrain in this case, you also have to allocate a piece of memory for the data you would like to store.
After allocating memory for the variable itself, you will need another piece of code, something similar to this:
for (int i = 0; i < height; i++) {
terrain[i] = (char*)malloc(width * sizeof(char));
}
Thanks for Raildex for pointing it out!
I'm trying to write a program that reads a text file into a 2D array of structs, but trying to put a struct into that array causes the program to crash.
Here's the program
ppm.c
#include "ppm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
image parse_ascii_image(FILE *fp) {
char magic[3];
char comm[1024];
char size[10];
image img;
int height;
int width;
... // some code
pixel **pixelarr;
printf("Commencing internal malloc...\n");
if (height <= 1024 && width <= 1024 && height > 0 && width > 0){
pixelarr = (pixel **) malloc(height * sizeof(pixel*));
}else{
fprintf(stderr, "Error: Invalid image size: %d * %d", width, height);
return img;
}
for (int i = 0; i < height; i++){
pixelarr[i] = malloc(width * sizeof(pixel));
}
int d = 0;
int e;
printf("Filling in array:\n");
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++){
for (int i = 0; i < 3; i++){
while ((e = fgetc(fp)) != '\n'){
d = d * 10;
e = e - 60;
d += e;
}
if (i == 0){
pixelarr[row][col].red = d;
}
if (i == 1){
pixelarr[row][col].green = d;
}
if (i == 2){
pixelarr[row][col].blue = d;
}
d = 0;
}
}
}
printf("Finished! Copying pixels over: \n");
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++){
img.pixels[row][col] = pixelarr[row][col];
// ^^^This is where the program crashes
}
}
printf("Finished! Freeing internal malloc:\n");
... // some more code
}
relevant info from ppm.h:
#ifndef PPM_H
#define PPM_H 1
#include <stdio.h>
...
typedef struct pixel pixel;
struct pixel {
int red;
int green;
int blue;
};
typedef struct image image;
struct image {
enum ppm_magic magic; // PPM format
char comments[1024]; // All comments truncated to 1023 characters
int width; // image width
int height; // image height
int max_color; // maximum color value
pixel **pixels; // 2D array of pixel structs.
};
...
// Parses an ASCII PPM file.
image parse_ascii_image(FILE *fp);
...
#endif
If anyone can help me figure out what's causing my program to crash there, I would appreciate it.
Thank you!
A few problems:
1: img.pixels is never initialized. Anytime you create a pointer to something without assigning it a value first, try to set it to NULL so it's easier to debug. Note that this will not fix the issue. To fix it, simply initialize them with a struct instance.
2: You should free pixelarr. Most modern OS's do this, but it's still really, really good practice.
3: Wouldn't it be easier to not use the nested loops, and instead do img.pixels = pixelarr? It achieves the same (unless this is for a class, and this part is required).
I have the following problem with rotating the PPM image to the right
The first two lines in the result image are black (or some color from the rainbow)
Here's the code that sets the buffer for the image (the variables g_Width and g_height are set by a function)
struct pixel *image = malloc(sizeof(struct pixel) * g_width * g_height);
here's the function with the pointer passed into it
void rotate90(struct pixel *img) {
int i, j, size, th;
size = sizeof(struct pixel) * g_width * g_height;
struct pixel *buffer = malloc(size);
if (buffer == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < g_height; i++) {
for (j=0; j < g_width; j++) {
buffer[(g_height*j)+(g_height-i)] = img[(g_width*i) + j];
}
}
//copy the buffer into the image pointer
memcpy(img, buffer, size);
//free the buffer and swap the width and height around
free(buffer);
th = g_height;
g_height = g_width;
g_width = th;
}
If I print the image buffer it comes out just fine, but if I rotate it it comes out like this (note the first 2 lines of pixels)
https://www.dropbox.com/s/vh8l6s26enbxj42/t3.png?dl=0
it's as if the last 2 lines aren't being swapped at all, please help
EDIT: I solved the second black line at least, but I still need help with the
last line
As said you mix the first line (and overflow)
void rotate90(struct pixel *img) {
int i, j, size, th;
size = sizeof(struct pixel) * g_width * g_height;
struct pixel *buffer = malloc(size);
if (buffer == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < g_height; i++) {
for (j=0; j < g_width; j++) {
buffer[(g_height*j)+(g_height-i -- 1)] = img[(g_width*i) + j];
}
}
//copy the buffer into the image pointer
memcpy(img, buffer, size);
//free the buffer and swap the width and height around
free(buffer);
th = g_height;
g_height = g_width;
g_width = th;
}
This would rotate it one way (removing unnecessary brackets)
for (i=0; i<g_height; i++) {
for (j=0; j<g_width; j++) {
buffer[g_height * j + i] = img[g_width * i + j];
}
}
But your code suggest you want it the other way, and the code lacks a -1, resulting in clipping a line at one edge and an undefined line at the other edge.
for (i=0; i<g_height; i++) {
for (j=0; j<g_width; j++) {
buffer[g_height * j + g_height - i - 1] = img[g_width * i + j];
}
}
I'm writing a simple game in C. So I'm trying to save some data to a 2dim array which I malloc'd correctly. The problem is though when I want to pass that variable I wrote to, to another function.
int readMap(FILE *eingabe, map_t *map, config_t *configstruct, pacman_t *pacman)
{
int i = 0, j = 0, k = 0, pac = 0;
map->mapdesign = (char**) malloc(sizeof(char*) * map->height);
do
{
for (i = 0; i < map->height; i++)
{
map->mapdesign[i] = (char*) malloc(sizeof(char) * (map->width + 1));
for (j = 0; j < map->width; j++)
{
fscanf(eingabe, "%c", &map->mapdesign[i][j]);
printf("%c", map->mapdesign[i][j]);
if (map->mapdesign[i][j] == configstruct->ghost)
map->ghostcount++;
else if (map->mapdesign[i][j] == configstruct->foodtypes[0]
|| map->mapdesign[i][j] == configstruct->foodtypes[1])
{
map->foodcount++;
}
for (k = 0; k < PAC; k++)
{
if (map->mapdesign[i][j] == configstruct->pacman[k])
{
pacman->cordinate.x = j;
pacman->cordinate.y = i;
if (pac > 1)
return -1;
pac++;
}
k++;
}
}
}
} while (!feof(eingabe));
return 0;
}
When I use that printf in the function itself it prints out what I want. Then I decided that I want to use a function that prints that out for me which looks like that:
int renderMap(map_t *mapstr)
{
int i = 0;
clrscr();
for (i = 0; i < mapstr->height; i++)
puts(mapstr->mapdesign[i]);
return 0;
}
This function above should print out that:
Pastebin 1
But it actually prints this:
Pastebin 2
Thanks in advance!
I advice that first get the differnce betwwen the two function of printf and puts as they they treat the character termination differently. Thats may be the error.
or send the reletively complete code so that the two function can be run independently I will debug it and return back to you.
I feel that a piece of code I have would cause a memory leak. I have a data structure with two two-dimensional arrays, one containing ints and one containing pointers to dynamically-allocated objects (sprites). The data structure is a tilemap, and the ints are the numeric index of each location, which are read from a file. I call that index 'tiles'. This tells what kind of tile it is, for behavioral purposes (i.e. player responds differently to water than to dirt or ice). The objects are the sprites to draw at their respective locations. That index is known as 'images'. That index tells the tilemap what sprite to draw at that position.
typedef struct
{
int** tiles;
sprite*** images;
int w, h;
} tilemap;
I have a function that creates a new tilemap, initializes it, and returns it.
tilemap* new_tilemap(int w, int h, const char* filename)
{
tilemap* tm = malloc(sizeof(tilemap));
tm->w = w;
tm->h = h;
/*allocate memory space for the tiles index*/
tm->tiles = malloc(sizeof(int) * h);
int i, j;
for (i = 0; i < h; ++i)
{
tm->tiles[i] = malloc(sizeof(int) * w);
}
/*fill the index with the appropriate data from a file*/
FILE* file = fopen (filename, "rb");
if (file == NULL)
{
printf("Failed to open map %s\n", filename);
}
for (j = 0; j < h; ++j)
{
for (i = 0; i < w; ++i)
{
fscanf(file, "%d", &(tm->tiles[j][i]));
}
}
fclose(file);
/*allocate space for the images*/
tm->images = malloc(sizeof(sprite*) * h);
for (i = 0; i < h; ++i)
{
tm->images[i] = malloc(sizeof(sprite*) * w);
}
/*load images based on what type of tile is at that position*/
for (j = 0; j < h; ++j)
{
for (i = 0; i < w; ++i)
{
switch (tm->tiles[j][i])
{
case 0:
tm->images[j][i] = new_sprite_file("dat/tiles/0.bmp", 1);
break;
case 1:
tm->images[j][i] = new_sprite_file("dat/tiles/1.bmp", 2);
break;
}
tm->images[j][i]->x = i*tm->images[j][i]->w;
tm->images[j][i]->y = j*tm->images[j][i]->h;
}
}
return tm;
}
Then, to free the tilemap and all it's structures I have this function:
void free_tilemap(tilemap* tm)
{
/*loop through and free each of the images in the array*/
int i, j;
for (j = 0; j < tm->h; ++j)
{
for (i = 0; i < tm->w; ++i)
{
free(tm->images[j][i]);
}
}
/*free the actual array*/
free(tm->images);
/*free the tile array?*/
free(tm->tiles);
/*free the entire tilemap structure*/
free(tm);
}
However, I feel that it isn't freeing up all the memory I have allocated, because I used malloc twice on the tiles, but only free'd once. I don't know if this is a problem though, seeing as they are ints, but I think that I may have to loop through the tiles array, free every row, then loop through and free every column (containing the rows), in the same manner as it was allocated. Is that what needs to be done or am I just being ignorant and/or paranoid? The same with the images array. Also, feel free to point out other flaws in my code as I know I'm not the best programmer.
Of course you should mirror the mallocs when you free.
for (i = 0; i < h; ++i)
{
tm->tiles[i] = malloc(sizeof(int) * w);
}
/* Inside free_tilemap. */
for (i = 0; i < h; ++i)
{
free(tm->tiles[i]);
}
free(tm->tiles);
Same goes for the other fors that closely resemble this one. Freeing just tiles doesn't automatically free tiles[0..h] in cascade.
Looking at the code quickly I would say that you are indeed missing the free's on the tiles. I would suggest to use a memory analyzer to find out for yourself. E.g. http://www.cprogramming.com/debugging/valgrind.html
That will give you a good overview of allocated memory, and possible memory leaks when the program exits.