Code:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef enum {NO, YES} Bool;
typedef struct GS8Pixel {
int level;
} GS8Pixel;
typedef struct GS8Image {
int width, height;
GS8Pixel *data;
} GS8Image;
void createGS8Image(GS8Image **image, int width, int height);
void freeGS8Image(GS8Image **image);
GS8Pixel getPixelOfGS8Image(GS8Image *image, int x, int y);
void setPixelOfGS8Image(GS8Image *image, int x, int y, int level);
int getP3StringSizeOfGS8Image(GS8Image *image);
void GS8ImageToP3String(char *str, GS8Image *image);
Bool GS8ImageToP3File(char *file_path, GS8Image *image);
void scaleGS8ImageWithNearestNeighbourInterpolation(GS8Image **new_image, GS8Image *old_image, float scale);
void createGS8Image(GS8Image **image, int width, int height)
{
int i;
*image = malloc(sizeof(GS8Image));
(*image)->data = malloc(sizeof(GS8Pixel)*width*height);
// if ((*image)->data == NULL) {
// fprintf(stderr, "out of memory!\n");
// }
for(i = 0; i < width*height; ++i)
{
((*image)->data)[i].level = 0;
}
(*image)->width = width;
(*image)->height = height;
}
void freeGS8Image(GS8Image **image)
{
free((*image)->data);
free((*image));
*image = NULL;
}
GS8Pixel getPixelOfGS8Image(GS8Image *image, int x, int y)
{
return image->data[y*image->width+x];
}
void setPixelOfGS8Image(GS8Image *image, int x, int y, int level)
{
image->data[y*image->width+x].level = level;
}
void scaleGS8ImageWithNearestNeighbourInterpolation(GS8Image **new_image, GS8Image *old_image, float scale)
{
int new_image_width, new_image_height, x, y, tmp_x, tmp_y;
new_image_width = (int) (scale * old_image->width);
new_image_height = (int) (scale * old_image->height);
createGS8Image(new_image, new_image_width, new_image_height);
for(y = 0; y < new_image_height; ++y)
{
for(x = 0; x < new_image_width; ++x)
{
tmp_x = (int) (x / scale + 0.5);
tmp_y = (int) (y / scale + 0.5);
getPixelOfGS8Image(*new_image, x, y);
}
}
}
Bool GS8ImageToP3File(char *file_path, GS8Image *image)
{
FILE *fp;
char str[getP3StringSizeOfGS8Image(image)];
GS8ImageToP3String(str, image);
if((fp = fopen(file_path, "w"))==NULL) {
printf("unable to open file");
return NO;
}
fputs(str, fp);
fclose(fp);
return YES;
}
void GS8ImageToP3String(char *str, GS8Image *image)
{
int i, tmp_level;
char tmp[70], *str_end;
strcpy(str, "P3\n");
sprintf(tmp, "%d %d\n", image->width, image->height);
strcat(str, tmp);
strcat(str, "255\n");
str_end = str + strlen(str);
for(i = 0; i < image->width*image->height; ++i)
{
tmp_level = (image->data)[i].level;
sprintf(tmp, "%3d %3d %3d ", tmp_level, tmp_level, tmp_level);
strcpy(str_end, tmp);
str_end += 13;
if ( i%10 ==9 ) {
strcpy(str_end, "\n");
str_end += 1;
}
}
}
int getP3StringSizeOfGS8Image(GS8Image *image)
{
char tmp[70];
sprintf(tmp, "%d %d\n", image->width, image->height);
return 1 + strlen(tmp) + 3 + 4 + 13*image->width*image->width + (image->width*image->width/10);
}
int main (int argc, char const *argv[])
{
GS8Image *a, *b, *c;
createGS8Image(&a, 10, 10);
GS8ImageToP3File("test.ppm", a);
printf("10x10 done.\n");
createGS8Image(&b, 1, 1);
GS8ImageToP3File("test.ppm", b);
printf("1x1 done.\n");
createGS8Image(&c, 1, 10);
GS8ImageToP3File("test.ppm", c);
printf("1x10 done.\n");
return 0;
}
Resolutions that work -> 1x1, 10x10, 512x512