- image.c: 基本的な画像処理(読み込み,書き出し,フィルタ適用)
- filter.c: 簡単なフィルタ
ただし,フィルタそのものは filter.c で定義されている.
- uniform.c: 平滑化フィルタ
- gaussian.c: ガウシアンフィルタ
- sharp.c: 先鋭化フィルタ
- sepia.c: セピア調に変換
#include <stdio.h> | |
#include "image.h" | |
#include "filter.h" | |
Image *uniform(Image * const image){ | |
Filter * const filter = create_filter(3, 3); | |
for(int i = 0; i < 9; ++i){ | |
(filter->r)[i] = 1.0 / 9.0; | |
(filter->g)[i] = 1.0 / 9.0; | |
(filter->b)[i] = 1.0 / 9.0; | |
} | |
apply_filter(image, filter); | |
delete_filter(filter); | |
return image; | |
} | |
Image *gaussian(Image * const image){ | |
Filter * const filter = create_filter(3, 3); | |
int i = 0; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 1.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 2.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 1.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 2.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 4.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 2.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 1.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 2.0 / 16.0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 1.0 / 16.0; | |
apply_filter(image, filter); | |
delete_filter(filter); | |
return image; | |
} | |
Image *sharp(Image * const image){ | |
Filter * const filter = create_filter(3, 3); | |
int i = 0; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 5; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 0; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 0; | |
apply_filter2(image, filter); | |
delete_filter(filter); | |
return image; | |
} | |
Image *sharp2(Image * const image){ | |
Filter * const filter = create_filter(3, 3); | |
int i = 0; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = 9; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
++i; | |
(filter->r)[i] = (filter->g)[i] = (filter->b)[i] = -1; | |
apply_filter2(image, filter); | |
delete_filter(filter); | |
return image; | |
} |
#ifndef _FILTER_H_ | |
#define _FILTER_H_ | |
Image *uniform(Image * const image); | |
Image *gaussian(Image * const image); | |
Image *sharp(Image * const image); | |
Image *sharp2(Image * const image); | |
#endif |
#include <stdio.h> | |
#include "image.h" | |
#include "filter.h" | |
int main(){ | |
Image *image; | |
FILE *fin, *fout; | |
// Read an image. | |
fin = fopen("scene.ppm", "r"); | |
if(fin == NULL){ | |
printf("File not found.\n"); | |
return 1; | |
} | |
image = read_image(fin); | |
fclose(fin); | |
// Do something. | |
gaussian(image); | |
// Write an image. | |
fout = fopen("gaussian.ppm", "wb"); | |
write_image(fout, image); | |
delete_image(image); | |
fclose(fout); | |
return 0; | |
} |
#include "image.h" | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
uchar _round(int v){ | |
if(v < 0){ | |
return 0; | |
}else if(v > 255){ | |
return 255; | |
} | |
return v; | |
} | |
int min(const int a, const int b){ | |
if(a < b){ | |
return a; | |
}else{ | |
return b; | |
} | |
} | |
int max(const int a, const int b){ | |
if(a > b){ | |
return a; | |
}else{ | |
return b; | |
} | |
} | |
Image *create_image(const int width, const int height){ | |
const int size = width * height; | |
Image * const res = malloc(sizeof(Image)); | |
res->width = width; | |
res->height = height; | |
res->r = malloc(sizeof(uchar) * size); | |
res->g = malloc(sizeof(uchar) * size); | |
res->b = malloc(sizeof(uchar) * size); | |
return res; | |
} | |
void delete_image(Image * const image){ | |
free(image->r); | |
free(image->g); | |
free(image->b); | |
free(image); | |
} | |
Image *copy_image(const Image * const image){ | |
Image * const res = create_image(image->width, image->height); | |
const int size = image->width * image->height; | |
memcpy(res->r, image->r, sizeof(uchar) * size); | |
memcpy(res->g, image->g, sizeof(uchar) * size); | |
memcpy(res->b, image->b, sizeof(uchar) * size); | |
return res; | |
} | |
Filter *create_filter(const int width, const int height){ | |
const int size = width * height; | |
Filter * const res = malloc(sizeof(Filter)); | |
res->width = width; | |
res->height = height; | |
res->r = malloc(sizeof(float) * size); | |
res->g = malloc(sizeof(float) * size); | |
res->b = malloc(sizeof(float) * size); | |
return res; | |
} | |
void delete_filter(Filter * const filter){ | |
free(filter->r); | |
free(filter->g); | |
free(filter->b); | |
free(filter); | |
} | |
Image *apply_filter(Image * const image, const Filter * const filter){ | |
Image * const copy = copy_image(image); | |
for(int i = 0; i < image->height; ++i){ | |
for(int j = 0; j < image->width; ++j){ | |
int new_r = 0, new_g = 0, new_b = 0; | |
for(int u = 0; u < filter->height; ++u){ | |
for(int v = 0; v < filter->width; ++v){ | |
const int row = i + u - filter->height/2; | |
const int col = j + v - filter->width/2; | |
if(row >= 0 && row < image->height && col >= 0 && col < image->width){ | |
new_r += *(copy->r + row * image->width + col) * *(filter->r + u * filter->width + v); | |
new_g += *(copy->g + row * image->width + col) * *(filter->g + u * filter->width + v); | |
new_b += *(copy->b + row * image->width + col) * *(filter->b + u * filter->width + v); | |
} | |
} | |
} | |
*(image->r + i * image->width + j) = _round(new_r); | |
*(image->g + i * image->width + j) = _round(new_g); | |
*(image->b + i * image->width + j) = _round(new_b); | |
} | |
} | |
delete_image(copy); | |
return image; | |
} | |
Image *apply_filter2(Image * const image, const Filter * const filter){ | |
Filter * const raw = create_filter(image->width, image->height); | |
int low = 0, high = 255; | |
for(int i = 0; i < image->height; ++i){ | |
for(int j = 0; j < image->width; ++j){ | |
int new_r = 0, new_g = 0, new_b = 0; | |
for(int u = 0; u < filter->height; ++u){ | |
for(int v = 0; v < filter->width; ++v){ | |
const int row = i + u - filter->height/2; | |
const int col = j + v - filter->width/2; | |
if(row >= 0 && row < image->height && col >= 0 && col < image->width){ | |
new_r += *(image->r + row * image->width + col) * *(filter->r + u * filter->width + v); | |
new_g += *(image->g + row * image->width + col) * *(filter->g + u * filter->width + v); | |
new_b += *(image->b + row * image->width + col) * *(filter->b + u * filter->width + v); | |
} | |
} | |
} | |
*(raw->r + i * raw->width + j) = new_r; | |
*(raw->g + i * raw->width + j) = new_g; | |
*(raw->b + i * raw->width + j) = new_b; | |
low = min(low, min(new_r, min(new_g, new_b))); | |
high = max(high, max(new_r, max(new_g, new_g))); | |
} | |
} | |
// printf("%d %d", low, high); | |
for(int i = 0; i < image->height; ++i){ | |
for(int j = 0; j < image->width; ++j){ | |
*(image->r + i * image->width + j) = _round((*(raw->r + i * raw->width + j) - low) / (float)(high - low) * 255); | |
*(image->g + i * image->width + j) = _round((*(raw->g + i * raw->width + j) - low) / (float)(high - low) * 255); | |
*(image->b + i * image->width + j) = _round((*(raw->b + i * raw->width + j) - low) / (float)(high - low) * 255); | |
} | |
} | |
delete_filter(raw); | |
return image; | |
} | |
/* Read an image from a given file pointer. | |
*/ | |
Image *read_image(FILE * const fp){ | |
char buf[BUFFER]; | |
int width, height; | |
Image *res; | |
// Ignore 1st line. | |
fgets(buf, BUFFER, fp); | |
// Ignore comments. | |
fgets(buf, BUFFER, fp); | |
while(buf[0] == '#'){ | |
fgets(buf, BUFFER, fp); | |
} | |
// Read width and height. | |
sscanf(buf, "%d %d", &width, &height); | |
fgets(buf, BUFFER, fp); | |
res = create_image(width, height); | |
for(int i = 0; i < width * height; ++i){ | |
fread(res->r + i, 1, 1, fp); | |
fread(res->g + i, 1, 1, fp); | |
fread(res->b + i, 1, 1, fp); | |
} | |
return res; | |
} | |
void write_image(FILE * const fp, const Image * const image){ | |
fprintf(fp, "P6\n"); | |
fprintf(fp, "%d %d\n", image->width, image->height); | |
fprintf(fp, "255\n"); | |
for(int i = 0; i < image->height * image->width; ++i){ | |
fwrite(image->r + i, 1, 1, fp); | |
fwrite(image->g + i, 1, 1, fp); | |
fwrite(image->b + i, 1, 1, fp); | |
} | |
} | |
Image *gray(Image * const image){ | |
for(int i = 0; i < image->height * image->width; ++i){ | |
float n = *(image->r + i) * 0.298912 + *(image->g + i) * 0.586611 + *(image->b + i) * 0.114478; | |
*(image->r + i) = *(image->g + i) = *(image->b + i) = _round(n); | |
} | |
return image; | |
} | |
Image *sepia(Image * const image){ | |
for(int i = 0; i < image->height * image->width; ++i){ | |
*(image->r + i) = _round(*(image->r + i) / 255.0 * 240.0); | |
*(image->g + i) = _round(*(image->g + i) / 255.0 * 200.0); | |
*(image->b + i) = _round(*(image->b + i) / 255.0 * 145.0); | |
} | |
return image; | |
} |
#ifndef _IMAGE_H_ | |
#define _IMAGE_H_ | |
#include <stdio.h> | |
#define WIDTH 640 | |
#define HEIGHT 480 | |
#define BUFFER 256 | |
typedef unsigned char uchar; | |
typedef struct { | |
int width; | |
int height; | |
uchar *r; | |
uchar *g; | |
uchar *b; | |
} Image; | |
typedef struct { | |
int width; | |
int height; | |
float *r; | |
float *g; | |
float *b; | |
} Filter; | |
Image *create_image(const int width, const int height); | |
void delete_image(Image * const image); | |
Image *copy_image(const Image * const image); | |
Filter *create_filter(const int width, const int height); | |
void delete_filter(Filter * const filter); | |
Image *apply_filter(Image * const image, const Filter * const filter); | |
Image *apply_filter2(Image * const image, const Filter * const filter); | |
Image *read_image(FILE * const fp); | |
void write_image(FILE * const fp, const Image * const image); | |
Image *gray(Image * const image); | |
Image *sepia(Image * const image); | |
#endif |
#include <stdio.h> | |
#include "image.h" | |
#include "filter.h" | |
int main(){ | |
Image *image; | |
FILE *fin, *fout; | |
// Read an image. | |
fin = fopen("scene.ppm", "r"); | |
if(fin == NULL){ | |
printf("File not found.\n"); | |
return 1; | |
} | |
image = read_image(fin); | |
fclose(fin); | |
// Do something. | |
sepia(image); | |
// Write an image. | |
fout = fopen("sepia.ppm", "wb"); | |
write_image(fout, image); | |
delete_image(image); | |
fclose(fout); | |
return 0; | |
} |
#include <stdio.h> | |
#include "image.h" | |
#include "filter.h" | |
int main(){ | |
Image *image; | |
FILE *fin, *fout; | |
// Read an image. | |
fin = fopen("scene.ppm", "r"); | |
if(fin == NULL){ | |
printf("File not found.\n"); | |
return 1; | |
} | |
image = read_image(fin); | |
fclose(fin); | |
// Do something. | |
sharp(image); | |
// Write an image. | |
fout = fopen("sharp.ppm", "wb"); | |
write_image(fout, image); | |
delete_image(image); | |
fclose(fout); | |
return 0; | |
} |
#include <stdio.h> | |
#include "image.h" | |
#include "filter.h" | |
int main(){ | |
Image *image; | |
FILE *fin, *fout; | |
// Read an image. | |
fin = fopen("scene.ppm", "r"); | |
if(fin == NULL){ | |
printf("File not found.\n"); | |
return 1; | |
} | |
image = read_image(fin); | |
fclose(fin); | |
// Do something. | |
sharp2(image); | |
// Write an image. | |
fout = fopen("sharp2.ppm", "wb"); | |
write_image(fout, image); | |
delete_image(image); | |
fclose(fout); | |
return 0; | |
} |
#include <stdio.h> | |
#include "image.h" | |
#include "filter.h" | |
int main(){ | |
Image *image; | |
FILE *fin, *fout; | |
// Read an image. | |
fin = fopen("scene.ppm", "r"); | |
if(fin == NULL){ | |
printf("File not found.\n"); | |
return 1; | |
} | |
image = read_image(fin); | |
fclose(fin); | |
// Do something. | |
uniform(image); | |
// Write an image. | |
fout = fopen("uniform.ppm", "wb"); | |
write_image(fout, image); | |
delete_image(image); | |
fclose(fout); | |
return 0; | |
} |