khanat-code-old/code/nel/tools/3d/tile_edit/PIC/Pic_Manage.c
2010-07-10 16:52:06 +02:00

637 lines
No EOL
12 KiB
C

#include <string.h>
#include "pic_private.h"
#include "pic.h"
static unsigned long NbPics=0;
static PIC_PICTURE *HeadPic=NULL;
// ----------------------------------------------------------------------------------------------------------------------------------
static PIC_PICTURE *GetPic(unsigned long id)
{
PIC_PICTURE *pic;
for(pic=HeadPic ; pic ; pic=pic->Next)
{
if (pic->ID==id)
{
return(pic);
}
}
return(NULL);
}
// ----------------------------------------------------------------------------------------------------------------------------------
unsigned long PIC_Load(char* FileName, unsigned char Quantize)
{
unsigned char ext[4];
unsigned long type;
unsigned long i,taken,id;
PIC_PICTURE *pic;
unsigned char *pDatas;
unsigned char *pPal;
unsigned long w,h,Depth;
unsigned long ret;
// --- Init
ret=0;
type=0;
id=0;
taken=0;
w=0;
h=0;
Depth=0;
pic=NULL;
pDatas=NULL;
pPal=NULL;
// --- Get 1st available ID
for(i=1 ; i<=NbPics+1 ; i++)
{
taken=0;
for(pic=HeadPic ; pic ; pic=pic->Next)
{
if (pic->ID==i)
{
taken=1;
break;
}
}
if (!taken)
{
id=i;
break;
}
}
if (!id)
{
Pic_SetError("Load, unable to create ID");
return(0);
}
// --- Load pic
if (FileName)
{
ext[0]=FileName[strlen(FileName)-3];
ext[1]=FileName[strlen(FileName)-2];
ext[2]=FileName[strlen(FileName)-1];
ext[3]=0;
strupr(ext);
if ( !strcmp(ext,"JPG") )
{
type=1;
}
else if ( !strcmp(ext,"TGA") )
{
type=2;
}
else if ( !strcmp(ext,"BMP") )
{
type=3;
}
switch(type)
{
// - JPG
case 1:
if (!Quantize)
{
Depth=24;
ret=Pic_JPG_Read(FileName,NULL,&pDatas,&w,&h);
}
else
{
Depth=8;
ret=Pic_JPG_Read(FileName,&pPal,&pDatas,&w,&h);
}
if (!ret)
{
Pic_SetError("Load, unable to load JPG file %s",FileName);
return(0);
}
break;
// - TGA
case 2:
ret=Pic_TGA_Read(FileName,&pPal,&pDatas,&w,&h,&Depth);
if (!ret)
{
Pic_SetError("Load, unable to load TGA file %s",FileName);
return(0);
}
break;
// - BMP
case 3:
ret=Pic_BMP_Read(FileName,&pPal,&pDatas,&w,&h,&Depth);
if (!ret)
{
Pic_SetError("Load, unable to load BMP file %s",FileName);
return(0);
}
break;
// - Unknown
default:
Pic_SetError("Load, unknown extension for %s",FileName);
return(0);
}
}
// --- Create and place new pic struct
pic=Pic_calloc(1,sizeof(PIC_PICTURE));
if (!pic)
{
Pic_SetError("Load, not enough memory for internal structure");
return(0);
}
pic->Next=HeadPic;
HeadPic=pic;
NbPics++;
pic->ID=id;
pic->pDatas=pDatas;
pic->pPal=pPal;
pic->Width=w;
pic->Height=h;
pic->Depth=Depth;
return(id);
}
// ----------------------------------------------------------------------------------------------------------------------------------
unsigned long PIC_Create(unsigned char* pPal, unsigned char* pDatas, unsigned long w, unsigned long h, unsigned long d)
{
unsigned long i,taken,id;
PIC_PICTURE *pic;
// --- Init
id=0;
taken=0;
pic=NULL;
// --- Get 1st available ID
for(i=1 ; i<=NbPics+1 ; i++)
{
taken=0;
for(pic=HeadPic ; pic ; pic=pic->Next)
{
if (pic->ID==i)
{
taken=1;
break;
}
}
if (!taken)
{
id=i;
break;
}
}
if (!id)
{
Pic_SetError("Create, unable to create ID");
return(0);
}
// --- Create pic
if (!pDatas)
{
pDatas=Pic_calloc(1,w*h*d/8);
if (!pDatas)
{
Pic_SetError("Create, not enough memory for datas");
return(0);
}
}
if (d==8)
{
if (!pPal)
{
pPal=Pic_calloc(1,256*3);
if (!pPal)
{
Pic_SetError("Create, not enough memory for palette");
return(0);
}
}
}
else
{
pPal=NULL;
}
// --- Create and place new pic struct
pic=Pic_calloc(1,sizeof(PIC_PICTURE));
if (!pic)
{
Pic_SetError("Create, not enough memory for internal structure");
return(0);
}
pic->Next=HeadPic;
HeadPic=pic;
NbPics++;
pic->ID=id;
pic->pDatas=pDatas;
pic->pPal=pPal;
pic->Width=w;
pic->Height=h;
pic->Depth=d;
return(id);
}
// ----------------------------------------------------------------------------------------------------------------------------------
unsigned long PIC_GetInfos( unsigned long id,
unsigned char* *ppPal, unsigned char* *ppDatas,
unsigned long *pW, unsigned long *pH, unsigned long *pD)
{
PIC_PICTURE *pic;
pic=GetPic(id);
if (!pic)
{
Pic_SetError("GetInfos, picture internal structure not found");
return(0);
}
if (ppPal)
{
*ppPal=pic->pPal;
}
if (ppDatas)
{
*ppDatas=pic->pDatas;
}
if (pW)
{
*pW=pic->Width;
}
if (pH)
{
*pH=pic->Height;
}
if (pD)
{
*pD=pic->Depth;
}
return(id);
}
// ----------------------------------------------------------------------------------------------------------------------------------
static char* Conv8To24(unsigned long id)
{
PIC_PICTURE *pic;
unsigned char *buf;
unsigned long i;
pic=GetPic(id);
if (!pic)
{
Pic_SetError("Conv8To24, picture internal structure not found");
return(NULL);
}
buf=Pic_malloc(pic->Width*pic->Height*3);
if (!buf)
{
Pic_SetError("Conv8To24, not enough memory for temporary buffer");
return(NULL);
}
for(i=0 ; i<pic->Width*pic->Height ; i++)
{
buf[i*3+0]=pic->pPal[pic->pDatas[i]*3+0];
buf[i*3+1]=pic->pPal[pic->pDatas[i]*3+1];
buf[i*3+2]=pic->pPal[pic->pDatas[i]*3+2];
}
return(buf);
}
// ----------------------------------------
static char* Conv8To16(unsigned long id)
{
PIC_PICTURE *pic;
unsigned short *buf;
unsigned long i;
unsigned short r,g,b,pix16;
pic=GetPic(id);
if (!pic)
{
Pic_SetError("Conv8To24, picture internal structure not found");
return(NULL);
}
buf=(unsigned short*)Pic_malloc(pic->Width*pic->Height*2);
if (!buf)
{
Pic_SetError("Conv8To24, not enough memory for temporary buffer");
return(NULL);
}
for(i=0 ; i<pic->Width*pic->Height ; i++)
{
b=pic->pPal[pic->pDatas[i]*3+0];
g=pic->pPal[pic->pDatas[i]*3+1];
r=pic->pPal[pic->pDatas[i]*3+2];
r>>=3;
g>>=3; g&=0x3E;
b>>=3;
pix16=(r<<10)+(g<<5)+b;
buf[i]=pix16;
}
return((unsigned char*)buf);
}
// ----------------------------------------
static char* Conv16To24(unsigned long id)
{
PIC_PICTURE *pic;
unsigned short *pDatas;
unsigned char *buf;
unsigned long i;
unsigned short r,g,b;
pic=GetPic(id);
if (!pic)
{
Pic_SetError("Conv16To24, picture internal structure not found");
return(NULL);
}
buf=Pic_malloc(pic->Width*pic->Height*3);
if (!buf)
{
Pic_SetError("Conv16To24, not enough memory for temporary buffer");
return(NULL);
}
pDatas=(unsigned short*)pic->pDatas;
for(i=0 ; i<pic->Width*pic->Height ; i++)
{
r=(pDatas[i] & 0x7C00)>>(10-3);
g=(pDatas[i] & 0x03E0)>>(5-3);
b=(pDatas[i] & 0x001F)<<3;
buf[i*3+0]=(unsigned char)r;
buf[i*3+1]=(unsigned char)g;
buf[i*3+2]=(unsigned char)b;
}
return(buf);
}
// ----------------------------------------
static char* Conv24To16(unsigned long id)
{
PIC_PICTURE *pic;
unsigned short *buf;
unsigned long i;
unsigned short r,g,b;
unsigned short pix16;
pic=GetPic(id);
if (!pic)
{
Pic_SetError("Conv24To16, picture internal structure not found");
return(NULL);
}
buf=(unsigned short*)Pic_malloc(pic->Width*pic->Height*2);
if (!buf)
{
Pic_SetError("Conv24To16, not enough memory for temporary buffer");
return(NULL);
}
for(i=0 ; i<pic->Width*pic->Height ; i++)
{
r=pic->pDatas[i*3+0];
g=pic->pDatas[i*3+1];
b=pic->pDatas[i*3+2];
// r : 5 bits forts (0x7C)
// g : 5 bits (6e zapped) (0x3E)
// b : 5 bits faibles (0x1F)
r>>=3;
g>>=3; g&=0x3E;
b>>=3;
pix16=(r<<10)+(g<<5)+b;
buf[i]=pix16;
}
return((unsigned char*)buf);
}
// ----------------------------------------
static char* ConvPic(PIC_PICTURE *pic, unsigned long type, char* pErr)
{
unsigned char *buf;
unsigned long src,dst;
*pErr=0;
buf=NULL;
src=pic->Depth;
if (type==PIC_TYPE_TGA8 || type==PIC_TYPE_BMP8)
{
dst=8;
}
if (type==PIC_TYPE_TGA16)
{
dst=16;
}
if (type==PIC_TYPE_JPG || type==PIC_TYPE_TGA24 || type==PIC_TYPE_BMP24)
{
dst=24;
}
// ---
if (src==dst)
{
return(NULL);
}
// ---
if (src==8 && dst==24)
{
buf=Conv8To24(pic->ID);
if (!buf)
{
*pErr=1;
}
return(buf);
}
if (src==8 && dst==16)
{
buf=Conv8To16(pic->ID);
if (!buf)
{
*pErr=1;
}
return(buf);
}
// ---
if (src==16 && dst==24)
{
buf=Conv16To24(pic->ID);
if (!buf)
{
*pErr=1;
}
return(buf);
}
// ---
if (src==24 && dst==16)
{
buf=Conv24To16(pic->ID);
if (!buf)
{
*pErr=1;
}
return(buf);
}
// ---
if (src==24 && dst==8)
{
Pic_SetError("ConvPic, downsampling 24 to 8 bits unsupported");
*pErr=1;
return(NULL);
}
Pic_SetError("ConvPic, conversion %d to %d unsupported",src,dst);
*pErr=1;
return(NULL);
}
// ----------------------------------------
unsigned long PIC_Save(unsigned long id, char* FileName, unsigned long type, unsigned long qual)
{
PIC_PICTURE *pic;
unsigned char err;
unsigned char *buf;
unsigned char *freeit;
unsigned long depth;
freeit=NULL;
pic=GetPic(id);
if (!pic)
{
Pic_SetError("Save %s, picture internal structure not found",FileName);
return(0);
}
freeit=ConvPic(pic,type,&err);
if (err)
{
Pic_SetError("Save %s, error while converting picture",FileName);
return(0);
}
if (!freeit)
{
buf=pic->pDatas;
}
else
{
buf=freeit;
}
err=0;
switch(type)
{
// ---
case PIC_TYPE_JPG:
if ( !Pic_JPG_Write(FileName,qual,buf,pic->Width,pic->Height) )
{
if (freeit)
{
Pic_free(buf);
}
Pic_SetError("Save %s, error while saving JPG file",FileName);
err=1;
}
break;
// ---
case PIC_TYPE_TGA8:
case PIC_TYPE_TGA16:
case PIC_TYPE_TGA24:
if (type==PIC_TYPE_TGA8)
{
depth=8;
}
if (type==PIC_TYPE_TGA16)
{
depth=16;
}
if (type==PIC_TYPE_TGA24)
{
depth=24;
}
if ( !Pic_TGA_Write(FileName,pic->pPal,buf,pic->Width,pic->Height,depth) )
{
if (freeit)
{
Pic_free(freeit);
}
Pic_SetError("Save %s, error while saving TGA file",FileName);
err=1;
}
break;
// ---
case PIC_TYPE_BMP8:
case PIC_TYPE_BMP24:
if (type==PIC_TYPE_BMP8)
{
depth=8;
}
if (type==PIC_TYPE_BMP24)
{
depth=24;
}
if ( !Pic_BMP_Write(FileName,pic->pPal,buf,pic->Width,pic->Height,depth) )
{
if (freeit)
{
Pic_free(freeit);
}
Pic_SetError("Save %s, error while saving BMP file",FileName);
err=1;
}
break;
// ---
default:
Pic_SetError("Save %s, unknow save format/type",FileName);
err=1;
break;
}
if (freeit)
{
Pic_free(freeit);
}
return(err-1);
}
// ----------------------------------------------------------------------------------------------------------------------------------
unsigned long PIC_Destroy(unsigned long id)
{
PIC_PICTURE *prevpic,*pic;
unsigned long found;
prevpic=NULL;
found=0;
for(pic=HeadPic ; pic ; pic=pic->Next)
{
if (pic->ID==id)
{
found=1;
break;
}
prevpic=pic;
}
if (!found)
{
Pic_SetError("Destroy, picture internal structure not found");
return(0);
}
if (prevpic)
{
prevpic->Next=pic->Next;
}
if (pic->pDatas)
{
Pic_free(pic->pDatas);
}
if (pic->pPal)
{
Pic_free(pic->pPal);
}
if (pic==HeadPic)
{
HeadPic=pic->Next;
}
Pic_free(pic);
return(1);
}
// ----------------------------------------------------------------------------------------------------------------------------------