#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
struct ppm
{
int type;
int depth;
// 像素字节数
int step;
int width;
int height;
uint8_t *buffer;
};
#define LINEMAX 128
// 读入ppm文件的一行 (例如第一行P6 type=6, 第二行1024 1024 width=1024 height=1024,第三行255代表depth=255)
// ---------------------------------------------------------------------------
static char *readline(FILE *f, char *buffer)
{
for (;;)
{
char *ret = fgets(buffer, LINEMAX, f);
if (ret == NULL)
{
return NULL;
}
if (ret[0] != '#')
{
return ret;
}
}
}
// ppm和pgm都是相同头格式
// ---------------------------------------------------------------------------
static int ppm_header(FILE *f, struct ppm *ppm)
{
char tmp[LINEMAX];
char *line = readline(f, tmp);
if (line == NULL)
return 0;
char c = 0;
sscanf(line, "P%c", &c);
ppm->type = c;
line = readline(f, tmp);
if (line == NULL)
return 0;
sscanf(line, "%d %d", &(ppm->width), &(ppm->height));
line = readline(f, tmp);
if (line == NULL)
return 0;
sscanf(line, "%d", &(ppm->depth));
return 1;
}
// id '3' ASCII RGB, '6' binary RGB, '2' ASCII Alpha, '5' binary Alpha
// ---------------------------------------------------------------------------
static int ppm_data(struct ppm *ppm, FILE *f, int id, int skip)
{
int i;
int n = ppm->width * ppm->height;
uint8_t *buffer = ppm->buffer + skip;
uint8_t *tmp;
int step = ppm->step;
switch (id)
{
case '3': // RGB text
for (i = 0; i < n; i++)
{
int r, g, b;
fscanf(f, "%d %d %d", &r, &g, &b);
buffer[i * step + 0] = (uint8_t)r;
buffer[i * step + 1] = (uint8_t)g;
buffer[i * step + 2] = (uint8_t)b;
}
break;
case '2': // ALPHA text
for (i = 0; i < n; i++)
{
int alpha;
fscanf(f, "%d", &alpha);
buffer[i * step] = (uint8_t)alpha;
}
break;
case '6': // RGB binary
tmp = (uint8_t *)malloc(n * 3);
if (fread(tmp, n * 3, 1, f) == 0)
{
free(tmp);
return 0;
}
for (i = 0; i < n; i++)
{
buffer[i * step + 0] = tmp[i * 3 + 0];
buffer[i * step + 1] = tmp[i * 3 + 1];
buffer[i * step + 2] = tmp[i * 3 + 2];
}
free(tmp);
break;
case '5': // ALPHA binary
tmp = (uint8_t *)malloc(n);
if (fread(tmp, n, 1, f) == 0)
{
free(tmp);
return 0;
}
for (i = 0; i < n; i++)
{
buffer[i * step] = tmp[i];
}
free(tmp);
break;
default:
return 0;
}
return 1;
}
// ---------------------------------------------------------------------------
static int loadppm_from_file(FILE *rgb, FILE *alpha, struct ppm *ppm)
{
ppm->buffer = NULL;
ppm->step = 0;
int rgb_id = 0;
int alpha_id = 0;
if (rgb)
{
if (!ppm_header(rgb, ppm))
{
return 0;
}
rgb_id = ppm->type;
ppm->step += 3;
}
if (alpha)
{
if (rgb == NULL)
{
if (!ppm_header(alpha, ppm))
{
return 0;
}
alpha_id = ppm->type;
}
else
{
struct ppm pgm;
if (!ppm_header(alpha, &pgm))
{
return 0;
}
if (ppm->depth != pgm.depth || ppm->width != pgm.width || ppm->height != pgm.height)
{
return 0;
}
alpha_id = pgm.type;
}
ppm->step += 1;
}
ppm->buffer = (uint8_t *)malloc(ppm->height * ppm->width * ppm->step);
if (rgb)
{
if (!ppm_data(ppm, rgb, rgb_id, 0))
return 0;
}
if (alpha)
{
int skip = 0;
if (rgb)
{
skip = 3;
}
if (!ppm_data(ppm, alpha, alpha_id, skip))
return 0;
}
return 1;
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("use ppn_to_png file_name\n");
return -1;
}
const char *file_name = argv[1];
int sz = strlen(file_name);
char tmp[sz+5];
sprintf(tmp, "%s.ppm", file_name);
FILE *rgb = fopen(tmp, "rb");
sprintf(tmp, "%s.pgm", file_name);
FILE *alpha = fopen(tmp, "rb");
if (rgb == NULL && alpha == NULL)
{
printf("Can't open %s(.ppm/.pgm)\n", file_name);
return -1;
}
struct ppm ppm;
int ok = loadppm_from_file(rgb, alpha, &ppm);
if (rgb)
{
fclose(rgb);
}
if (alpha)
{
fclose(alpha);
}
sprintf(tmp, "%s.png", file_name);
stbi_write_png(tmp, ppm.width, ppm.height, ppm.step, ppm.buffer, ppm.width*ppm.step);
free(ppm.buffer);
return 0;
}
用到的库
stb/stb_image_write.h at master · nothings/stb · GitHub
标签:tmp,return,十万个,int,ppm,step,alpha,png,图片 From: https://www.cnblogs.com/kehuadong/p/18288358