I made a backtracking code which solves a sudoku and I want to display it on the screen using C libraries. I know that I can use GTK, but I think it is too complicated for my level.
How can I create an image with the solution displayed on a sudoku grid. It doesn't need to create the grid too, it is ok if I use an image with a grid as an input. So basically, I have a matrix (the sudoku solution) and I want to display it as an image.
I mention that I use VSC on a Virtual Machine with Mint.
From my top comments ...
I assume you already have a 2D matrix that represents your board position.
You might consider using SDL2 instead of GTK as it's much simpler and can display directly to a window.
Or, you can create an image file and then use system to invoke a display program (e.g. ImageMagick's display command). It's pretty easy to output a .bmp file.
Or, you could create a .ppm format file--that's even simpler.
You could even output text graphics as a sudoku representation isn't too complex.
ImageMagick's convert can convert a format to any other format.
Thank you for your help! I still have a question. #CraigEstey, How do I convert my 2D matrix who looks like a sudoku into a matrix that can be displayed as a ppm or bmp. I assume that I need to have a matrix of pixels for that. – Ionut Becheru
Yes, you'll need a pixel matrix.
But, if you just create that yourself, you'll have to create a bunch of drawing primitives for drawing rectangles, drawing text fonts, adding colors, etc. In particular, drawing text into an image is complicated (we need a font definition).
So, once again, I suggest using a graphics package that does all that for you. And, again, I suggest SDL2.
In addition to the development package for SDL2, [on fedora, at least], you'll need to install the development package for SDL2_ttf. And, you'll need the font packages.
So, you'll need:
SDL2-devel
SDL2_ttf-devel
gnu-free-sans-fonts
gnu-free-fonts-common
The following code is adapted and enhanced from: How to render text in SDL2?
I added the grid drawing, box drawing, adapted the text draw to draw the sudoku numbers inside their boxes, and saving of the image to a .ppm file.
To build, do (e.g.):
cc -o sudrend sudrend.c `pkg-config --libs --cflags SDL2_ttf` -g
Here is the code. It's a bit messy [and crude] but it works:
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#if 0
#define WINDOW_WIDTH 512
#endif
#if 0
#define WINDOW_WIDTH (64 * 9)
#endif
#if 1
#define WINDOW_WIDTH (32 * 9)
#endif
#define WINDOW_HEIGHT (WINDOW_WIDTH)
#define GRIDMAX (WINDOW_WIDTH / 3)
#define SUDBOXMAX 3
#define SUDXMAX (SUDBOXMAX * 3)
#define SUDYMAX (SUDBOXMAX * 3)
typedef int board_t[SUDYMAX][SUDXMAX];
typedef unsigned char byte;
typedef struct {
byte r;
byte g;
byte b;
#ifdef PIX32
byte a;
#endif
} pixel_t;
board_t brd;
TTF_Font *font;
/*
- x, y: upper left corner.
- texture, rect: outputs.
*/
void
get_text_and_rect(SDL_Renderer *renderer,
int x, int y,
char *text, TTF_Font *font,
SDL_Texture **texture, SDL_Rect *rect)
{
int text_width;
int text_height;
SDL_Surface *surface;
#if 0
SDL_Color textColor = { 255, 255, 255, 0 };
#endif
#if 0
SDL_Color textColor = { 237, 135, 45, 0 };
#endif
#if 1
SDL_Color textColor = { 255, 69, 0, 0 };
#endif
surface = TTF_RenderText_Solid(font,text,textColor);
*texture = SDL_CreateTextureFromSurface(renderer,surface);
text_width = surface->w;
text_height = surface->h;
SDL_FreeSurface(surface);
rect->x = x;
rect->y = y;
rect->w = text_width;
rect->h = text_height;
}
// genboard -- generate sudoku board
void
genboard(board_t brd)
{
for (int y = 0; y < SUDYMAX; ++y) {
for (int x = 0; x < SUDYMAX; ++x)
brd[y][x] = 0;
}
int maxpt = (rand() % (SUDYMAX * SUDXMAX)) + 1;
for (int curpt = 0; curpt < maxpt; ++curpt) {
int y = rand() % SUDYMAX;
int x = rand() % SUDYMAX;
int val = rand() % 10;
brd[y][x] = val;
}
}
// prtboard -- print sudoku board as text
void
prtboard(board_t brd)
{
for (int y = 0; y < SUDYMAX; ++y) {
if ((y % 3) == 0)
printf("\n");
for (int x = 0; x < SUDYMAX; ++x) {
if ((x % 3) == 0)
printf(" ");
int val = brd[y][x];
if (val == 0)
printf(" *");
else
printf(" %d",val);
}
printf("\n");
}
}
void
drawgrid(SDL_Renderer *renderer)
{
int gridmax;
int boxmax;
SDL_Rect rect;
#if 0
SDL_SetRenderDrawColor(renderer, 0, 0xFF, 0, 0);
#endif
#if 0
SDL_SetRenderDrawColor(renderer,143,188,143,0);
#endif
#if 1
SDL_SetRenderDrawColor(renderer,0,0,139,0);
#endif
gridmax = GRIDMAX;
boxmax = SUDYMAX;
for (int ybox = 0; ybox < boxmax; ++ybox) {
int ybase = ybox * gridmax;
rect.y = ybase;
rect.h = gridmax;
for (int xbox = 0; xbox < boxmax; ++xbox) {
int xbase = xbox * gridmax;
rect.x = xbase;
rect.w = gridmax;
SDL_RenderDrawRect(renderer,&rect);
}
}
}
void
drawbox(SDL_Renderer *renderer)
{
int gridmax;
int boxmax;
SDL_Rect rect;
#if 0
SDL_SetRenderDrawColor(renderer, 255, 216, 0, 0);
#else
SDL_SetRenderDrawColor(renderer,255,250,205,0);
#endif
gridmax = GRIDMAX / 3;
boxmax = SUDYMAX * 3;
for (int ybox = 0; ybox < boxmax; ++ybox) {
int ybase = ybox * gridmax;
rect.y = ybase;
rect.h = gridmax;
for (int xbox = 0; xbox < boxmax; ++xbox) {
int xbase = xbox * gridmax;
rect.x = xbase;
rect.w = gridmax;
SDL_RenderDrawRect(renderer,&rect);
}
}
}
void
drawtext(SDL_Renderer *renderer)
{
int gridmax;
int boxmax_y;
int boxmax_x;
SDL_Rect grect;
SDL_Rect trect;
SDL_Texture *texture;
char buf[2];
#if 0
SDL_SetRenderDrawColor(renderer, 255, 216, 0, 0);
#endif
#if 0
SDL_SetRenderDrawColor(renderer,255,250,205,0);
#endif
#if 1
SDL_SetRenderDrawColor(renderer,0,0,0,0);
#endif
gridmax = GRIDMAX / 3;
#if 0
boxmax_y = SUDYMAX * 3;
boxmax_x = SUDXMAX * 3;
#else
boxmax_y = SUDYMAX;
boxmax_x = SUDXMAX;
#endif
for (int ybox = 0; ybox < boxmax_y; ++ybox) {
int ybase = ybox * gridmax;
grect.y = ybase + gridmax / 3;
grect.h = gridmax / 3;
for (int xbox = 0; xbox < boxmax_x; ++xbox) {
int chr = brd[ybox][xbox];
if (chr != 0)
buf[0] = chr + '0';
else
buf[0] = ' ';
buf[1] = 0;
get_text_and_rect(renderer, 0, 0, buf, font, &texture, &trect);
int xbase = xbox * gridmax;
grect.x = xbase + gridmax / 3;
grect.w = gridmax / 3;
SDL_RenderCopy(renderer, texture, &trect, &grect);
SDL_DestroyTexture(texture);
}
}
}
// imgsave -- save image to P6 .ppm file
void
imgsave(SDL_Renderer *renderer,int imgno)
{
int pitch;
FILE *xf;
char file[1000];
pixel_t *pixmap;
pitch = sizeof(pixel_t) * WINDOW_WIDTH;
pixmap = malloc(pitch * WINDOW_HEIGHT);
// get pixel map from renderer image
#ifdef PIX32
SDL_RenderReadPixels(renderer,NULL,SDL_PIXELFORMAT_RGBA32,pixmap,pitch);
#else
SDL_RenderReadPixels(renderer,NULL,SDL_PIXELFORMAT_RGB24,pixmap,pitch);
#endif
sprintf(file,"img%3.3d.ppm",imgno);
xf = fopen(file,"w");
fprintf(xf,"P6\n");
fprintf(xf,"%d %d",WINDOW_WIDTH,WINDOW_HEIGHT);
fprintf(xf," %d\n",255);
#ifdef PIX32
pixel_t *pixcur = &pixmap[0];
pixel_t *pixlim = &pixmap[WINDOW_WIDTH * WINDOW_HEIGHT];
for (; pixcur < pixlim; ++pixcur) {
fputc(pixcur->r,xf);
fputc(pixcur->g,xf);
fputc(pixcur->b,xf);
}
#else
fwrite(pixmap,sizeof(pixel_t),WINDOW_WIDTH * WINDOW_HEIGHT,xf);
#endif
fclose(xf);
free(pixmap);
}
void
fontinit(const char *font_tail)
{
const char *dir;
char font_path[1000];
TTF_Init();
for (int idx = 0; idx <= 1; ++idx) {
switch (idx) {
case 0:
dir = NULL;
break;
default: // NOTE: my system needed this
dir = "/usr/share/fonts/gnu-free";
break;
}
if (dir == NULL)
strcpy(font_path,font_tail);
else
sprintf(font_path,"%s/%s",dir,font_tail);
font = TTF_OpenFont(font_path, 24);
if (font != NULL)
break;
}
if (font == NULL) {
fprintf(stderr, "error: font not found\n");
exit(EXIT_FAILURE);
}
}
int
main(int argc, char **argv)
{
SDL_Event event;
SDL_Renderer *renderer;
SDL_Window *window;
char *font_path;
int quit;
switch (argc) {
case 1:
font_path = "FreeSans.ttf";
break;
case 2:
font_path = argv[1];
break;
default:
fprintf(stderr, "error: too many arguments\n");
exit(EXIT_FAILURE);
break;
}
genboard(brd);
prtboard(brd);
/* Inint TTF. */
SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_WIDTH, 0, &window,
&renderer);
fontinit(font_path);
#if 0
SDL_Rect rect1, rect2;
SDL_Texture *texture1, *texture2;
get_text_and_rect(renderer, 0, 0, "hello", font, &texture1, &rect1);
get_text_and_rect(renderer, 0, rect1.y + rect1.h, "world", font,
&texture2, &rect2);
#endif
quit = 0;
while (1) {
while (SDL_PollEvent(&event) == 1) {
if (event.type == SDL_QUIT)
quit = 1;
}
if (quit)
break;
// set background
#if 0
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
#else
SDL_SetRenderDrawColor(renderer,135,206,250,0);
#endif
SDL_RenderClear(renderer);
drawbox(renderer);
drawgrid(renderer);
drawtext(renderer);
/* Use TTF textures. */
#if 0
SDL_RenderCopy(renderer, texture1, NULL, &rect1);
SDL_RenderCopy(renderer, texture2, NULL, &rect2);
#endif
imgsave(renderer,0);
SDL_RenderPresent(renderer);
}
/* Deinit TTF. */
#if 0
SDL_DestroyTexture(texture1);
SDL_DestroyTexture(texture2);
#endif
TTF_Quit();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
Here is the text output of the program (Note that the program just generates a random test matrix that may or may not be a valid sudoku):
2 4 7 9 * 7 * 6 *
* 6 * * * * 9 * 1
7 1 * * * 3 * * 6
* * 6 * 7 * 5 7 *
* * 9 * 5 * * * *
* * 7 3 * * * 8 *
7 * 1 * * * 2 * 8
5 * 6 * 2 6 * * *
* 2 * * * * * * 3
Here is the image file that was generated. The program saved it to img000.ppm. I then did: convert img000.ppm img000.png [using ImageMagick's convert]
Related
I'm new to OpenGL and I am trying to get a mandelbrot set computed with OpenGL and GLFW.
I found the code here but freeglut is broken on my system and for some reason complains about no callback being set even though it clearly is being set. It does however flash one frame and then crash, in that frame I can see the mandelbrot set so I know the math is correct.
I figured this would be a good opportunity to learn more about OpenGL and GLFW, so I set to work making this happen.
After double checking everything, I can see that it definitely calculates the values then switches the buffers properly.
However, I think I'm missing two things:
A vertex which the texture can actually be applied to
EDIT: (from learnopengl.com) "Once glTexImage2D is called, the currently bound texture object now has the texture image attached to it.", so it can't be #2
not sure what's happening with the calculation but it looks like it's binding a texture named 'texture' but then calculating the values in a struct array which don't seem to be associated in any way. I bind the texture with tex (texture) and then send the struct array to glTexImage2D
If someone could just point me in the right direction or confirm my suspicions that would be awesome.
My code is here:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <pthread.h>
#include <GLFW/glfw3.h>
#include <GL/gl.h>
#define VAL 255
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
}rgb_t;
rgb_t **tex_array = 0;
rgb_t *image;
int gwin;
int width = 640;
int height = 480;
int tex_w, tex_h;
double scale = 1./256;
double cx = -.6, cy = 0;
int color_rotate = 0;
int saturation = 1;
int invert = 0;
int max_iter = 256;
int dump = 1;
GLFWwindow* window;
int global_iterator = 0;
int conversion_iterator_x = 0;
int conversion_iterator_y = 0;
GLFWwindow* init_glfw();
void set_texture(GLuint tex);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void render(GLuint tex);
void screen_dump();
void keypress(unsigned char key, int x, int y);
void hsv_to_rgb(int hue, int min, int max, rgb_t *p);
void calc_mandel(rgb_t* px);
void alloc_texture();
void set_texture();
void mouseclick(int button, int state, int x, int y);
void resize(int w, int h);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
int main(int c, char **v)
{
GLFWwindow* win = init_glfw();
glfwSetWindowPos(win, 1000, 500);
GLuint texture;
glGenTextures(1, &texture);
set_texture(texture);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(win))
{
render(texture);
/* Swap front and back buffers */
glfwSwapBuffers(win);
/* Poll for and process events */
glfwPollEvents();
if(glfwGetKey(win, GLFW_KEY_ESCAPE) == GLFW_PRESS){
glfwSetWindowShouldClose(win, GL_TRUE);
}
}
return 0;
}
void set_texture(GLuint tex)
{
printf("Allocating space\n");
alloc_texture();
printf("Calculating mandel... %d\n", global_iterator);
++global_iterator;
calc_mandel(image);
printf("mandel calculation complete\n");
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h,
0, GL_RGB, GL_UNSIGNED_BYTE, tex_array[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
printf("Rendering to screen...\n");
render(tex);
}
void alloc_texture()
{
int i;
int ow = tex_w;
int oh = tex_h;
for (tex_w = 1; tex_w < width; tex_w <<= 1);
for (tex_h = 1; tex_h < height; tex_h <<= 1);
if (tex_h != oh || tex_w != ow){
tex_array = realloc(tex_array, tex_h * tex_w * 3 + tex_h * sizeof(rgb_t*));
}
for (tex_array[0] = (rgb_t *)(tex_array + tex_h), i = 1; i < tex_h; i++){
tex_array[i] = tex_array[i - 1] + tex_w;
}
}
void render(GLuint tex)
{
double x = (double)width /tex_w,
y = (double)height/tex_h;
glClear(GL_COLOR_BUFFER_BIT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2i(0, 0);
glTexCoord2f(x, 0); glVertex2i(width, 0);
glTexCoord2f(x, y); glVertex2i(width, height);
glTexCoord2f(0, y); glVertex2i(0, height);
glEnd();
glFlush();
glFinish();
}
GLFWwindow* init_glfw()
{
/* Initialize the library */
if (!glfwInit()){
return NULL;
}
/*
* Configure window options here if you so desire
*
* i.e.
*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//the fourth parameter of glfwCreateWindow should be NULL for windowed mode and
//glfGetPrimaryMonitor() for full screen mode
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(width, height, "Mandelbrot", NULL, NULL);
if (!window)
{
glfwTerminate();
return NULL;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*
* Initialize glew here
*/
glewExperimental = GL_TRUE;
glewInit();
return window;
}
void calc_mandel(rgb_t* px)
{
int i, j, iter, min, max;
double x, y, zx, zy, zx2, zy2;
min = max_iter;
max = 0;
for (i = 0; i < height; i++) {
px = tex_array[i];
y = (i - height/2) * scale + cy;
for (j = 0; j < width; j++, px++) {
x = (j - width/2) * scale + cx;
iter = 0;
zx = hypot(x - .25, y);
if (x < zx - 2 * zx * zx + .25){
iter = max_iter;
}
if ((x + 1)*(x + 1) + y * y < 1/16){
iter = max_iter;
}
zx = zy = zx2 = zy2 = 0;
for (; iter < max_iter && zx2 + zy2 < 4; iter++) {
zy = 2 * zx * zy + y;
zx = zx2 - zy2 + x;
zx2 = zx * zx;
zy2 = zy * zy;
}
if (iter < min){
min = iter;
}
if (iter > max){
max = iter;
}
*(unsigned short *)px = iter;
}
}
for (i = 0; i < height; i++){
for (j = 0, px = tex_array[i]; j < width; j++, px++){
hsv_to_rgb(*(unsigned short*)px, min, max, px);
}
}
}
void hsv_to_rgb(int hue, int min, int max, rgb_t *p)
{
printf("Converting hsv to rbg... \n");
if (min == max){
max = min + 1;
}
if (invert){
hue = max - (hue - min);
}
if (!saturation) {
p->r = p->g = p->b = 255 * (max - hue) / (max - min);
printf("done! (!saturation)\n");
return;
}
double h = fmod(color_rotate + 1e-4 + 4.0 * (hue - min) / (max - min), 6);
double c = VAL * saturation;
double X = c * (1 - fabs(fmod(h, 2) - 1));
p->r = p->g = p->b = 0;
switch((int)h) {
case 0: p->r = c; p->g = X; break;
case 1: p->r = X; p->g = c; break;
case 2: p->g = c; p->b = X; break;
case 3: p->g = X; p->b = c; break;
case 4: p->r = X; p->b = c; break;
default:p->r = c; p->b = X; break;
}
printf("done! (sauration)\n");
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
glOrtho(0, width, 0, height, -1, 1);
//set_texture();
}
[1]: https://rosettacode.org/wiki/Mandelbrot_set#PPM_non_interactive
I am trying to compile an MPI program with mpicc. The compiler complains only that there is no reference to MPI_RECIVE and MPI_SEND, and ends the compile error. I have #include in the .c file.
Can someone tell me how I can fix this?
Here ist the Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <mpi.h>
#include "random.h"
#include "md5tool.h"
/* horizontal size of the configuration */
#define XSIZE 1024
/* "ADT" State and line of states (plus border) */
typedef char State;
typedef State Line[XSIZE + 2];
/* determine random integer between 0 and n-1 */
#define randInt(n) ((int)(nextRandomLEcuyer() * n))
/* random starting configuration */
static void initConfig(Line *buf, int lines){
int x, y;
initRandomLEcuyer(424243);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
buf[y][x] = randInt(100) >= 50;
}
}
}
/* annealing rule from ChoDro96 page 34
* the table is used to map the number of nonzero
* states in the neighborhood to the new state
*/
static State anneal[10] = {0, 0, 0, 0, 1, 0, 1, 1, 1, 1};
/* a: pointer to array; x,y: coordinates; result: n-th element of anneal,
where n is the number of neighbors */
#define transition(a, x, y) \
(anneal[(a)[(y)-1][(x)-1] + (a)[(y)][(x)-1] + (a)[(y)+1][(x)-1] +\
(a)[(y)-1][(x) ] + (a)[(y)][(x) ] + (a)[(y)+1][(x) ] +\
(a)[(y)-1][(x)+1] + (a)[(y)][(x)+1] + (a)[(y)+1][(x)+1]])
/* treat torus like boundary conditions */
static void boundary(Line *buf, int lines){
int x,y;
for (y = 0; y <= lines+1; y++) {
/* copy rightmost column to the buffer column 0 */
buf[y][0 ] = buf[y][XSIZE];
/* copy leftmost column to the buffer column XSIZE + 1 */
buf[y][1+1] = buf[y][1 ];
}
for (x = 0; x <= XSIZE+1; x++) {
/* copy bottommost row to buffer row 0 */
buf[0][x ] = buf[lines][x];
/* copy topmost row to buffer row lines + 1 */
buf[lines+1][x] = buf[1][x ];
}
}
/* make one simulation iteration with lines lines.
* old configuration is in from, new one is written to to.
*/
//umschreiben
/**
static void simulate(Line *from, Line *to, int lines){
boundary(from, lines);
for (y = 1; y <= lines; y++) {
for (x = 1; x <= XSIZE; x++) {
to[y][x ] = transition(from, x , y);
}
}
}
*/
/* --------------------- measurement ---------------------------------- */
int main(int argc, char** argv){
int lines, its;
int i;
Line *from, *to, *temp, *next;
char* hash;
assert(argc == 3);
lines = atoi(argv[1]);
its = atoi(argv[2]);
from = malloc((lines + 2) * sizeof(Line));
to = malloc((lines + 2) * sizeof(Line));
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
if(world_rank == 0){
int y;
next = malloc((lines + 2) * sizeof(Line));
initConfig(from, lines);
for (i = 0; i < its; i++) {
boundary(from, lines);
int z;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_SEND(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,0,MPI_COMM_WORLD);
}
}
MPI_Status status;
for(z = 0; z < world_size;z++){
if(z !=world_rank ){
MPI_RECIVE(next,(lines + 2) * sizeof(Line),MPI_CHARACTER,z,1,&status);
if(status.MPI_ERROR){
//TODO
MPI_Abort(MPI_COMM_WORLD,1);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
stpcpy(to[y*z],next[y*z]);
}
}
}
temp = from;
from = to;
to = temp;
}
hash = getMD5DigestStr(from[1], sizeof(Line) * (lines));
printf("hash: %s\n", hash);
free(next);
}else{
int x,y;
MPI_Status status;
for(i = 0; i < its; i++){
MPI_RECIVE(from,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,0,&status);
if(status.MPI_ERROR){
MPI_Abort(MPI_COMM_WORLD,2);
}
for (y = 1; y <= (lines%world_size+lines/world_size); y++) {
for (x = 1; x <= XSIZE; x++) {
to[y*world_rank][x ] = transition(from, x , y*world_rank);
}
}
MPI_SEND(to,(lines + 2) * sizeof(Line),MPI_CHARACTER,0,1,MPI_COMM_WORLD);
}
}
MPI_Finalize();
free(from);
free(to);
free(hash);
return 0;
}
This is a C a Sequence implementation which I wrote for the university as a homework assignment.
Are you talking about MPI_Send and MPI_Recv ?
Don't know about any MPI_SEND or MPI_RECIV function...
I think you just mispelled them.
BTW: here is a great tutorial about how to use them http://mpitutorial.com/tutorials/mpi-send-and-receive/
Here's the relevant code (in C):
uint8_t sort_array[SORT_ARRAY_LEN];
for (int i = 0; i < SORT_ARRAY_LEN; i++) {
sort_array[i] = rand() % 256;
}
// Every frame
int el1_i = rand() % SORT_ARRAY_LEN;
int el2_i = rand() % SORT_ARRAY_LEN;
uint8_t temp = sort_array[el1_i];
sort_array[el1_i] = sort_array[el2_i];
sort_array[el2_i] = temp;
When I run this for long enough, elements will seem to disappear over time until every element is zero. I can't figure out why this happens, but after a while of commenting out random things, I've discovered that changing
uint8_t sort_array[SORT_ARRAY_LEN];
to
uint8_t *sort_array = malloc(sizeof(u8) * SORT_ARRAY_LEN);
fixes the problem. Why on earth is this happening?
Here is the complete code:
#include <SDL2/SDL.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SORT_ARRAY_LEN 160
#define MAX_TICK_SAMPLES 100
void error_quit(char * message) {
fprintf(stderr, "%s SDL_Error:\n\t%s\n", message, SDL_GetError());
exit(1);
}
void draw_array(SDL_Surface * screen_surface,
uint8_t * sort_array, int sa_len)
{
int bar_width = SCREEN_WIDTH / sa_len;
for (int i = 0; i < sa_len; i++) {
int bar_height = (SCREEN_HEIGHT * sort_array[i]) / 256;
SDL_Surface * bar_surface = SDL_CreateRGBSurface(
0, bar_width, bar_height, 32, 0, 0, 0, 0);
SDL_FillRect(bar_surface, 0,
SDL_MapRGB(bar_surface->format, 255, 0, 0));
SDL_Rect bar_rect;
bar_rect.x = i * bar_width;
bar_rect.w = bar_width;
bar_rect.y = SCREEN_HEIGHT - bar_height;
bar_rect.h = bar_height;
SDL_BlitSurface(bar_surface, 0, screen_surface, &bar_rect);
SDL_FreeSurface(bar_surface);
}
}
int main() {
/* INITIALIZATION */
SDL_Window * window;
SDL_Surface * screen_surface;
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
error_quit("Trouble initializing.");
}
window = SDL_CreateWindow(
"Sorting Visualizer",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH, SCREEN_HEIGHT,
SDL_WINDOW_SHOWN
);
if (window == 0) {
error_quit("Trouble creating the window.");
}
screen_surface = SDL_GetWindowSurface(window);
if (screen_surface == 0) {
error_quit("Trouble getting window surface.");
}
srand(time(0));
uint8_t sort_array[SORT_ARRAY_LEN];
//uint8_t * sort_array = malloc(sizeof(uint8_t) * SORT_ARRAY_LEN);
for (int i = 0; i < SORT_ARRAY_LEN; i++) {
sort_array[i] = rand() % 256;
}
/* FRAMERATE SETUP */
int tick_index = 0;
int tick_sum = 0;
int tick_list[MAX_TICK_SAMPLES];
for (int i = 0; i < MAX_TICK_SAMPLES; i++) {
tick_list[i] = 0;
}
printf("[ ");
for (int i = 0; i < SORT_ARRAY_LEN; i++) {
printf("%d, ", sort_array[i]);
}
printf("]\n");
/* MAIN LOOP */
uint8_t running = 0xFF;
SDL_Event event;
while (running) {
int frame_start_time = SDL_GetTicks();
/* PROCESS EVENTS */
while (SDL_PollEvent(&event) != 0) {
if (event.type == SDL_QUIT) {
running = 0x00;
}
}
/* SORTING */
int el1_i = rand() % SORT_ARRAY_LEN;
int el2_i = rand() % SORT_ARRAY_LEN;
uint8_t temp = sort_array[el1_i];
sort_array[el1_i] = sort_array[el2_i];
sort_array[el2_i] = temp;
/* DRAWING */
SDL_FillRect(
screen_surface, 0,
SDL_MapRGB(screen_surface->format, 255, 255, 255)
);
draw_array(screen_surface, sort_array, SORT_ARRAY_LEN);
SDL_UpdateWindowSurface(window);
/* FRAMERATE */
int frame_time = SDL_GetTicks() - frame_start_time;
tick_sum -= tick_list[tick_index];
tick_sum += frame_time;
tick_list[tick_index] = frame_time;
if (tick_index++ == MAX_TICK_SAMPLES) {
tick_index = 0;
}
if (SDL_GetTicks() % 50 == 0) {
//printf("%f\n", (double)tick_sum / MAX_TICK_SAMPLES);
}
}
/* CLEANUP */
SDL_DestroyWindow(window);
SDL_Quit();
printf("[ ");
for (int i = 0; i < SORT_ARRAY_LEN; i++) {
printf("%d, ", sort_array[i]);
}
printf("]\n");
return 0;
}
The array in defined with automatic storage in the main function. Moving it to the heap should not have an effect. What you observe count be the side effect of a bug elsewhere in the code that overwrites the array with zero values...
Here it is:
if (tick_index++ == MAX_TICK_SAMPLES) {
tick_index = 0;
}
This test is off by one, it should be:
if (++tick_index == MAX_TICK_SAMPLES) {
tick_index = 0;
}
This error causes a buffer overfow every MAX_TICK_SAMPLES+1 runs, possibly storing a 0 into the first entry of the other array, which eventually gets moved randomly to another location in the array.
This is an awesome bug! The array contents are rotting away over time...
I want to read an text file Using C Language.Here's the file:-
You see there is some pattern in the text content on the file.
0 means nothing. 9 means black. so there is coloring scheme from 0 to 9.
I have to create a bitmap image of this and the color are according to the values in the pattern. You have to adjust it with the 0-256 color scheme.
And the final output for this is shown below
Now see the pattern in the content of the text file is opposite to the final output bitmap file (not necessary). The darkness of the colors in bitmap image is according to the values in the pattern of the text content.
Anyone will tell me how I achieve this in C language.
I am able to create a BMP file but not according to the pattern in text file.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char bitmap[1900];
// -- FILE HEADER -- //
// bitmap signature
bitmap[0] = 0x42;
bitmap[1] = 0x4d;
// file size
bitmap[2] = 58; // 40 + 14 + 12
bitmap[3] = 0;
bitmap[4] = 0;
bitmap[5] = 0;
int i=0;
// reserved field (in hex. 00 00 00 00)
for(i = 6; i < 10; i++) bitmap[i] = 0;
// offset of pixel data inside the image
for(i = 10; i < 14; i++) bitmap[i] = 0;
// -- BITMAP HEADER -- //
// header size
bitmap[14] = 40;
for(i = 15; i < 18; i++) bitmap[i] = 0;
// width of the image
bitmap[18] = 4;
for(i = 19; i < 22; i++) bitmap[i] = 0;
// height of the image
bitmap[22] = 1;
for(i = 23; i < 26; i++) bitmap[i] = 0;
// reserved field
bitmap[26] = 1;
bitmap[27] = 0;
// number of bits per pixel
bitmap[28] = 24; // 3 byte
bitmap[29] = 0;
// compression method (no compression here)
for(i = 30; i < 34; i++) bitmap[i] = 0;
// size of pixel data
bitmap[34] = 12; // 12 bits => 4 pixels
bitmap[35] = 0;
bitmap[36] = 0;
bitmap[37] = 0;
// horizontal resolution of the image - pixels per meter (2835)
bitmap[38] = 0;
bitmap[39] = 0;
bitmap[40] = 0b00110000;
bitmap[41] = 0b10110001;
// vertical resolution of the image - pixels per meter (2835)
bitmap[42] = 0;
bitmap[43] = 0;
bitmap[44] = 0b00110000;
bitmap[45] = 0b10110001;
// color pallette information
for(i = 46; i < 50; i++) bitmap[i] = 0;
// number of important colors
for(i = 50; i < 54; i++) bitmap[i] = 0;
// -- PIXEL DATA -- //
for(i = 54; i < 66; i++) bitmap[i] = 255;
FILE *file;
file = fopen("bitmap.bmp", "w+");
for(i = 0; i < 66; i++)
{
fputc(bitmap[i], file);
}
fclose(file);
return 0;
}
Here is a working code. I do not check some case of error (input file badly formatted, for example). I put some commentaries, though the code itself is not difficult to understand.
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <ctype.h>
#define BMP_ASSERT(condition, message) \
do { \
if (! (condition)) { \
fprintf(stderr, __FILE__ ":%d: %s: Assertion `" #condition \
"` failed.\n\t: %s\n", __LINE__, __func__, message); \
exit(EXIT_FAILURE); \
} \
} while (false)
#define BMP_COLORMAP_SIZE 10
////////////////////////////////////////////////////////////////////////////////
// STRUCTS
typedef struct __attribute__((__packed__))
bmp_color
{
uint8_t r,
g,
b;
uint8_t :8;
} bmp_color_t;
typedef struct __attribute__((__packed__))
bmp_header_infos
{
uint32_t const info_size;
uint32_t width;
uint32_t height;
uint16_t const planes;
uint16_t const bpp;
uint32_t const compression;
uint32_t img_size;
uint32_t const horz_resolution;
uint32_t const vert_resolution;
uint32_t const n_colors;
uint32_t const n_important_colors;
} bmp_header_infos_t;
typedef struct __attribute__((__packed__))
bmp_header
{
/* Header */
char const signature[2];
uint32_t file_size;
uint32_t const :32; // reserved
uint32_t const img_offset;
/* Infos */
bmp_header_infos_t infos;
/* Color map */
bmp_color_t colormap[BMP_COLORMAP_SIZE];
} bmp_header_t;
typedef struct bmp_file_datas
{
size_t width;
size_t height;
/* Bit map */
uint8_t *bitmap;
} bmp_file_datas_t;
////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/* Give a header with the right magic values */
bmp_header_t *
bmp_get_header(void)
{
static bmp_header_t _header = {
{'B', 'M'},
0u,
sizeof(_header),
{ // struct info
sizeof(_header.infos),
0u, 0u, // width, height
1u, // planes
8u, // bpp
0u, // no compression
0u, // img size
0u, 0u, // resolution
BMP_COLORMAP_SIZE,
BMP_COLORMAP_SIZE, // important colors
},
{{0u}}
};
bmp_header_t *header = malloc(sizeof(_header));
size_t i,
color;
assert(header != NULL);
memcpy(header, &_header, sizeof(*header));
// setting the scale of greys
for (i = 0 ; i < BMP_COLORMAP_SIZE ; ++i)
{
color = (i * 255) / BMP_COLORMAP_SIZE;
header->colormap[i] = (bmp_color_t){color, color, color};
}
return header;
}
/* Take all the file content and store it in a buffer */
char *
get_file_content(char const *filename)
{
FILE *file_handler = fopen(filename, "r");
size_t file_len;
char *buff;
BMP_ASSERT(file_handler != NULL, strerror(errno));
fseek(file_handler, 0, SEEK_END);
file_len = ftell(file_handler);
fseek(file_handler, 0, SEEK_SET);
buff = malloc(file_len + 1);
assert(buff != NULL);
fread(buff, file_len, 1, file_handler);
buff[file_len] = '\0';
fclose(file_handler);
return buff;
}
/* Get the greatest multiple of 4 that is >= size */
static inline size_t
multiple_of_four(size_t size)
{
while (size % 4)
++size;
return size;
}
/* Get the informations from buffer: size of line, number of lines */
void
get_file_infos(char *buff, bmp_header_t *header, bmp_file_datas_t *datas)
{
/* width & height */
header->infos.width = strchr(buff, '\n') - buff;
header->infos.height = strlen(buff) / (header->infos.width + 1);
// + 1 for the terminating '\n'
datas->width = multiple_of_four(header->infos.width);
datas->height = header->infos.height;
printf("File size: %u, %u\n", header->infos.width, header->infos.height);
/* image size & bitmap allocation */
header->infos.img_size = datas->width * datas->height;
datas->bitmap = malloc(header->infos.img_size * sizeof(*datas->bitmap));
assert(datas->bitmap != NULL);
header->file_size = header->img_offset + header->infos.img_size;
}
/* Take the informations from the buffer and store them in the bitmap */
void
write_bitmap(char *buff, bmp_file_datas_t *datas)
{
size_t ibuff,
iline = 0,
ibitmap = 0;
for (ibuff = 0 ; buff[ibuff] ; ++ibuff)
{
if (isdigit(buff[ibuff]))
{
datas->bitmap[ibitmap] = BMP_COLORMAP_SIZE - 1 - (buff[ibuff] - '0');
++ibitmap;
}
else if (buff[ibuff] == '\n')
{
++iline;
ibitmap = iline * datas->width;
}
}
}
/* Write the datas in the file: the header and the bitmap */
void
write_in_file(bmp_header_t *header,
bmp_file_datas_t *datas,
char const *filename)
{
FILE *file_handler = fopen(filename, "w");
BMP_ASSERT(file_handler != NULL, strerror(errno));
fwrite(header, sizeof(*header), 1, file_handler);
fwrite(datas->bitmap, header->infos.img_size, 1, file_handler);
fclose(file_handler);
}
int main(int argc, char **argv)
{
char *buff;
bmp_header_t *header;
bmp_file_datas_t datas;
if (argc != 3)
{
fprintf(stderr, "Usage: %s <input filename> <output filename>\n",
argv[0]);
return EXIT_FAILURE;
}
buff = get_file_content(argv[1]);
header = bmp_get_header();
get_file_infos(buff, header, &datas);
write_bitmap(buff, &datas);
write_in_file(header, &datas, argv[2]);
free(buff), free(header), free(datas.bitmap);
return EXIT_SUCCESS;
}
A crude method to achieve the required functionality would be: (Not really C, but then it is your homework not mine)
WIDTH = 0, HEIGHT = 0
if(LINE=READ_LINE(fin))
WIDTH = strlen(LINE)
++HEIGHT
else
ERROR!!!
PUSH(LINE)
while(LINE=READ_LINE(fin))
if(WIDTH != strlen(LINE))
ERROR!!!
else
++HEIGHT
PUSH(LINE)
WRITE_BMP_HEADER(WIDTH, HEIGHT)
for(h = 0; h < HEIGHT; ++h)
LINE = POP()
for(w = 0; w < WIDTH; ++w)
COLOR = (LINE[w] - '0') * 255 / 9;
WRITE_BMP_COLOR(COLOR)
WRITE_BMP_PADDING(W)
I have the following code from a class:
#include <stdio.h>
#include <math.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
void destroy(void) {
gtk_main_quit();
}
static void
put_pixel (GdkPixbuf *pixbuf, int x, int y, guchar red, guchar green, guchar blue, guchar alpha);
typedef
struct complex{
double re;
double im;
} Complex;
int main(int argc, char** argv ){
gtk_init (&argc, &argv);
gint width = 256;
gint height = 256;
GdkColorspace cs = GDK_COLORSPACE_RGB;
GdkPixbuf* pixbuf = gdk_pixbuf_new( cs, 1, 8, width, height);
if (pixbuf == NULL ) {
fprintf( stderr, "Not able to create gdkimage object\n");
return -1;
}
/*
* Lower left and upper right corners of complex plane
*/
const Complex ll = {-2.5, -1.0};
const Complex ur = { 1.0, 1.0};
/*
* Resolution: Nx by Ny pixels in complex plane
*/
const int Nx = 256;
const int Ny = 256;
const double dx = (ur.re - ll.re)/(double)(Nx-1);
const double dy = (ur.im - ll.im)/(double)(Ny-1);
Complex z[Nx][Ny];
Complex c[Nx][Ny];
unsigned int pixel[Nx][Ny];
/*
* Number of iterations
*/
const int number_of_iterations = 1024;
/*
* Once the real or imaginary parts go beyond the max
* values, they have "escaped"
*/
const double Max = 4.0;
/*
* Initialize z and c
*/
printf("Initializing ... \n");
int i=0;
for (i=0; i<Nx; i++) {
int j=0;
for (j=0; j<Ny; j++) {
z[i][j].re = z[i][j].im = 0.;
c[i][j].re = ll.re + i * dx;
c[i][j].im = ll.im + j * dy;
pixel[i][j] = 1; // close to black
}
}
/*
* Iterate for number of iterations
*/
printf("Starting iterations ... \n");
int k=0;
unsigned int color;
for(k=0; k<number_of_iterations; k++){
/*
* Figure out the color for this iteration
*/
color = (unsigned int) ((k * 255 * 256 * 256 ) / number_of_iterations);
for (i=0; i<Nx; i++) {
int j=0;
for (j=0; j<Ny; j++) {
/*
* if pixel value is 0, no need to compute anything.
*/
Complex t = z[i][j];
/*
* check magnitude
*/
if (t.re * t.re + t.im*t.im < Max) {
/*
* Compute z_n+1 = z_n * z_n + c
*/
Complex znp1;
znp1.re = t.re * t.re - t.im * t.im + c[i][j].re;
znp1.im = 2.0 * t.re * t.im + c[i][j].im;
z[i][j] = znp1;
pixel[i][j] = color;
} else {
pixel[i][j] = 0; // black
}
//put draw part here
guchar red = pixel[i][j] & 0xff;
guchar green = pixel[i][j] & 0xff00;
guchar blue = pixel[i][j] & 0xff0000;
guchar alpha = 255; //opacity
put_pixel( pixbuf, i, j, red, green, blue, alpha);
}
}
}
printf("Done with iterations \n");
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget* image = gtk_image_new();
gtk_image_set_from_pixbuf((GtkImage*) image, pixbuf);
/*
* The next 7 lines of code are NOW used to end the program if x button
*/
GdkScreen* screen = gtk_widget_get_screen (GTK_WIDGET (window));
GdkVisual* visual = gdk_screen_get_rgba_visual (screen);
if (visual == NULL)
visual = gdk_screen_get_system_visual (screen);
g_signal_connect(G_OBJECT (window), "destroy",
G_CALLBACK (destroy), NULL);
gtk_container_add(GTK_CONTAINER (window), image);
gtk_widget_show_all(window);
gtk_widget_queue_draw(image);
gtk_main();
return 0;
}//end of main
/*
* put_pixel - from: https://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-The-GdkPixbuf-Structure.html
*/
static void
put_pixel (GdkPixbuf *pixbuf,
int x, int y,
guchar red, guchar green,
guchar blue, guchar alpha) {
int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
g_assert (n_channels == 4);
int width = gdk_pixbuf_get_width (pixbuf);
int height = gdk_pixbuf_get_height (pixbuf);
g_assert (x >= 0 && x < width);
g_assert (y >= 0 && y < height);
int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
guchar* pixels = gdk_pixbuf_get_pixels (pixbuf);
guchar* p = pixels + y * rowstride + x * n_channels;
p[0] = red;
p[1] = green;
p[2] = blue;
p[3] = alpha;
}
I am trying to have the color of the shape multi-colored. Currently it only outputs with 1 color.
I think it may be something to do with the iterations. And the color not changing from iteration to iteration.
Any help would be great.