Linuxc语言用标准io给一个图片变成马赛克
时间: 2023-06-17 11:03:04 浏览: 184
要将一个图片变成马赛克,一种常见的方法是将原始图片划分成一个个小的块,然后将每个小块用相同的颜色填充,以达到马赛克的效果。下面是一个使用标准IO的C语言程序,可以将PNG图片转换为马赛克图像:
```c
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#define BLOCK_SIZE 10
void process_file(png_structp png_ptr, png_infop info_ptr) {
png_bytep *row_pointers;
int row, col;
// 读取图片数据
png_read_image(png_ptr, row_pointers);
// 获取图片的宽度和高度
int width = png_get_image_width(png_ptr, info_ptr);
int height = png_get_image_height(png_ptr, info_ptr);
// 遍历所有块
for (row = 0; row < height; row += BLOCK_SIZE) {
for (col = 0; col < width; col += BLOCK_SIZE) {
// 计算当前块的颜色
int r = 0, g = 0, b = 0;
int block_rows = BLOCK_SIZE;
int block_cols = BLOCK_SIZE;
if (row + BLOCK_SIZE > height) {
block_rows = height - row;
}
if (col + BLOCK_SIZE > width) {
block_cols = width - col;
}
int block_size = block_rows * block_cols;
png_bytep row_ptr;
for (int i = 0; i < block_rows; i++) {
row_ptr = row_pointers[row + i];
for (int j = 0; j < block_cols; j++) {
png_bytep pixel_ptr = &(row_ptr[(col + j) * 3]);
r += pixel_ptr[0];
g += pixel_ptr[1];
b += pixel_ptr[2];
}
}
r /= block_size;
g /= block_size;
b /= block_size;
// 用当前块的颜色填充块内所有像素
for (int i = 0; i < block_rows; i++) {
row_ptr = row_pointers[row + i];
for (int j = 0; j < block_cols; j++) {
png_bytep pixel_ptr = &(row_ptr[(col + j) * 3]);
pixel_ptr[0] = r;
pixel_ptr[1] = g;
pixel_ptr[2] = b;
}
}
}
}
// 写入输出文件
png_write_image(png_ptr, row_pointers);
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <input_file> <output_file>\n", argv[0]);
exit(1);
}
FILE *fp = fopen(argv[1], "rb");
if (!fp) {
fprintf(stderr, "Error: could not open file %s\n", argv[1]);
exit(1);
}
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fprintf(stderr, "Error: could not create png read struct\n");
exit(1);
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
fprintf(stderr, "Error: could not create png info struct\n");
exit(1);
}
if (setjmp(png_jmpbuf(png_ptr))) {
fprintf(stderr, "Error: an error occurred while reading the PNG file %s\n", argv[1]);
exit(1);
}
png_init_io(png_ptr, fp);
png_read_info(png_ptr, info_ptr);
if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB) {
fprintf(stderr, "Error: input file %s is not an RGB PNG image\n", argv[1]);
exit(1);
}
FILE *out_fp = fopen(argv[2], "wb");
if (!out_fp) {
fprintf(stderr, "Error: could not open output file %s\n", argv[2]);
exit(1);
}
png_structp out_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!out_png_ptr) {
fprintf(stderr, "Error: could not create png write struct\n");
exit(1);
}
png_infop out_info_ptr = png_create_info_struct(out_png_ptr);
if (!out_info_ptr) {
fprintf(stderr, "Error: could not create png info struct\n");
exit(1);
}
if (setjmp(png_jmpbuf(out_png_ptr))) {
fprintf(stderr, "Error: an error occurred while writing the PNG file %s\n", argv[2]);
exit(1);
}
png_init_io(out_png_ptr, out_fp);
png_set_IHDR(out_png_ptr, out_info_ptr, png_get_image_width(png_ptr, info_ptr),
png_get_image_height(png_ptr, info_ptr), 8, PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info(out_png_ptr, out_info_ptr);
// 处理图片
process_file(png_ptr, info_ptr);
png_write_end(out_png_ptr, NULL);
fclose(out_fp);
png_destroy_write_struct(&out_png_ptr, &out_info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
return 0;
}
```
使用方法:`./mosaic input.png output.png`,其中`input.png`是原始图片,`output.png`是转换后的马赛克图片。`BLOCK_SIZE`宏定义可以控制每个小块的大小,越大则马赛克效果越明显。
阅读全文