Problems using OpenCV with ZBar in C - c

I'm trying to use OpenCV to load a jpg image from file and pass it to zbar library to decode a barcode. However, no barcodes are decoded properly, even though the code below works when I use functions from libpng to load the image. I have no errors, and I have no idea where the problem is, as I have already checked all posts I could find and nothing worked.
Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <zbar.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>
zbar_image_scanner_t *scanner = NULL;
IplImage* cvLoadImage(const char* filename, int iscolor);
int main (int argc, char **argv)
{
// create a reader
scanner = zbar_image_scanner_create();
// configure the reader
zbar_image_scanner_set_config(scanner, 0, ZBAR_CFG_ENABLE, 1);
// obtain image data with opencv
IplImage* img = 0;
int height,width,step,channels;
img = cvLoadImage(argv[1], 1);
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
void *raw = (void *)(img->imageData);
printf("Processing a %dx%d image \n",height,width);
// wrap image data
zbar_image_t *image = zbar_image_create();
zbar_image_set_format(image, *(int*)"Y800");
zbar_image_set_size(image, width, height);
zbar_image_set_data(image, raw, width * height, zbar_image_free_data);
// scan the image for barcodes
int n = zbar_scan_image(scanner, image);
if (n==0){
printf("No barcode detected for image %s\n", argv[1]);
return 1;
}
// extract results
if (n!=0) {
const zbar_symbol_t *symbol = zbar_image_first_symbol(image);
printf("symbol extracted \n");
for(; symbol; symbol = zbar_symbol_next(symbol)) {
// do something useful with results
zbar_symbol_type_t typ = zbar_symbol_get_type(symbol);
const char *dataZ = zbar_symbol_get_data(symbol);
printf("decoded %s symbol \"%s\" of image %s \n", zbar_get_symbol_name(typ), dataZ, argv[1]);
}
}
// clean up
zbar_image_destroy(image);
zbar_image_scanner_destroy(scanner);
return 0;
}

That code worked perfectly for me. I used it in my program with small changes:
I don't show how I get the 'struct _IplImage *' {aka 'IplImage *'} because it is done in another file, and get it as param, but it is of course done with cvLoadImage().
I used "GREY" instead of "Y800", but I tried "Y800" and also worked, as they are fundamentally the same.
This works (at least with openCV 2.4.9; openCV is deprecating its C API, and its C++ API should be used instead (I'm against this, but nothing can be done :( )):
/******************************************************************************
******* headers **************************************************************
******************************************************************************/
/* Standard C ----------------------------------------------------------------*/
/* snprintf() */
#include <stdio.h>
/* Packages ------------------------------------------------------------------*/
/* opencv */
#include <cv.h>
/* zbar */
#include <zbar.h>
/* Module --------------------------------------------------------------------*/
#include "this_file.h"
/******************************************************************************
******* macros ***************************************************************
******************************************************************************/
# define ZB_CODES_MAX (10)
# define ZBAR_LEN_MAX (1048576)
/******************************************************************************
******* structs **************************************************************
******************************************************************************/
struct ZB_Codes {
int n;
struct {
int type;
char sym_name [80];
char data [ZBAR_LEN_MAX];
} arr [ZB_CODES_MAX];
};
/******************************************************************************
******* variables ************************************************************
******************************************************************************/
struct ZB_Codes zb_codes;
/******************************************************************************
******* functions ************************************************************
******************************************************************************/
void img_zb_decode (struct _IplImage *imgptr)
{
struct zbar_image_scanner_s *scanner;
struct zbar_image_s *image_zb;
const struct zbar_symbol_s *symbol;
/* Type of code to scan */
/* 0 for all; set to another if used only for a specific barcode */
int code_type;
code_type = 0;
/* create & configure a reader */
scanner = zbar_image_scanner_create();
zbar_image_scanner_set_config(scanner, code_type, ZBAR_CFG_ENABLE, 1);
/* wrap image data */
image_zb = zbar_image_create();
zbar_image_set_format(image_zb, *(int *)"GREY");
zbar_image_set_size(image_zb, imgptr->width, imgptr->height);
zbar_image_set_data(image_zb, (void *)(imgptr->imageData),
(imgptr->width * imgptr->height), NULL);
/* scan the image for barcodes */
int i;
zb_codes.n = zbar_scan_image(scanner, image_zb);
if (zb_codes.n) {
/* extract results */
symbol = zbar_image_first_symbol(image_zb);
for (i = 0; i < ZB_CODES_MAX && symbol; i++) {
/* Write results into array */
zb_codes.arr[i].type = zbar_symbol_get_type(symbol);
snprintf(zb_codes.arr[i].sym_name, 80, "%s",
zbar_get_symbol_name(
zb_codes.arr[i].type));
snprintf(zb_codes.arr[i].data, ZBAR_LEN_MAX, "%s",
zbar_symbol_get_data(symbol));
/* Load next symbol */
symbol = zbar_symbol_next(symbol);
}
}
/* clean up */
zbar_image_destroy(image_zb);
zbar_image_scanner_destroy(scanner);
}
/******************************************************************************
******* end of file **********************************************************
******************************************************************************/

Related

Linux framebuffer driver and custom file operation

I implemented a framebuffer driver retrieved from a former project in Linux for an embedded system and what I need to do is quite simple: draw a small rectangle where the screen is touched.
In order to do this, I want to use the function xxxfb_fillrect() that you can find in the following driver code (some parts are omitted) :
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/console.h>
#define PCI_VENDOR_ID_XXX 0x10F610F6
#define PCI_DEVICE_ID_XXX 0x2864C826
#define PCI_CLASS_MASK 0x00FF
#define FB_NAME "MFCC8556_vfb_"
#define FB_MAJOR 29
#define VIDEOMEMSIZE (480*800*3)
#define FBIO_TEST _IO('F', 0x21)
/* Global variable */
/*
* Driver data
*/
//static char *videomemory;
static int fb_count = 3;
static u_long videomemorysize = VIDEOMEMSIZE;
/* array of framebuffer */
static struct fb_info **g_fb_list;
static struct fb_fix_screeninfo fix_default __initdata = {
.id = FB_NAME,
.smem_len = VIDEOMEMSIZE,
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
.xpanstep = 0,
.ypanstep = 0,
.ywrapstep = 0,
.accel = FB_ACCEL_NONE,
};
static struct fb_var_screeninfo var_default __initdata = {
.xres = 800,
.yres = 480,
.xres_virtual = 800,
.yres_virtual = 480,
.bits_per_pixel = 24,
.red = {0, 8, 0},
.green = {0, 8, 0},
.blue = {0, 8, 0},
.grayscale = 0,
.activate = FB_ACTIVATE_TEST,
.height = -1,
.width = -1,
.pixclock = 30060,
.vmode = FB_VMODE_NONINTERLACED,
};
static int xxxfb_init(void);
static int register_fb(struct fb_info *info);
static int set_screen_base(struct fb_info* info);
static int init_fb_info(struct fb_info *info, struct fb_ops *fbops, unsigned int id_no);
static int alloc_fb_info (struct fb_info **info);
/* ------------ Accelerated Functions --------------------- */
/*
* We provide our own functions if we have hardware acceleration
* or non packed pixel format layouts. If we have no hardware
* acceleration, we can use a generic unaccelerated function. If using
* a pack pixel format just use the functions in cfb_*.c. Each file
* has one of the three different accel functions we support.
*/
/**
* xxxfb_fillrect - REQUIRED function. Can use generic routines if
* non acclerated hardware and packed pixel based.
* Draws a rectangle on the screen.
*
* #info: frame buffer structure that represents a single frame buffer
* #region: The structure representing the rectangular region we
* wish to draw to.
*
* This drawing operation places/removes a retangle on the screen
* depending on the rastering operation with the value of color which
* is in the current color depth format.
*/
void xxxfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
{
/* Meaning of struct fb_fillrect
*
* #dx: The x and y coordinates of the upper left hand corner of the
* #dy: area we want to draw to.
* #width: How wide the rectangle is we want to draw.
* #height: How tall the rectangle is we want to draw.
* #color: The color to fill in the rectangle with.
* #rop: The raster operation. We can draw the rectangle with a COPY
* of XOR which provides erasing effect.
*/
struct fb_fillrect *tmp_fillrect;
/*ptr=(unsigned long*)info->screen_base;
//fill the screen base ///
for(i=0; i<800*10; i++){
*ptr=0x0000FF00;
ptr++;
}*/
printk(KERN_DEBUG "\nfb_fillrect()");
printk(KERN_DEBUG "\nFix Screen Info.id =%s\n", info->fix.id);
/* printk(KERN_INFO "\nstruct fb_fillrect:\n"
"dx = %d\n"
"dy = %d\n"
"width = %d\n"
"height = %d\n"
"color = 0x%08X\n"
"rop = 0x%X\n___\n"
, region->dx, region->dy, region->width, region->height, region->color, region->rop);
*/
// printk(KERN_INFO "_in fill_rectangle : screen_base = 0x%X\n0x_%02X_%02X_%02X_%02X\n...\n",(unsigned int)info->screen_base, *info->screen_base, *(info->screen_base+1), *(info->screen_base+2),*(info->screen_base+3));
tmp_fillrect = kmalloc(sizeof(struct fb_fillrect), GFP_KERNEL);
*tmp_fillrect = *region;
/*tmp_fillrect->dx=400;
tmp_fillrect->dy=200;
tmp_fillrect->width=100;
tmp_fillrect->height=50;
tmp_fillrect->color=0x0000FF00;
tmp_fillrect->rop=0x0;
*/
//tmp = copy_from_user(tmp_fillrect, region, sizeof(struct fb_fillrect));
printk(KERN_INFO "\nstruct fb_fillrect:\n"
"dx = %d\n"
"dy = %d\n"
"width = %d\n"
"height = %d\n"
"color = 0x%08X\n"
"rop = 0x%X\n___\n"
, tmp_fillrect->dx, tmp_fillrect->dy, tmp_fillrect->width, tmp_fillrect->height, tmp_fillrect->color, tmp_fillrect->rop);
//if (tmp) printk(KERN_ERR "**ERROR: copy_from_user = %d\n", tmp);
cfb_fillrect(info, region);
}
...
int xxxfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg){
int ret = 0;
printk(KERN_INFO "fb_ioctl()");
mutex_lock(&info->lock);
switch(cmd) {
case FBIOGET_VSCREENINFO:
printk(KERN_DEBUG "FBIOGET_VSCREENINFO");
break;
case FBIOGET_FSCREENINFO:
printk(KERN_DEBUG "FBIOGET_FSCREENINFO");
break;
case FBIO_TEST:
printk(KERN_DEBUG "FBIO_TEST");
break;
default:
printk(KERN_DEBUG "ioctl DEFAULT");
break;
}
mutex_unlock(&info->lock);
return ret;
}
/*
* Frame buffer operations
*/
static struct fb_ops xxxfb_ops = {
.owner = THIS_MODULE,
.fb_open = xxxfb_open,
.fb_read = fb_sys_read,
.fb_write = fb_sys_write,
.fb_release = xxxfb_release,
.fb_check_var = xxxfb_check_var,
.fb_set_par = xxxfb_set_par,
//.fb_setcolreg = xxxfb_setcolreg,
.fb_blank = xxxfb_blank,
.fb_pan_display = xxxfb_pan_display,
.fb_fillrect = xxxfb_fillrect, /* Needed !!! */
.fb_copyarea = xxxfb_copyarea, /* Needed !!! */
.fb_imageblit = xxxfb_imageblit, /* Needed !!! */
.fb_cursor = xxxfb_cursor, /* Optional !!! */
.fb_sync = xxxfb_sync,
.fb_ioctl = xxxfb_ioctl,
.fb_mmap = xxxfb_mmap,
};
/* ------------------------------------------------------------------------- */
...
/*
* Modularization
*/
module_init(xxxfb_init);
module_exit(xxxfb_exit);
MODULE_LICENSE("GPL");
But the thing is, I have no idea how to call it. I ended up implementing the drawing of the rectangle manually without using this fb_fillrect().
I know this is not a usual open/rd/wr/... operation, but it is here. How do I use it ? Should I call it with ioctl()? If yes, why is fb_fillrect appearing in the frame buffer operations struct ?
Thank you in advance for your help.
The functions in fb_ops are low level operations not directly exposed to user-space. Instead, there is a fb_fops struct in drivers/video/fbdev/core/fbmem.c that contains the handler functions for the open/read/write/ioctl from user-space (see code below). Some of those handler functions may call subsequently call the fb_ops functions from your driver (see do_fb_ioctl function).
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
...
};
static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct fb_info *info = file_fb_info(file);
if (!info)
return -ENODEV;
return do_fb_ioctl(info, cmd, arg);
}
static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
struct fb_ops *fb;
...
switch (cmd) {
case FBIOGET_VSCREENINFO:
...
case FBIOPUT_VSCREENINFO:
...
case FBIOGET_FSCREENINFO:
...
case FBIOPAN_DISPLAY:
...
default:
if (!lock_fb_info(info))
return -ENODEV;
fb = info->fbops;
if (fb->fb_ioctl)
ret = fb->fb_ioctl(info, cmd, arg);
else
ret = -ENOTTY;
unlock_fb_info(info);
}
return ret;
}
In other cases, fb_ops functions may be used by drivers like fbcon that work on top of fbdev. Here is an example of fb_fillrect being called directly by a framebuffer console driver http://lxr.free-electrons.com/source/drivers/video/console/fbcon_cw.c#L80.
static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width)
{
struct fbcon_ops *ops = info->fbcon_par;
struct fb_fillrect region;
...
info->fbops->fb_fillrect(info, &region);
}

