| ppm-lib/ppm.c - Den tilsvarende fil ppm.c - en mulig implementation. | Lektion 6 - slide 21 : 21 Program 4 |
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "ppm.h"
/* IT IS NOT NECESSARY TO UNDERSTAND THE DETAILS OF THIS PROGRAM.
IT IS SUFFICIENT TO UNDERSTAND ppm.h */
unsigned int **alloc_image(int m, int n){
int i;
unsigned int **dpp = (unsigned int **)malloc(m * sizeof(unsigned int *));
if(dpp == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
for(i = 0; i < m; i++) {
if((dpp[i] = (unsigned int *)malloc(n * sizeof(unsigned int))) == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
}
return dpp;
}
void init_image(unsigned int **image, unsigned int width, unsigned int height,
unsigned int red, unsigned int green, unsigned int blue){
int x,y ;
for(y = 0; y < height; y++)
for (x = 0; x < width ; x++){
image[x][y] = (red << 16) | (green << 8) | blue;
}
}
ppm *make_image(unsigned int width, unsigned int height, pixel background_pixel){
/* Allocate the struct: */
ppm *the_image = malloc(sizeof(ppm));
/* Initialize the fields: */
the_image->width = width;
the_image->height = height;
the_image->pixels = alloc_image(width,height);
/* Initialize all pixels of image: */
init_image(the_image->pixels, width, height,
get_red(background_pixel),
get_green(background_pixel),
get_blue(background_pixel));
/* Return the pointer to the image: */
return the_image;
}
void set_pixel(ppm *image, unsigned int x, unsigned int y, pixel p){
unsigned int **pixel_table = image->pixels;
if (x >= 0 && x < image->width && y >= 0 && y < image->height)
pixel_table[x][y] = (unsigned int)p;
}
pixel get_pixel(ppm *image, unsigned int x, unsigned int y){
unsigned int **pixel_table = image->pixels;
return (pixel)(pixel_table[x][y]);
}
/* Return the width of the image */
unsigned int image_width(ppm *img){
return img->width;
}
/* Return the height of the image */
unsigned int image_height(ppm *img){
return img->height;
}
void write_image(ppm *image, char *file_name){
FILE *image_file;
unsigned int **pixel_table = image->pixels;
unsigned int r, g, b;
int x, y;
char width_height_str[50];
image_file = fopen(file_name, "wb");
/* Write PPM header: */
fputs("P6\n", image_file);
sprintf(width_height_str, "%d %d\n", image->width, image->height);
fputs(width_height_str, image_file);
fputs("255\n", image_file);
/* Write pixels: */
for(y = 0; y < image->height; y++)
for (x = 0; x < image->width; x++){
r = (pixel_table[x][y] >> 16) & 0xff;
g = (pixel_table[x][y] >> 8) & 0xff;
b = pixel_table[x][y] & 0xff;
fputc(r, image_file); fputc(g, image_file); fputc(b, image_file);
}
fclose(image_file);
}
int blank_char(int ch){
return (ch == 32 || ch == 10 || ch == 12);
}
ppm *read_image(char *file_name){
ppm *the_image = malloc(sizeof(ppm)); /* Allocate the ppm struct: */
FILE *image_file;
unsigned int **image;
int ch, ch1, ch2, red, green, blue,
width, height, pixel_depth, x, y;
image_file = fopen(file_name, "rb");
/* Get two first chars - expected 'P6': */
ch1 = fgetc(image_file); ch2 = fgetc(image_file);
if (ch1 == 'P' && ch2 == '6'){
fscanf(image_file, " %d", &width); fscanf(image_file, " %d", &height);
fscanf(image_file, " %d", &pixel_depth);
if (pixel_depth == 255){
the_image->width = width;
the_image->height = height;
the_image->pixels = alloc_image(width,height);
image = the_image->pixels;
/* Read blank stuff before image: */
while (blank_char(ch = fgetc(image_file)));
ungetc(ch, image_file);
/* Read the image bytes */
for(y = 0; y < height; y++)
for (x = 0; x < width ; x++){
red = fgetc(image_file); green = fgetc(image_file); blue = fgetc(image_file);
image[x][y] = (red << 16) | (green << 8) | blue;
}
return the_image;
}
else {
printf("Unsupported pixel depth. Bye.");
exit(-1);
}
}
else {
printf("The image file does not seem to be PPM, P6 file. Bye.");
exit(-1);
}
}
void release_image(ppm *image){
int i;
for(i = 0; i <= image->width; i++)
free(image->pixels[i]);
free(image->pixels);
image->pixels = NULL;
image->width = 0;
image->height = 0;
}