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);
}
}