How to produce sound in C on Linux?

I need a way to play certain musical notes in my C program on Linux.
When using windows, it is possible to #include <dos.h> and use straight forward functions like sound(note/frequency), delay(time in ms), and the self explaining nosound().
Is there anything parallel on Linux?
Thanks
I like the tip above concerning libao - I just gave it a try and it works nicely. Here is a similar level of complexity using OpenAL to synthesize a raw audio buffer in PCM format then to render as audio
// sudo apt-get install libopenal-dev
// gcc -o openal_play_monday openal_play_monday.c -lopenal -lm
#include <stdio.h>
#include <stdlib.h> // gives malloc
#include <math.h>
#ifdef __APPLE__
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#elif __linux
#include <AL/al.h>
#include <AL/alc.h>
#include <unistd.h>
#endif
ALCdevice * openal_output_device;
ALCcontext * openal_output_context;
ALuint internal_buffer;
ALuint streaming_source[1];
int al_check_error(const char * given_label) {
ALenum al_error;
al_error = alGetError();
if(AL_NO_ERROR != al_error) {
printf("ERROR - %s (%s)\n", alGetString(al_error), given_label);
return al_error;
}
return 0;
}
void MM_init_al() {
const char * defname = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
openal_output_device = alcOpenDevice(defname);
openal_output_context = alcCreateContext(openal_output_device, NULL);
alcMakeContextCurrent(openal_output_context);
// setup buffer and source
alGenBuffers(1, & internal_buffer);
al_check_error("failed call to alGenBuffers");
}
void MM_exit_al() {
ALenum errorCode = 0;
// Stop the sources
alSourceStopv(1, & streaming_source[0]); // streaming_source
int ii;
for (ii = 0; ii < 1; ++ii) {
alSourcei(streaming_source[ii], AL_BUFFER, 0);
}
// Clean-up
alDeleteSources(1, &streaming_source[0]);
alDeleteBuffers(16, &streaming_source[0]);
errorCode = alGetError();
alcMakeContextCurrent(NULL);
errorCode = alGetError();
alcDestroyContext(openal_output_context);
alcCloseDevice(openal_output_device);
}
void MM_render_one_buffer() {
/* Fill buffer with Sine-Wave */
// float freq = 440.f;
float freq = 100.f;
float incr_freq = 0.1f;
int seconds = 4;
// unsigned sample_rate = 22050;
unsigned sample_rate = 44100;
double my_pi = 3.14159;
size_t buf_size = seconds * sample_rate;
// allocate PCM audio buffer
short * samples = malloc(sizeof(short) * buf_size);
printf("\nhere is freq %f\n", freq);
int i=0;
for(; i<buf_size; ++i) {
samples[i] = 32760 * sin( (2.f * my_pi * freq)/sample_rate * i );
freq += incr_freq; // change freq just to make things interesting
if (100.0 > freq || freq > 5000.0) {
incr_freq *= -1.0f; // toggle direction of freq increment
}
}
/* upload buffer to OpenAL */
alBufferData( internal_buffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate);
al_check_error("populating alBufferData");
free(samples);
/* Set-up sound source and play buffer */
// ALuint src = 0;
// alGenSources(1, &src);
// alSourcei(src, AL_BUFFER, internal_buffer);
alGenSources(1, & streaming_source[0]);
alSourcei(streaming_source[0], AL_BUFFER, internal_buffer);
// alSourcePlay(src);
alSourcePlay(streaming_source[0]);
// ---------------------
ALenum current_playing_state;
alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
al_check_error("alGetSourcei AL_SOURCE_STATE");
while (AL_PLAYING == current_playing_state) {
printf("still playing ... so sleep\n");
sleep(1); // should use a thread sleep NOT sleep() for a more responsive finish
alGetSourcei(streaming_source[0], AL_SOURCE_STATE, & current_playing_state);
al_check_error("alGetSourcei AL_SOURCE_STATE");
}
printf("end of playing\n");
/* Dealloc OpenAL */
MM_exit_al();
} // MM_render_one_buffer
int main() {
MM_init_al();
MM_render_one_buffer();
}
If you want to take OpenAL further ... take a gander at this
https://github.com/scottstensland/render-audio-openal
Out of the box OpenAL plays a buffer of PCM audio just fine ... however it leaves as an exercise the ability to play a stream. In that github repo I wrote an audio server using OpenAL which implements playing streaming audio ... enjoy
Windows uses its own one and only sound architecture, therefore you can access the sound() routine.
Different linux machines, depending on the packages installed, may require different approaches.
Maybe the utility beep (out of this question on stackexchange) can guide you to the right direction
one way
including
#include<conio.h>
and in side main() or where you want to use call print("\a")
printf("\a");
2nd way
including header file
#include <windows.h>
and calling function
Beep(500, 500);
Beep(freq, dur); where freq =beep frequency which is int and dutation in also int

