首页 > 其他分享 >[十万个为什么] ppm图片转png图片

[十万个为什么] ppm图片转png图片

时间:2024-07-07 12:19:28浏览次数:12  
标签:tmp return 十万个 int ppm step alpha png 图片

#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

相关文章

  • 最新扣子(Coze)实战案例:使用图像流做超分,模糊图片秒变清晰,完全免费教程
    ......
  • python 识别图片验证码/滑块验证码准确率极高的 ddddocr 库
    前言验证码的种类有很多,它是常用的一种反爬手段,包括:图片验证码,滑块验证码,等一些常见的验证码场景。识别验证码的python库有很多,用起来也并不简单,这里推荐一个简单实用的识别验证码的库ddddocr(带带弟弟ocr)库.环境准备python版本要求小于等于python3.9版本pip安装pipin......
  • 原生js上传图片至阿里云oss并回显,配合上个帖子的java使用
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Invoice</title>......
  • iOS开发-图片UIImage
    UIImage和UIImageView是iOS开发中常用的两个类,分别用于表示图像数据和显示图像。UIImageUIImage是一个表示图像数据的类,可以从文件、数据、图像资源库等加载图像。UIImage支持多种图像格式,包括PNG、JPEG、GIF等。创建UIImage从文件创建UIImage*image=[UIImage......
  • Python以中心裁剪图片,一个中国大陆身份证的尺寸是88mm*55mm,通常使用的身份证像素分辨
    1#以中心裁剪图片2#一个中国大陆身份证的尺寸是88mm*55mm,通常使用的身份证像素分辨率是336*2563defcrop_image_by_center(input_image_path,width_mm=88,height_mm=55):4#打开图片5image=Image.open(input_image_path)6image=ImageOps.ex......
  • Python按证件照实际大小调整图片尺寸,2英寸证件照:35mmx49mm
    #按证件照实际大小调整图片尺寸,2英寸证件照:35mmx49mm(2024年7月6日)defresize_image_by_ip(input_image_path,width_mm=35,height_mm=49):input_image_path=Path(input_image_path)image=Image.open(input_image_path).convert('RGB')#打开图片,并转换为RGB模......
  • [python]Markdown图片引用格式批处理桌面应用程序
    需求使用python编写一个exe,实现批量修改图片引用,将修改后的文件生成为文件名_blog.md。有一个编辑框,允许接收拖动过来md文件,拖入文件时获取文件路径,有一个编辑框编辑修改后的文件的输出路径,用户拖入文件时,就能自动得到输出的路径作用是将md文件中的例如![image-20240706062921......
  • [python]Markdown图片引用格式批处理桌面应用程序
    需求使用python编写一个exe,实现批量修改图片引用,将修改后的文件生成为文件名_blog.md。有一个编辑框,允许接收拖动过来md文件,拖入文件时获取文件路径,有一个编辑框编辑修改后的文件的输出路径,用户拖入文件时,就能自动得到输出的路径作用是将md文件中的例如![image-20240706062921......
  • python实现从某个网址爬取图片到本地电脑
    源码如下:importurllib#导入urllib包importurllib.request#导入urllib包里的request方法importre#导入re正则库#这个函数实现打开传入的路径并将页面数据读取出来,实现代码,包括发送请求,打开页面,获取数据。defload_page(url):    request=urllib.request.Req......
  • EasyExcel 单元格根据图片数量动态设置宽度
    在使用EasyExcel导出Excel时,如果某个单元格是图片内容,且存在多张图片,此时就需要单元格根据图片数量动态设置宽度。经过自己的研究和实验,导出效果如下:具体代码如下:EasyExcel版本<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactI......