他人の空似自作物置場

th105_SE.zip/src/th105_png.c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <windows.h>
#include "th105_lib.h"

typedef struct color{
	unsigned char r;
	unsigned char g;
	unsigned char b;
	unsigned char alpha;
}COLOR;

extern COLOR pal[256];
void load_pal(char *fn,int n);
int cv2_flag = 1;
extern img_flag;

int adler32(unsigned char *data,int len){
	unsigned short s1,s2;
	int i;

	i = 0;
	s1 = 1;
	s2 = 0;
	while(i < len){
		s1 = (s1 + data[i])%65521;
		s2 = (s2 + s1)%65521;
		i++;
	}
	return (s2<<16) + s1;
}

void setchunk(char *p,int len,char *name,char *data){
	*(unsigned int *)p = endian(len);
	memcpy(&p[4],name,4);
	memcpy(&p[8],data,len);
	*(unsigned int *)&p[len+8] = endian(crc(&p[4],len+4));
}

void set_compresseddata(unsigned char *data,unsigned int height,unsigned int width,char *col,int flag){
	unsigned char str[256];
	char *c;
	int i,h,w;

	if(flag)*str = 01;
	else *str = 0;
	*(unsigned short *)&str[1] = height*width+height;
	*(unsigned short *)&str[3] = ~(*(unsigned short *)&str[1]);
	memcpy(data,str,5);

	c = col;
	i = 0;
	h = 0;
	while(h < height){
		w = 0;
		data[5+i] = 0;
		i++;
		while(w < width){
			data[5+i] = *c;
			c++;
			i++;
			w++;
		}
		h++;
	}
}

void pngout(unsigned int width2,unsigned int height,unsigned int width,char *col,char *fn,int cn){
	unsigned int h,w,i,count,len,a,b,d,num;
	unsigned char str[768],s[1024],*data,*e,*c;
	unsigned int adler;
	FILE *fp;


	fp = fopen2(fn,"wb");
	*(int *)s = 0x474e5089;
	*(int *)&s[4] = 0x0a1a0a0d;
	fwrite(s,4,2,fp);

	*(unsigned int *)str = endian(width);
	*(unsigned int *)&str[4] = endian(height);
	str[8] = 8;
	if(cn == 8)str[9] = 3;
	else str[9] = 6;
	str[10] = 0;
	str[11] = 0;
	str[12] = 0;
	setchunk(s,13,"IHDR",str);
	fwrite(s,1,25,fp);

	if(width2 != width){
		*(unsigned int *)str = width2;
		setchunk(s,4,"orIx",str);
		fwrite(s,1,16,fp);
	}

	if(cn == 24 || cn == 32)width *= 4;
	if(cn == 8){
		i = 0;
		while(i < 256){
			str[i*3+0] = pal[i].r;
			str[i*3+1] = pal[i].g;
			str[i*3+2] = pal[i].b;
			i++;
		}
		setchunk(s,768,"PLTE",str);
		fwrite(s,1,780,fp);

		i = 0;
		while(i < 256){
			str[i] = pal[i].alpha;
			i++;
		}
		setchunk(s,256,"tRNS",str);
		fwrite(s,1,268,fp);
	}


	a = height*width+height;
	num = (int)ceil(a/(double)0xffff);//分割数(lenが2byteなので)
	data = malloc(18+10*num+a);

	set_compresseddata(&data[10],height,width,col,1);
	adler = endian(adler32(&data[15],height*width+height));

	if(num == 1){
		i = 1;
	} else {
		i = 0;
		a = height;
		e = &data[10];
		c = col;
		while(1){
			d = a;
			while(d*width+d > 0xFFFF)d--;
			set_compresseddata(e,d,width,c,d == a);
			i++;
			if(d==a)break;
			c += d*width;
			e += 5+d*width+d;
			a -= d;
		}
	}

	a = height*width+height;
	len = 6+5*i+a;
	*(unsigned int *)data = endian(len);
	memcpy(&data[4],"IDAT",4);
	*(short *)&data[8] = endian16(0x7801);

	*(unsigned int *)&data[len+4] = adler;

	*(unsigned int *)&data[len+8] = endian(crc(&data[4],len+4));
	fwrite(data,1,12+len,fp);
	free(data);

	setchunk(s,0,"IEND",NULL);
	fwrite(s,1,12,fp);
	fclose(fp);
}
void convert_col(unsigned int width,unsigned int height,char *col,int cn){
	int h,size;
	char *data;

	switch(cn){
		case 8:
			size = width;
			break;
		case 16:
			size = width*2;
			break;
		case 24:/*
			size = width*3;
			break;*/
		case 32:
			size = width*4;
			break;
		default:
			return;
	}
	data = malloc(size);
	h = 0;
	while(h < height/2){
		memcpy(data,&col[h*size],size);
		memcpy(&col[h*size],&col[(height-h-1)*size],size);
		memcpy(&col[(height-h-1)*size],data,size);
		h++;
	}
	free(data);
}
void bmpout(unsigned int width,unsigned int height,char *col,char *fn,int cn,int mode){
	unsigned int h,w,i,count,len,a;
	unsigned char str[1024],s[1024],*data,*in,*out;
	FILE *fp;

	if(cn == 1|| cn == 4){//未対応
		return;
	}

	convert_col(width,height,col,cn);

	if(strcmp(&fn[strlen(fn)-4],".png") == 0)strcpy(&fn[strlen(fn)-4],".bmp");
	fp = fopen2(fn,"wb");
	strncpy(s,"BM",2);
	*(int *)&s[2] = 0x00000000;
	*(short *)&s[6] = 0x0000;
	*(short *)&s[8] = 0x0000;
	*(int *)&s[10] = 0x00000000;
	fwrite(s,1,14,fp);

	if(mode == 0){
		*(int *)&s[0] = 12;
		*(short *)&s[4] = width;
		*(short *)&s[6] = height;
		*(short *)&s[8] = 1;
		*(short *)&s[10] = cn;
		fwrite(s,1,12,fp);

		if(cn == 8){
			i = 0;
			while(i < 256){
				str[i*3+0] = pal[i].b;
				str[i*3+1] = pal[i].g;
				str[i*3+2] = pal[i].r;
				i++;
			}
			fwrite(str,1,768,fp);
		}
	} else {
		*(int *)&s[0] = 40;
		*(int *)&s[4] = width;
		*(int *)&s[8] = height;
		*(short *)&s[12] = 1;
		*(short *)&s[14] = cn;
		*(int *)&s[16] = 0;
		if(cn == 32){
			*(int *)&s[20] = width*4*height;
		} else if(cn == 24){
			*(int *)&s[20] = ((width*3+3)/4)*4*height;
		} else if(cn == 8){
			*(int *)&s[20] = ((width+3)/4)*4*height;
		} else {
			*(int *)&s[20] = 0;
		}
		*(int *)&s[24] = 3780;
		*(int *)&s[28] = 3780;
		if(cn == 8)	*(int *)&s[32] = 256;
		else 		*(int *)&s[32] = 0;
		*(int *)&s[36] = 0;
		fwrite(s,1,40,fp);

		if(cn == 8){
			i = 0;
			while(i < 256){
				str[i*4+0] = pal[i].b;
				str[i*4+1] = pal[i].g;
				str[i*4+2] = pal[i].r;
				str[i*4+3] = 0;//pal[i].alpha;//α放り込むと一部ソフトで読めなくなるためコメントアウト
				i++;
			}
			fwrite(str,1,1024,fp);
		}
	}
	a = ftell(fp);
	fseek(fp,10,SEEK_SET);
	fwrite(&a,4,1,fp);
	fseek(fp,0,SEEK_END);

	if(cn == 32){
		a = height * width*4;
		data = malloc(a);
		i = 0;
		while(i < a){
			data[i] = col[i+2];
			data[i+1] = col[i+1];
			data[i+2] = col[i];
			data[i+3] = col[i+3];
			i += 4;
		}
	} else if(cn == 24){
		len = width*3;
		if(len%4){
			len += 4-len%4;
		}
		a = height * len;
		data = malloc(a);
		i = 0;
		while(i < a){
			w = 0;
			while(w < width*3){
				data[i+w] = col[2];
				data[i+w+1] = col[1];
				data[i+w+2] = col[0];
				w+=3;
				col+=4;
			}
			while(w < len){
				data[i+w] = 0;
				w++;
			}
			i += len;
		}
	} else if(cn == 8){
		len = width;
		if(len%4){
			len += 4-len%4;
		}
		a = height * len;
		data = malloc(a);
		i = 0;
		while(i < a){
			memcpy(&data[i],col,width);
			memset(&data[i+width],0,len-width);
			i+=len;
			col+=width;
		}
	}

	fwrite(data,1,a,fp);
	free(data);
	a = ftell(fp);
	fseek(fp,2,SEEK_SET);
	fwrite(&a,4,1,fp);
	//fseek(fp,0,SEEK_END);
	fclose(fp);
}