Extracting sequence header from mpeg video file

I am new too mpeg2dec and I Have been trying to extract sequence header from a video file with mpeg2.h(from libmpeg2) but not getting anywhere.
I tried by getting STATE_SEQUENCE and tried to point to that location in the file but could not copy that to another file.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
//mpeg2dec library
#include "mpeg2dec/mpeg2.h"
//jni header
#include "VideoProc.h"
int mpeg2Fun(uint8_t * pointer);
//jni function to get byte array from and return integer
JNIEXPORT jint JNICALL Java_VideoProc_mpeg2FunC(JNIEnv * env, jobject jobj, jbyteArray bytes)
{
jbyte u_byte[4096] ;
(*env)->GetByteArrayRegion(env,bytes, 0, 4096, u_byte);
jint reply=mpeg2Fun(u_byte);
return reply;
}
int mpeg2Fun(uint8_t * pointer)
{
mpeg2dec_t * decoder;
const mpeg2_info_t * info;
const mpeg2_sequence_t * sequence;
mpeg2_state_t state;
size_t size;
int framenum = 0;
decoder = mpeg2_init ();
if (decoder == NULL) {
fprintf (stderr, "Could not allocate a decoder object.\n");
exit (1);
}
info = mpeg2_info (decoder);
int t;
size = (size_t)-1;
do {
state = mpeg2_parse (decoder);
sequence = info->sequence;
switch (state) {
case STATE_BUFFER:
mpeg2_buffer (decoder, pointer, pointer + 4096);
break;
case STATE_SEQUENCE:
t=mpeg2_getpos(decoder);
return 4096-t;
break;
default:
break;
}
} while (size);
mpeg2_close (decoder);
}
In the statement of case STATE_SEQUENCE: instead of returning position, I wanted to write the whole sequence header to the another file. Is that correct or not ?

