用c语言写一个基于游程编码算法的图片压缩
时间: 2024-02-20 19:57:59 浏览: 108
游程编码C语言
4星 · 用户满意度95%
好的,以下是基于游程编码算法的图片压缩的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_RLEN 255
// 定义游程编码结构体
struct rle {
int len;
int val;
};
// 读取图片像素矩阵
void readPixels(unsigned char *pixels, int width, int height, FILE *f)
{
int count = 0;
while (count < width * height) {
int c = fgetc(f);
if (c == EOF) {
break;
}
pixels[count++] = (unsigned char)c;
}
}
// 游程编码
int rle_encode(unsigned char *in, int len, struct rle **out)
{
*out = malloc(sizeof(struct rle) * len);
if (*out == NULL) {
return -1;
}
int count = 0, k = 0;
for (int i = 0; i < len; i++) {
(*out)[k].val = in[i];
count = 1;
while (i < len - 1 && in[i] == in[i+1] && count < MAX_RLEN) {
count++;
i++;
}
(*out)[k].len = count;
k++;
}
return k;
}
// 游程解码
void rle_decode(struct rle *in, int len, unsigned char *out)
{
int count = 0;
for (int i = 0; i < len; i++) {
for (int j = 0; j < in[i].len; j++) {
out[count++] = (unsigned char)in[i].val;
}
}
}
// 压缩图片
void compressImage(unsigned char *pixels, int width, int height, char *filename)
{
FILE *f = fopen(filename, "wb");
if (f == NULL) {
printf("Error: could not open file for writing\n");
return;
}
struct rle *rle_pixels;
int rle_len = rle_encode(pixels, width * height, &rle_pixels);
fwrite(&width, sizeof(int), 1, f);
fwrite(&height, sizeof(int), 1, f);
fwrite(rle_pixels, sizeof(struct rle), rle_len, f);
fclose(f);
}
// 解压图片
void decompressImage(char *filename, unsigned char **pixels, int *width, int *height)
{
FILE *f = fopen(filename, "rb");
if (f == NULL) {
printf("Error: could not open file for reading\n");
return;
}
fread(width, sizeof(int), 1, f);
fread(height, sizeof(int), 1, f);
struct rle *rle_pixels = malloc(sizeof(struct rle) * (*width) * (*height));
fread(rle_pixels, sizeof(struct rle), (*width) * (*height), f);
*pixels = malloc((*width) * (*height));
rle_decode(rle_pixels, (*width) * (*height), *pixels);
free(rle_pixels);
fclose(f);
}
int main()
{
// 读取图片像素矩阵
FILE *f = fopen("input.pgm", "rb");
if (f == NULL) {
printf("Error: could not open file for reading\n");
return -1;
}
char format[3];
fgets(format, 3, f);
if (strcmp(format, "P5") != 0) {
printf("Error: not a PGM file\n");
return -1;
}
int width, height, maxval;
fscanf(f, "%d %d %d", &width, &height, &maxval);
if (maxval > 255) {
printf("Error: cannot handle PGM files with maxval > 255\n");
return -1;
}
unsigned char *pixels = malloc(width * height);
readPixels(pixels, width, height, f);
fclose(f);
// 压缩图片
compressImage(pixels, width, height, "output.rle");
// 解压图片
unsigned char *decompressed_pixels;
int decompressed_width, decompressed_height;
decompressImage("output.rle", &decompressed_pixels, &decompressed_width, &decompressed_height);
// 检查解压是否正确
if (decompressed_width != width || decompressed_height != height) {
printf("Error: decompressed image has incorrect dimensions\n");
return -1;
}
for (int i = 0; i < width * height; i++) {
if (pixels[i] != decompressed_pixels[i]) {
printf("Error: decompressed image is incorrect\n");
return -1;
}
}
printf("Compression and decompression successful\n");
free(pixels);
free(decompressed_pixels);
return 0;
}
```
这段代码实现了对PGM格式图片的压缩和解压缩。其中,`rle_encode()`函数实现了游程编码算法,将像素矩阵压缩成了一个游程编码数组;`rle_decode()`函数实现了游程解码算法,将游程编码数组解码成了一个像素矩阵。`compressImage()`函数将像素矩阵压缩成了文件,`decompressImage()`函数将压缩文件解压成了像素矩阵。程序通过读取PGM格式图片来进行测试,也可以通过修改代码以适应其他图片格式。
阅读全文