void imgout(unsigned int width2,unsigned int height,unsigned int width,char *col,char *fn,int cn){
	switch(img_flag){
		case 0:
			pngout(width2,height,width,col,fn,cn);
			break;
		case 1:
			bmpout(width,height,col,fn,cn,1);
			break;
		case 2:
			bmpout(width,height,col,fn,cn,0);
			break;
		default:
			printf("Error:Unknown img_type\n");
			return;
	}
}
void ex_cv2(unsigned char *data,int len,char *fn){
	int w,h,w2,i,l;
	COLOR *col;
	char str[256],*c;
	FILE *fp;

	str[0] = data[0];
	w2 = *(unsigned int *)&data[1];
	h = *(unsigned int *)&data[5];
	w = *(unsigned int *)&data[9];
	if(*str == 24 || *str == 32){
		if(cv2_flag){
			i = 0;
			l = 0;
			col = malloc(sizeof(COLOR)*h*w2);
			while(i < h*w2){
				col[i].b = data[17+l*4];
				col[i].g = data[17+l*4+1];
				col[i].r = data[17+l*4+2];
				col[i].alpha = data[17+l*4+3];
				i++;
				l++;
				if(i%w2==0){l+=w-w2;}
			}
			imgout(w2,h,w2,(char *)col,fn,*str);
		} else {
			i = 0;
			col = malloc(sizeof(COLOR)*h*w);
			while(i < h*w){
				col[i].b = data[17+i*4];
				col[i].g = data[17+i*4+1];
				col[i].r = data[17+i*4+2];
				col[i].alpha = data[17+i*4+3];
				i++;
			}
			imgout(w2,h,w,(char *)col,fn,*str);
		}
		free(col);
	} else if(*str == 8){
		load_pal(fn,0);
		if(cv2_flag){
			i = 0;
			l = 0;
			c = malloc(h*w2);
			while(i < h*w2){
				c[i] = data[17+l];
				i++;
				l++;
				if(i%w2==0){l+=w-w2;}
			}
			imgout(w2,h,w2,c,fn,*str);
			free(c);
		} else {
			c = &data[17];
			imgout(w2,h,w,c,fn,*str);
		}
	} else {
		strcpy(str,fn);
		strcpy(&str[strlen(str)-4],".cv2");
		fp = fopen2(str,"wb");
		fwrite(data,1,len,fp);
		fclose(fp);
	}
}