tinyc compiler - libtcc, how to bound check?

im using libtcc to compile c code on the fly. Im going to use it on a cloud computer, to be used over the internet.
how do i use tinyc's built in memory and bound checker function?
heres an example that comes with the tinyc libtcc library?
any help would be great!
thank you!
/*
* Simple Test program for libtcc
*
* libtcc can be useful to use tcc as a "backend" for a code generator.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "libtcc.h"
/* this function is called by the generated code */
int add(int a, int b)
{
return a + b;
}
char my_program[] =
"int fib(int n)\n"
"{\n"
" if (n <= 2)\n"
" return 1;\n"
" else\n"
" return fib(n-1) + fib(n-2);\n"
"}\n"
"\n"
"int foo(int n)\n"
"{\n"
" printf(\"Hello World!\\n\");\n"
" printf(\"fib(%d) = %d\\n\", n, fib(n));\n"
" printf(\"add(%d, %d) = %d\\n\", n, 2 * n, add(n, 2 * n));\n"
" return 0;\n"
"}\n";
int main(int argc, char **argv)
{
TCCState *s;
int (*func)(int);
void *mem;
int size;
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
if (argc == 2 && !memcmp(argv[1], "lib_path=",9))
tcc_set_lib_path(s, argv[1]+9);
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
if (tcc_compile_string(s, my_program) == -1)
return 1;
/* as a test, we add a symbol that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
/* get needed size of the code */
size = tcc_relocate(s, NULL);
if (size == -1)
return 1;
/* allocate memory and copy the code into it */
mem = malloc(size);
tcc_relocate(s, mem);
/* get entry symbol */
func = tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* delete the state */
tcc_delete(s);
/* run the code */
func(32);
free(mem);
return 0;
}
you can set bounds checking manually using:
s->do_bounds_check = 1; //s here is TCCState*
just make sure libtcc is compiled with CONFIG_TCC_BCHECK being defined.
you may also want to enable debugging using:
s->do_debug = 1;
the command line option -b does the exact same to enable bounds checking (it enables debugging as well).

Values of an array changing randomly during execution

I'm trying to make a little programme in C using SDL, displaying a robot moving on a grid. This grid is represented by a txt file of 0s and 1s.
Here is the fonction creating an array from the txt file, which works.
// create a map(array) from a text file
int (*newMap())[SIZE_HEIGHT][SIZE_WIDTH]
{
static const char filename[] = "input.txt"; /* the name of a file to open */
FILE *file = fopen(filename, "r"); /* try to open the file */
int map[SIZE_HEIGHT][SIZE_WIDTH];
char line[BUFSIZ]; /* space to read a line into */
int k = 0;
while ( fgets(line, sizeof line, file)!=NULL && k<SIZE_HEIGHT) /* read each line */
{
int i;
char *token = line; /* point to the beginning of the line */
for ( i = 0; i<SIZE_WIDTH; i++ )
{
map[k][i]=((int)*token)-48;
token+=sizeof(char);
printf("map[%d][%d]=%d\n", (int)k,(int)i,map[k][i]);
}
puts("----\n");
k++;
}
fclose(file);
int (*p)[SIZE_HEIGHT][SIZE_WIDTH];
p=&map;
return p;
}
Then I try to put the grid on the sreen (not the whole fonction):
#include <stdlib.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <time.h>
#include <string.h>
#include "Parameters.h"
#include "simulation.h"
#include "editor.h"
void simulate(SDL_Surface *ecran)
{
SDL_Surface *carreVert = SDL_LoadBMP("carreVert.bmp");
SDL_Surface *carreRouge = SDL_LoadBMP("carreRouge.bmp");
SDL_Surface *robot = SDL_LoadBMP("robotRouge.bmp");
SDL_SetColorKey(robot, SDL_SRCCOLORKEY, SDL_MapRGB(robot->format, 255, 255, 255));
int (*map)[SIZE_HEIGHT][SIZE_WIDTH];
map=newMap();
SDL_Rect positionFond;
int i;
int j;
for(j=0; j<SIZE_HEIGHT; j++)
{
for(i=0; i<SIZE_WIDTH; i++)
{
positionFond.x = 100*i;
positionFond.y = 100*j;
if((*map)[j][i]+1)
{
SDL_BlitSurface(carreVert, NULL, ecran, &positionFond);
}else
{
SDL_BlitSurface(carreRouge, NULL, ecran, &positionFond);
}
}
}
And then something strange happens: when I observe the array *map with the debugger, I see that the values are changing when I go through the test. So the grid does appear, but not with the right pattern. Why does that happen?
Edit:no error an compiler.
Edit: Any guess of what might do that would be gladly accepted.
The array map is local to the function. It ceases to exist when the function finishes. You pass its address to the caller, but when the caller tries to use it ... BANG!
Fast solution: make the array map a static one: make sure you never call newMap more than once per run.
Other solutions:
move the creation of the array outwards and pass the address around
use malloc and friends to manage the array
You are returning a pointer to an object with automatic storage duration (an array that gets "deallocated" on return from the function where it is declared), so you end up seeing random garbage.

Resources