From f35b4bd18f8cd4d7c4aed34d4905bc8d6931e5d5 Mon Sep 17 00:00:00 2001 From: Denton Woods Date: Wed, 28 Dec 2016 17:39:02 -0600 Subject: - More source changes to C++ --- DevIL/src-IL/src/altivec_common.c | 40 - DevIL/src-IL/src/altivec_common.cpp | 40 + DevIL/src-IL/src/altivec_typeconversion.c | 230 --- DevIL/src-IL/src/altivec_typeconversion.cpp | 230 +++ DevIL/src-IL/src/il_alloc.c | 287 --- DevIL/src-IL/src/il_alloc.cpp | 287 +++ DevIL/src-IL/src/il_bits.c | 185 -- DevIL/src-IL/src/il_bits.cpp | 185 ++ DevIL/src-IL/src/il_blp.c | 736 -------- DevIL/src-IL/src/il_blp.cpp | 736 ++++++++ DevIL/src-IL/src/il_bmp.c | 1048 ----------- DevIL/src-IL/src/il_bmp.cpp | 1048 +++++++++++ DevIL/src-IL/src/il_convbuff.c | 2315 ----------------------- DevIL/src-IL/src/il_convbuff.cpp | 2315 +++++++++++++++++++++++ DevIL/src-IL/src/il_convert.c | 1125 ----------- DevIL/src-IL/src/il_convert.cpp | 1125 +++++++++++ DevIL/src-IL/src/il_cut.c | 147 -- DevIL/src-IL/src/il_cut.cpp | 147 ++ DevIL/src-IL/src/il_dcx.c | 485 ----- DevIL/src-IL/src/il_dcx.cpp | 485 +++++ DevIL/src-IL/src/il_dds-save.c | 1313 ------------- DevIL/src-IL/src/il_dds-save.cpp | 1313 +++++++++++++ DevIL/src-IL/src/il_dds.c | 2523 ------------------------- DevIL/src-IL/src/il_dds.cpp | 2523 +++++++++++++++++++++++++ DevIL/src-IL/src/il_devil.c | 1068 ----------- DevIL/src-IL/src/il_devil.cpp | 1068 +++++++++++ DevIL/src-IL/src/il_dicom.c | 608 ------ DevIL/src-IL/src/il_dicom.cpp | 608 ++++++ DevIL/src-IL/src/il_doom.c | 271 --- DevIL/src-IL/src/il_doom.cpp | 271 +++ DevIL/src-IL/src/il_dpx.c | 325 ---- DevIL/src-IL/src/il_dpx.cpp | 325 ++++ DevIL/src-IL/src/il_endian.c | 546 ------ DevIL/src-IL/src/il_endian.cpp | 546 ++++++ DevIL/src-IL/src/il_error.c | 56 - DevIL/src-IL/src/il_error.cpp | 56 + DevIL/src-IL/src/il_fastconv.c | 290 --- DevIL/src-IL/src/il_fastconv.cpp | 290 +++ DevIL/src-IL/src/il_files.c | 773 -------- DevIL/src-IL/src/il_files.cpp | 773 ++++++++ DevIL/src-IL/src/il_fits.c | 472 ----- DevIL/src-IL/src/il_fits.cpp | 472 +++++ DevIL/src-IL/src/il_ftx.c | 101 - DevIL/src-IL/src/il_ftx.cpp | 101 + DevIL/src-IL/src/il_gif.c | 755 -------- DevIL/src-IL/src/il_gif.cpp | 755 ++++++++ DevIL/src-IL/src/il_hdr.c | 659 ------- DevIL/src-IL/src/il_hdr.cpp | 659 +++++++ DevIL/src-IL/src/il_header.c | 135 -- DevIL/src-IL/src/il_header.cpp | 135 ++ DevIL/src-IL/src/il_icns.c | 362 ---- DevIL/src-IL/src/il_icns.cpp | 362 ++++ DevIL/src-IL/src/il_icon.c | 674 ------- DevIL/src-IL/src/il_icon.cpp | 674 +++++++ DevIL/src-IL/src/il_iff.c | 479 ----- DevIL/src-IL/src/il_iff.cpp | 479 +++++ DevIL/src-IL/src/il_ilbm.c | 658 ------- DevIL/src-IL/src/il_ilbm.cpp | 658 +++++++ DevIL/src-IL/src/il_internal.c | 271 --- DevIL/src-IL/src/il_internal.cpp | 271 +++ DevIL/src-IL/src/il_io.c | 2698 --------------------------- DevIL/src-IL/src/il_io.cpp | 2698 +++++++++++++++++++++++++++ DevIL/src-IL/src/il_iwi.c | 401 ---- DevIL/src-IL/src/il_iwi.cpp | 401 ++++ DevIL/src-IL/src/il_jp2.c | 809 -------- DevIL/src-IL/src/il_jp2.cpp | 809 ++++++++ DevIL/src-IL/src/il_jpeg.c | 1001 ---------- DevIL/src-IL/src/il_jpeg.cpp | 1001 ++++++++++ DevIL/src-IL/src/il_ktx.c | 271 --- DevIL/src-IL/src/il_ktx.cpp | 271 +++ DevIL/src-IL/src/il_lif.c | 198 -- DevIL/src-IL/src/il_lif.cpp | 198 ++ DevIL/src-IL/src/il_main.c | 30 - DevIL/src-IL/src/il_main.cpp | 30 + DevIL/src-IL/src/il_manip.c | 1154 ------------ DevIL/src-IL/src/il_manip.cpp | 1154 ++++++++++++ DevIL/src-IL/src/il_mdl.c | 218 --- DevIL/src-IL/src/il_mdl.cpp | 218 +++ DevIL/src-IL/src/il_mng.c | 378 ---- DevIL/src-IL/src/il_mng.cpp | 378 ++++ DevIL/src-IL/src/il_mp3.c | 280 --- DevIL/src-IL/src/il_mp3.cpp | 280 +++ DevIL/src-IL/src/il_neuquant.c | 462 ----- DevIL/src-IL/src/il_neuquant.cpp | 462 +++++ DevIL/src-IL/src/il_pal.c | 1111 ----------- DevIL/src-IL/src/il_pal.cpp | 1111 +++++++++++ DevIL/src-IL/src/il_pcd.c | 206 -- DevIL/src-IL/src/il_pcd.cpp | 206 ++ DevIL/src-IL/src/il_pcx.c | 739 -------- DevIL/src-IL/src/il_pcx.cpp | 739 ++++++++ DevIL/src-IL/src/il_pic.c | 425 ----- DevIL/src-IL/src/il_pic.cpp | 425 +++++ DevIL/src-IL/src/il_pix.c | 158 -- DevIL/src-IL/src/il_pix.cpp | 158 ++ DevIL/src-IL/src/il_png.c | 738 -------- DevIL/src-IL/src/il_png.cpp | 738 ++++++++ DevIL/src-IL/src/il_pnm.c | 697 ------- DevIL/src-IL/src/il_pnm.cpp | 697 +++++++ DevIL/src-IL/src/il_profiles.c | 174 -- DevIL/src-IL/src/il_profiles.cpp | 174 ++ DevIL/src-IL/src/il_psd.c | 1086 ----------- DevIL/src-IL/src/il_psd.cpp | 1086 +++++++++++ DevIL/src-IL/src/il_psp.c | 712 ------- DevIL/src-IL/src/il_psp.cpp | 712 +++++++ DevIL/src-IL/src/il_pxr.c | 119 -- DevIL/src-IL/src/il_pxr.cpp | 119 ++ DevIL/src-IL/src/il_quantizer.c | 643 ------- DevIL/src-IL/src/il_quantizer.cpp | 643 +++++++ DevIL/src-IL/src/il_raw.c | 188 -- DevIL/src-IL/src/il_raw.cpp | 188 ++ DevIL/src-IL/src/il_rawdata.c | 120 -- DevIL/src-IL/src/il_rawdata.cpp | 120 ++ DevIL/src-IL/src/il_register.c | 434 ----- DevIL/src-IL/src/il_register.cpp | 434 +++++ DevIL/src-IL/src/il_rle.c | 153 -- DevIL/src-IL/src/il_rle.cpp | 153 ++ DevIL/src-IL/src/il_rot.c | 289 --- DevIL/src-IL/src/il_rot.cpp | 289 +++ DevIL/src-IL/src/il_sgi.c | 762 -------- DevIL/src-IL/src/il_sgi.cpp | 762 ++++++++ DevIL/src-IL/src/il_size.c | 185 -- DevIL/src-IL/src/il_size.cpp | 185 ++ DevIL/src-IL/src/il_stack.c | 669 ------- DevIL/src-IL/src/il_stack.cpp | 669 +++++++ DevIL/src-IL/src/il_states.c | 1192 ------------ DevIL/src-IL/src/il_states.cpp | 1192 ++++++++++++ DevIL/src-IL/src/il_sun.c | 398 ---- DevIL/src-IL/src/il_sun.cpp | 398 ++++ DevIL/src-IL/src/il_targa.c | 961 ---------- DevIL/src-IL/src/il_targa.cpp | 961 ++++++++++ DevIL/src-IL/src/il_texture.c | 66 - DevIL/src-IL/src/il_texture.cpp | 66 + DevIL/src-IL/src/il_tiff.c | 1112 ----------- DevIL/src-IL/src/il_tiff.cpp | 1112 +++++++++++ DevIL/src-IL/src/il_tpl.c | 782 -------- DevIL/src-IL/src/il_tpl.cpp | 782 ++++++++ DevIL/src-IL/src/il_utility.c | 171 -- DevIL/src-IL/src/il_utility.cpp | 171 ++ DevIL/src-IL/src/il_vtf.c | 953 ---------- DevIL/src-IL/src/il_vtf.cpp | 953 ++++++++++ DevIL/src-IL/src/il_wal.c | 168 -- DevIL/src-IL/src/il_wal.cpp | 168 ++ DevIL/src-IL/src/il_wbmp.c | 274 --- DevIL/src-IL/src/il_wbmp.cpp | 274 +++ DevIL/src-IL/src/il_wdp.c | 429 ----- DevIL/src-IL/src/il_wdp.cpp | 429 +++++ DevIL/src-IL/src/il_xpm.c | 655 ------- DevIL/src-IL/src/il_xpm.cpp | 655 +++++++ 148 files changed, 43606 insertions(+), 43606 deletions(-) delete mode 100644 DevIL/src-IL/src/altivec_common.c create mode 100644 DevIL/src-IL/src/altivec_common.cpp delete mode 100644 DevIL/src-IL/src/altivec_typeconversion.c create mode 100644 DevIL/src-IL/src/altivec_typeconversion.cpp delete mode 100644 DevIL/src-IL/src/il_alloc.c create mode 100644 DevIL/src-IL/src/il_alloc.cpp delete mode 100644 DevIL/src-IL/src/il_bits.c create mode 100644 DevIL/src-IL/src/il_bits.cpp delete mode 100755 DevIL/src-IL/src/il_blp.c create mode 100755 DevIL/src-IL/src/il_blp.cpp delete mode 100644 DevIL/src-IL/src/il_bmp.c create mode 100644 DevIL/src-IL/src/il_bmp.cpp delete mode 100644 DevIL/src-IL/src/il_convbuff.c create mode 100644 DevIL/src-IL/src/il_convbuff.cpp delete mode 100644 DevIL/src-IL/src/il_convert.c create mode 100644 DevIL/src-IL/src/il_convert.cpp delete mode 100644 DevIL/src-IL/src/il_cut.c create mode 100644 DevIL/src-IL/src/il_cut.cpp delete mode 100644 DevIL/src-IL/src/il_dcx.c create mode 100644 DevIL/src-IL/src/il_dcx.cpp delete mode 100644 DevIL/src-IL/src/il_dds-save.c create mode 100644 DevIL/src-IL/src/il_dds-save.cpp delete mode 100644 DevIL/src-IL/src/il_dds.c create mode 100644 DevIL/src-IL/src/il_dds.cpp delete mode 100644 DevIL/src-IL/src/il_devil.c create mode 100644 DevIL/src-IL/src/il_devil.cpp delete mode 100644 DevIL/src-IL/src/il_dicom.c create mode 100644 DevIL/src-IL/src/il_dicom.cpp delete mode 100644 DevIL/src-IL/src/il_doom.c create mode 100644 DevIL/src-IL/src/il_doom.cpp delete mode 100644 DevIL/src-IL/src/il_dpx.c create mode 100644 DevIL/src-IL/src/il_dpx.cpp delete mode 100644 DevIL/src-IL/src/il_endian.c create mode 100644 DevIL/src-IL/src/il_endian.cpp delete mode 100644 DevIL/src-IL/src/il_error.c create mode 100644 DevIL/src-IL/src/il_error.cpp delete mode 100644 DevIL/src-IL/src/il_fastconv.c create mode 100644 DevIL/src-IL/src/il_fastconv.cpp delete mode 100644 DevIL/src-IL/src/il_files.c create mode 100644 DevIL/src-IL/src/il_files.cpp delete mode 100644 DevIL/src-IL/src/il_fits.c create mode 100644 DevIL/src-IL/src/il_fits.cpp delete mode 100644 DevIL/src-IL/src/il_ftx.c create mode 100644 DevIL/src-IL/src/il_ftx.cpp delete mode 100644 DevIL/src-IL/src/il_gif.c create mode 100644 DevIL/src-IL/src/il_gif.cpp delete mode 100644 DevIL/src-IL/src/il_hdr.c create mode 100644 DevIL/src-IL/src/il_hdr.cpp delete mode 100644 DevIL/src-IL/src/il_header.c create mode 100644 DevIL/src-IL/src/il_header.cpp delete mode 100644 DevIL/src-IL/src/il_icns.c create mode 100644 DevIL/src-IL/src/il_icns.cpp delete mode 100644 DevIL/src-IL/src/il_icon.c create mode 100644 DevIL/src-IL/src/il_icon.cpp delete mode 100755 DevIL/src-IL/src/il_iff.c create mode 100755 DevIL/src-IL/src/il_iff.cpp delete mode 100644 DevIL/src-IL/src/il_ilbm.c create mode 100644 DevIL/src-IL/src/il_ilbm.cpp delete mode 100644 DevIL/src-IL/src/il_internal.c create mode 100644 DevIL/src-IL/src/il_internal.cpp delete mode 100644 DevIL/src-IL/src/il_io.c create mode 100644 DevIL/src-IL/src/il_io.cpp delete mode 100644 DevIL/src-IL/src/il_iwi.c create mode 100644 DevIL/src-IL/src/il_iwi.cpp delete mode 100644 DevIL/src-IL/src/il_jp2.c create mode 100644 DevIL/src-IL/src/il_jp2.cpp delete mode 100644 DevIL/src-IL/src/il_jpeg.c create mode 100644 DevIL/src-IL/src/il_jpeg.cpp delete mode 100644 DevIL/src-IL/src/il_ktx.c create mode 100644 DevIL/src-IL/src/il_ktx.cpp delete mode 100644 DevIL/src-IL/src/il_lif.c create mode 100644 DevIL/src-IL/src/il_lif.cpp delete mode 100644 DevIL/src-IL/src/il_main.c create mode 100644 DevIL/src-IL/src/il_main.cpp delete mode 100644 DevIL/src-IL/src/il_manip.c create mode 100644 DevIL/src-IL/src/il_manip.cpp delete mode 100644 DevIL/src-IL/src/il_mdl.c create mode 100644 DevIL/src-IL/src/il_mdl.cpp delete mode 100644 DevIL/src-IL/src/il_mng.c create mode 100644 DevIL/src-IL/src/il_mng.cpp delete mode 100755 DevIL/src-IL/src/il_mp3.c create mode 100755 DevIL/src-IL/src/il_mp3.cpp delete mode 100644 DevIL/src-IL/src/il_neuquant.c create mode 100644 DevIL/src-IL/src/il_neuquant.cpp delete mode 100644 DevIL/src-IL/src/il_pal.c create mode 100644 DevIL/src-IL/src/il_pal.cpp delete mode 100644 DevIL/src-IL/src/il_pcd.c create mode 100644 DevIL/src-IL/src/il_pcd.cpp delete mode 100644 DevIL/src-IL/src/il_pcx.c create mode 100644 DevIL/src-IL/src/il_pcx.cpp delete mode 100644 DevIL/src-IL/src/il_pic.c create mode 100644 DevIL/src-IL/src/il_pic.cpp delete mode 100644 DevIL/src-IL/src/il_pix.c create mode 100644 DevIL/src-IL/src/il_pix.cpp delete mode 100644 DevIL/src-IL/src/il_png.c create mode 100644 DevIL/src-IL/src/il_png.cpp delete mode 100644 DevIL/src-IL/src/il_pnm.c create mode 100644 DevIL/src-IL/src/il_pnm.cpp delete mode 100644 DevIL/src-IL/src/il_profiles.c create mode 100644 DevIL/src-IL/src/il_profiles.cpp delete mode 100644 DevIL/src-IL/src/il_psd.c create mode 100644 DevIL/src-IL/src/il_psd.cpp delete mode 100644 DevIL/src-IL/src/il_psp.c create mode 100644 DevIL/src-IL/src/il_psp.cpp delete mode 100644 DevIL/src-IL/src/il_pxr.c create mode 100644 DevIL/src-IL/src/il_pxr.cpp delete mode 100644 DevIL/src-IL/src/il_quantizer.c create mode 100644 DevIL/src-IL/src/il_quantizer.cpp delete mode 100644 DevIL/src-IL/src/il_raw.c create mode 100644 DevIL/src-IL/src/il_raw.cpp delete mode 100644 DevIL/src-IL/src/il_rawdata.c create mode 100644 DevIL/src-IL/src/il_rawdata.cpp delete mode 100644 DevIL/src-IL/src/il_register.c create mode 100644 DevIL/src-IL/src/il_register.cpp delete mode 100644 DevIL/src-IL/src/il_rle.c create mode 100644 DevIL/src-IL/src/il_rle.cpp delete mode 100644 DevIL/src-IL/src/il_rot.c create mode 100644 DevIL/src-IL/src/il_rot.cpp delete mode 100644 DevIL/src-IL/src/il_sgi.c create mode 100644 DevIL/src-IL/src/il_sgi.cpp delete mode 100755 DevIL/src-IL/src/il_size.c create mode 100755 DevIL/src-IL/src/il_size.cpp delete mode 100644 DevIL/src-IL/src/il_stack.c create mode 100644 DevIL/src-IL/src/il_stack.cpp delete mode 100644 DevIL/src-IL/src/il_states.c create mode 100644 DevIL/src-IL/src/il_states.cpp delete mode 100644 DevIL/src-IL/src/il_sun.c create mode 100644 DevIL/src-IL/src/il_sun.cpp delete mode 100644 DevIL/src-IL/src/il_targa.c create mode 100644 DevIL/src-IL/src/il_targa.cpp delete mode 100644 DevIL/src-IL/src/il_texture.c create mode 100644 DevIL/src-IL/src/il_texture.cpp delete mode 100644 DevIL/src-IL/src/il_tiff.c create mode 100644 DevIL/src-IL/src/il_tiff.cpp delete mode 100755 DevIL/src-IL/src/il_tpl.c create mode 100755 DevIL/src-IL/src/il_tpl.cpp delete mode 100644 DevIL/src-IL/src/il_utility.c create mode 100644 DevIL/src-IL/src/il_utility.cpp delete mode 100644 DevIL/src-IL/src/il_vtf.c create mode 100644 DevIL/src-IL/src/il_vtf.cpp delete mode 100644 DevIL/src-IL/src/il_wal.c create mode 100644 DevIL/src-IL/src/il_wal.cpp delete mode 100755 DevIL/src-IL/src/il_wbmp.c create mode 100755 DevIL/src-IL/src/il_wbmp.cpp delete mode 100644 DevIL/src-IL/src/il_wdp.c create mode 100644 DevIL/src-IL/src/il_wdp.cpp delete mode 100644 DevIL/src-IL/src/il_xpm.c create mode 100644 DevIL/src-IL/src/il_xpm.cpp diff --git a/DevIL/src-IL/src/altivec_common.c b/DevIL/src-IL/src/altivec_common.c deleted file mode 100644 index d3ca2dba..00000000 --- a/DevIL/src-IL/src/altivec_common.c +++ /dev/null @@ -1,40 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Last modified: 17/04/2005 -// by Meloni Dario -// -// Description: Common altivec function. -// -//----------------------------------------------------------------------------- - -#ifdef HAVE_CONFIG_H -#include -#endif //HAVE_CONFIG_H - -#ifdef ALTIVEC_GCC -#include "altivec_common.h" - -// from http://developer.apple.com/hardware/ve/alignment.html -/*vector unsigned char load_unaligned( unsigned char *buffer ) { - vector unsigned char MSQ, LSQ; - vector unsigned char mask; - MSQ = vec_ld(0, buffer); // most significant quadword - LSQ = vec_ld(15, buffer); // least significant quadword - mask = vec_lvsl(0, buffer); // create the permute mask - return vec_perm(MSQ, LSQ, mask);// align the data -}*/ - -vector float fill_vector_f( float value ) { - vector_t vec; - vec.sf[0] = value; - vector float temp = vec_ld(0,vec.sf); - return vec_splat(temp,0); -} - -inline unsigned int round16( unsigned int v ) { - return ((int)((v/16)*10)%10) > 0 ? (v/16) : (v/16)+1; -} - - -#endif diff --git a/DevIL/src-IL/src/altivec_common.cpp b/DevIL/src-IL/src/altivec_common.cpp new file mode 100644 index 00000000..d3ca2dba --- /dev/null +++ b/DevIL/src-IL/src/altivec_common.cpp @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Last modified: 17/04/2005 +// by Meloni Dario +// +// Description: Common altivec function. +// +//----------------------------------------------------------------------------- + +#ifdef HAVE_CONFIG_H +#include +#endif //HAVE_CONFIG_H + +#ifdef ALTIVEC_GCC +#include "altivec_common.h" + +// from http://developer.apple.com/hardware/ve/alignment.html +/*vector unsigned char load_unaligned( unsigned char *buffer ) { + vector unsigned char MSQ, LSQ; + vector unsigned char mask; + MSQ = vec_ld(0, buffer); // most significant quadword + LSQ = vec_ld(15, buffer); // least significant quadword + mask = vec_lvsl(0, buffer); // create the permute mask + return vec_perm(MSQ, LSQ, mask);// align the data +}*/ + +vector float fill_vector_f( float value ) { + vector_t vec; + vec.sf[0] = value; + vector float temp = vec_ld(0,vec.sf); + return vec_splat(temp,0); +} + +inline unsigned int round16( unsigned int v ) { + return ((int)((v/16)*10)%10) > 0 ? (v/16) : (v/16)+1; +} + + +#endif diff --git a/DevIL/src-IL/src/altivec_typeconversion.c b/DevIL/src-IL/src/altivec_typeconversion.c deleted file mode 100644 index b620066e..00000000 --- a/DevIL/src-IL/src/altivec_typeconversion.c +++ /dev/null @@ -1,230 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include -#endif //HAVE_CONFIG_H - -#ifdef ALTIVEC_GCC -#include "altivec_typeconversion.h" - -static inline void abc2cba_internal( register const vector unsigned char p[4], unsigned char *data, register unsigned int length, unsigned char *newdata ) { - register vector unsigned char d0,d1,d2,t0,t1,t2; - - length = eround16(length); - - if( length >= 3 ) { - length -= 3; - - d2 = vec_ld(32,data); - d1 = vec_ld(16,data); - d0 = vec_ld(0,data); - - while( length >= 3 ) { - t0 = vec_perm(d0,d1,p[0]); - t1 = vec_perm(d1,d0,p[1]); - t2 = vec_perm(d2,d1,p[2]); - t1 = vec_perm(t1,d2,p[3]); - - vec_st(t0,0,newdata); - vec_st(t1,16,newdata); - vec_st(t2,32,newdata); - - length -= 3; - data += 16*3; - newdata += 16*3; - - d2 = vec_ld(32,data); - d1 = vec_ld(16,data); - d0 = vec_ld(0,data); - } - t0 = vec_perm(d0,d1,p[0]); - t1 = vec_perm(d1,d0,p[1]); - t2 = vec_perm(d2,d1,p[2]); - t1 = vec_perm(t1,d2,p[3]); - - vec_st(t0,0,newdata); - vec_st(t1,16,newdata); - vec_st(t2,32,newdata); - } - - if( length == 2 ) { - d0 = vec_ld(0,data); - d1 = vec_ld(16,data); - - t0 = vec_perm(d0,d1,p[0]); - t1 = vec_perm(d1,d0,p[1]); - - vec_st(t0,0,newdata); - vec_st(t1,16,newdata); - } else if( length == 1 ) { - d0 = vec_ld(0,data); - t0 = vec_perm(d0,d0,p[0]); - vec_st(t0,0,newdata); - } -} - -static inline void abcd2cbad_internal( register const vector unsigned char p, unsigned char *data, unsigned int length, unsigned char *newdata ) { - register vector unsigned char d0,d1,d2,z; - z = vec_splat_u8(0); - - length = eround16(length); - - if( length >= 3 ) { - length -= 3; - - d2 = vec_ld(32,data); - d1 = vec_ld(16,data); - d0 = vec_ld(0,data); - - while( length >= 3 ) { - d0 = vec_perm(d0,z,p); - d1 = vec_perm(d1,z,p); - d2 = vec_perm(d2,z,p); - - vec_st(d0,0,newdata); - vec_st(d1,16,newdata); - vec_st(d2,32,newdata); - - length -= 3; - data += 16*3; - newdata += 16*3; - - d2 = vec_ld(32,data); - d1 = vec_ld(16,data); - d0 = vec_ld(0,data); - } - d0 = vec_perm(d0,z,p); - d1 = vec_perm(d1,z,p); - d2 = vec_perm(d2,z,p); - - vec_st(d0,0,newdata); - vec_st(d1,16,newdata); - vec_st(d2,32,newdata); - } - - if( length == 2 ) { - d0 = vec_ld(0,data); - d1 = vec_ld(16,data); - - d0 = vec_perm(d0,z,p); - d1 = vec_perm(d1,z,p); - - vec_st(d0,0,newdata); - vec_st(d1,16,newdata); - } else if( length == 1 ) { - d0 = vec_ld(0,data); - d0 = vec_perm(d0,d0,z); - vec_st(d0,0,newdata); - } -} - -// Format conversion function -void abc2cba_byte( ILubyte *data, ILuint length, ILubyte *newdata ) { - const vector unsigned char p[4] = -{ (vector unsigned char)(0x02,0x01,0x00,0x05,0x04,0x03,0x08,0x07,0x06,0x0B,0x0A,0x09,0x0E,0x0D,0x0C,0x11), - (vector unsigned char)(0x00,0x10,0x04,0x03,0x02,0x07,0x06,0x05,0x0A,0x09,0x08,0x0D,0x0C,0x0B,0x0E,0x0F), - (vector unsigned char)(0x1E,0x03,0x02,0x01,0x06,0x05,0x04,0x09,0x08,0x07,0x0C,0x0B,0x0A,0x0F,0x0E,0x0D), - (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x10,0x0F)}; - abc2cba_internal(p,data,length,newdata); -} - -void abc2cba_short( ILushort *data, ILuint length, ILushort *newdata ) { - const vector unsigned char p[4] = -{ (vector unsigned char)(0x04,0x05,0x02,0x03,0x00,0x01,0x0A,0x0B,0x08,0x09,0x06,0x07,0x10,0x11,0x0E,0x0F), - (vector unsigned char)(0x1C,0x1D,0x06,0x07,0x04,0x05,0x02,0x03,0x0C,0x0D,0x0A,0x0B,0x08,0x09,0x0E,0x0F), - (vector unsigned char)(0x00,0x01,0x1E,0x1F,0x08,0x09,0x06,0x07,0x04,0x05,0x0E,0x0F,0x0C,0x0D,0x0A,0x0B), - (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x12,0x13)}; - abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); -} - -void abc2cba_int( ILuint *data, ILuint length, ILuint *newdata ) { - const vector unsigned char p[4] = -{ (vector unsigned char)(0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x14,0x15,0x16,0x17), - (vector unsigned char)(0x00,0x01,0x02,0x03,0x1C,0x1D,0x1E,0x1F,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F), - (vector unsigned char)(0x18,0x19,0x1A,0x1B,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07), - (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x0C,0x0D,0x0E,0x0F)}; - abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); -} - -void abc2cba_double( ILdouble *data, ILuint length, ILdouble *newdata ) { - const vector unsigned char p[4] = -{ (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F), - (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F), - (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F), - (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F)}; - abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); -} - -void abcd2cbad_byte( ILubyte *data, ILuint length, ILubyte *newdata ) { - const vector unsigned char p = (vector unsigned char)(0x02,0x01,0x00,0x03,0x06,0x05,0x04,0x07,0x0A,0x09,0x08,0x0B, 0x0E,0x0D,0x0C,0x0F); - abcd2cbad_internal(p,data,length,newdata); -} - -void abcd2cbad_short( ILushort *data, ILuint length, ILushort *newdata ) { - const vector unsigned char p = (vector unsigned char)(0x04,0x05,0x02,0x03,0x00,0x01,0x06,0x07,0x0C,0x0D,0x0A,0x0B,0x08,0x09,0x0E,0x0F); - abcd2cbad_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); -} - -void abcd2cbad_int( ILuint *data, ILuint length, ILuint *newdata ) { - const vector unsigned char p = (vector unsigned char)(0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x0C,0x0D,0x0E,0x0F); - abcd2cbad_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); -} - -void abcd2cbad_double( ILdouble *tdata, ILuint length, ILdouble *tnewdata ) { - register ILubyte *data = (ILubyte*)tdata; - register ILubyte *newdata = (ILubyte*)tnewdata; - const vector unsigned char p = (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F); - register vector unsigned char d0,d1,d2,d3,t0,t1,t2,t3; - - length = eround16(length); - - if( length >= 4 ) { - length -= 4; - - d3 = vec_ld(48,data); - d2 = vec_ld(32,data); - d1 = vec_ld(16,data); - d0 = vec_ld(0,data); - - while( length >= 4 ) { - t0 = vec_perm(d0,d1,p); - t1 = vec_perm(d1,d0,p); - t2 = vec_perm(d2,d3,p); - t3 = vec_perm(d3,d2,p); - - vec_st(t0,0,newdata); - vec_st(t1,16,newdata); - vec_st(t2,32,newdata); - vec_st(t3,48,newdata); - - length -= 4; - data += 16*4; - newdata += 16*4; - - d3 = vec_ld(48,data); - d2 = vec_ld(32,data); - d1 = vec_ld(16,data); - d0 = vec_ld(0,data); - } - t0 = vec_perm(d0,d1,p); - t1 = vec_perm(d1,d0,p); - t2 = vec_perm(d2,d3,p); - t3 = vec_perm(d3,d2,p); - - vec_st(d0,0,newdata); - vec_st(d1,16,newdata); - vec_st(d2,32,newdata); - vec_st(d3,48,newdata); - } - - if( length == 2 ) { - d0 = vec_ld(0,data); - d1 = vec_ld(16,data); - - t0 = vec_perm(d0,d1,p); - t1 = vec_perm(d1,d0,p); - - vec_st(t0,0,newdata); - vec_st(t1,16,newdata); - } -} - -#endif diff --git a/DevIL/src-IL/src/altivec_typeconversion.cpp b/DevIL/src-IL/src/altivec_typeconversion.cpp new file mode 100644 index 00000000..b620066e --- /dev/null +++ b/DevIL/src-IL/src/altivec_typeconversion.cpp @@ -0,0 +1,230 @@ +#ifdef HAVE_CONFIG_H +#include +#endif //HAVE_CONFIG_H + +#ifdef ALTIVEC_GCC +#include "altivec_typeconversion.h" + +static inline void abc2cba_internal( register const vector unsigned char p[4], unsigned char *data, register unsigned int length, unsigned char *newdata ) { + register vector unsigned char d0,d1,d2,t0,t1,t2; + + length = eround16(length); + + if( length >= 3 ) { + length -= 3; + + d2 = vec_ld(32,data); + d1 = vec_ld(16,data); + d0 = vec_ld(0,data); + + while( length >= 3 ) { + t0 = vec_perm(d0,d1,p[0]); + t1 = vec_perm(d1,d0,p[1]); + t2 = vec_perm(d2,d1,p[2]); + t1 = vec_perm(t1,d2,p[3]); + + vec_st(t0,0,newdata); + vec_st(t1,16,newdata); + vec_st(t2,32,newdata); + + length -= 3; + data += 16*3; + newdata += 16*3; + + d2 = vec_ld(32,data); + d1 = vec_ld(16,data); + d0 = vec_ld(0,data); + } + t0 = vec_perm(d0,d1,p[0]); + t1 = vec_perm(d1,d0,p[1]); + t2 = vec_perm(d2,d1,p[2]); + t1 = vec_perm(t1,d2,p[3]); + + vec_st(t0,0,newdata); + vec_st(t1,16,newdata); + vec_st(t2,32,newdata); + } + + if( length == 2 ) { + d0 = vec_ld(0,data); + d1 = vec_ld(16,data); + + t0 = vec_perm(d0,d1,p[0]); + t1 = vec_perm(d1,d0,p[1]); + + vec_st(t0,0,newdata); + vec_st(t1,16,newdata); + } else if( length == 1 ) { + d0 = vec_ld(0,data); + t0 = vec_perm(d0,d0,p[0]); + vec_st(t0,0,newdata); + } +} + +static inline void abcd2cbad_internal( register const vector unsigned char p, unsigned char *data, unsigned int length, unsigned char *newdata ) { + register vector unsigned char d0,d1,d2,z; + z = vec_splat_u8(0); + + length = eround16(length); + + if( length >= 3 ) { + length -= 3; + + d2 = vec_ld(32,data); + d1 = vec_ld(16,data); + d0 = vec_ld(0,data); + + while( length >= 3 ) { + d0 = vec_perm(d0,z,p); + d1 = vec_perm(d1,z,p); + d2 = vec_perm(d2,z,p); + + vec_st(d0,0,newdata); + vec_st(d1,16,newdata); + vec_st(d2,32,newdata); + + length -= 3; + data += 16*3; + newdata += 16*3; + + d2 = vec_ld(32,data); + d1 = vec_ld(16,data); + d0 = vec_ld(0,data); + } + d0 = vec_perm(d0,z,p); + d1 = vec_perm(d1,z,p); + d2 = vec_perm(d2,z,p); + + vec_st(d0,0,newdata); + vec_st(d1,16,newdata); + vec_st(d2,32,newdata); + } + + if( length == 2 ) { + d0 = vec_ld(0,data); + d1 = vec_ld(16,data); + + d0 = vec_perm(d0,z,p); + d1 = vec_perm(d1,z,p); + + vec_st(d0,0,newdata); + vec_st(d1,16,newdata); + } else if( length == 1 ) { + d0 = vec_ld(0,data); + d0 = vec_perm(d0,d0,z); + vec_st(d0,0,newdata); + } +} + +// Format conversion function +void abc2cba_byte( ILubyte *data, ILuint length, ILubyte *newdata ) { + const vector unsigned char p[4] = +{ (vector unsigned char)(0x02,0x01,0x00,0x05,0x04,0x03,0x08,0x07,0x06,0x0B,0x0A,0x09,0x0E,0x0D,0x0C,0x11), + (vector unsigned char)(0x00,0x10,0x04,0x03,0x02,0x07,0x06,0x05,0x0A,0x09,0x08,0x0D,0x0C,0x0B,0x0E,0x0F), + (vector unsigned char)(0x1E,0x03,0x02,0x01,0x06,0x05,0x04,0x09,0x08,0x07,0x0C,0x0B,0x0A,0x0F,0x0E,0x0D), + (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x10,0x0F)}; + abc2cba_internal(p,data,length,newdata); +} + +void abc2cba_short( ILushort *data, ILuint length, ILushort *newdata ) { + const vector unsigned char p[4] = +{ (vector unsigned char)(0x04,0x05,0x02,0x03,0x00,0x01,0x0A,0x0B,0x08,0x09,0x06,0x07,0x10,0x11,0x0E,0x0F), + (vector unsigned char)(0x1C,0x1D,0x06,0x07,0x04,0x05,0x02,0x03,0x0C,0x0D,0x0A,0x0B,0x08,0x09,0x0E,0x0F), + (vector unsigned char)(0x00,0x01,0x1E,0x1F,0x08,0x09,0x06,0x07,0x04,0x05,0x0E,0x0F,0x0C,0x0D,0x0A,0x0B), + (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x12,0x13)}; + abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); +} + +void abc2cba_int( ILuint *data, ILuint length, ILuint *newdata ) { + const vector unsigned char p[4] = +{ (vector unsigned char)(0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x14,0x15,0x16,0x17), + (vector unsigned char)(0x00,0x01,0x02,0x03,0x1C,0x1D,0x1E,0x1F,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F), + (vector unsigned char)(0x18,0x19,0x1A,0x1B,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07), + (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x0C,0x0D,0x0E,0x0F)}; + abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); +} + +void abc2cba_double( ILdouble *data, ILuint length, ILdouble *newdata ) { + const vector unsigned char p[4] = +{ (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F), + (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F), + (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F), + (vector unsigned char)(0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F)}; + abc2cba_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); +} + +void abcd2cbad_byte( ILubyte *data, ILuint length, ILubyte *newdata ) { + const vector unsigned char p = (vector unsigned char)(0x02,0x01,0x00,0x03,0x06,0x05,0x04,0x07,0x0A,0x09,0x08,0x0B, 0x0E,0x0D,0x0C,0x0F); + abcd2cbad_internal(p,data,length,newdata); +} + +void abcd2cbad_short( ILushort *data, ILuint length, ILushort *newdata ) { + const vector unsigned char p = (vector unsigned char)(0x04,0x05,0x02,0x03,0x00,0x01,0x06,0x07,0x0C,0x0D,0x0A,0x0B,0x08,0x09,0x0E,0x0F); + abcd2cbad_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); +} + +void abcd2cbad_int( ILuint *data, ILuint length, ILuint *newdata ) { + const vector unsigned char p = (vector unsigned char)(0x08,0x09,0x0A,0x0B,0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x0C,0x0D,0x0E,0x0F); + abcd2cbad_internal(p,(ILubyte*)data,length,(ILubyte*)newdata); +} + +void abcd2cbad_double( ILdouble *tdata, ILuint length, ILdouble *tnewdata ) { + register ILubyte *data = (ILubyte*)tdata; + register ILubyte *newdata = (ILubyte*)tnewdata; + const vector unsigned char p = (vector unsigned char)(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F); + register vector unsigned char d0,d1,d2,d3,t0,t1,t2,t3; + + length = eround16(length); + + if( length >= 4 ) { + length -= 4; + + d3 = vec_ld(48,data); + d2 = vec_ld(32,data); + d1 = vec_ld(16,data); + d0 = vec_ld(0,data); + + while( length >= 4 ) { + t0 = vec_perm(d0,d1,p); + t1 = vec_perm(d1,d0,p); + t2 = vec_perm(d2,d3,p); + t3 = vec_perm(d3,d2,p); + + vec_st(t0,0,newdata); + vec_st(t1,16,newdata); + vec_st(t2,32,newdata); + vec_st(t3,48,newdata); + + length -= 4; + data += 16*4; + newdata += 16*4; + + d3 = vec_ld(48,data); + d2 = vec_ld(32,data); + d1 = vec_ld(16,data); + d0 = vec_ld(0,data); + } + t0 = vec_perm(d0,d1,p); + t1 = vec_perm(d1,d0,p); + t2 = vec_perm(d2,d3,p); + t3 = vec_perm(d3,d2,p); + + vec_st(d0,0,newdata); + vec_st(d1,16,newdata); + vec_st(d2,32,newdata); + vec_st(d3,48,newdata); + } + + if( length == 2 ) { + d0 = vec_ld(0,data); + d1 = vec_ld(16,data); + + t0 = vec_perm(d0,d1,p); + t1 = vec_perm(d1,d0,p); + + vec_st(t0,0,newdata); + vec_st(t1,16,newdata); + } +} + +#endif diff --git a/DevIL/src-IL/src/il_alloc.c b/DevIL/src-IL/src/il_alloc.c deleted file mode 100644 index d41103a8..00000000 --- a/DevIL/src-IL/src/il_alloc.c +++ /dev/null @@ -1,287 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Last modified: 08/17/2009 -// -// Filename: src-IL/src/il_alloc.c -// -// Description: Memory allocation functions -// -//----------------------------------------------------------------------------- - - -#define __ALLOC_C - -// Memory leak detection -#ifdef _WIN32 - #ifdef _DEBUG - #define _CRTDBG_MAP_ALLOC - #include - #ifndef _WIN32_WCE // Does not have this header. - #include - #endif - #endif -#endif//_WIN32 - -#include "il_internal.h" -#include -#include - -#ifdef MM_MALLOC -#include -#endif - -static void ILAPIENTRY DefaultFreeFunc(const void * CONST_RESTRICT Ptr); -static void* ILAPIENTRY DefaultAllocFunc(const ILsizei Size); - -static mAlloc ialloc_ptr = DefaultAllocFunc; -static mFree ifree_ptr = DefaultFreeFunc; - -/*** Vector Allocation/Deallocation Function ***/ -#ifdef VECTORMEM -void *vec_malloc(const ILsizei size) -{ - const ILsizei _size = size % 16 > 0 ? size + 16 - (size % 16) : size; // align size value - -#ifdef MM_MALLOC - return _mm_malloc(_size,16); -#else -#ifdef VALLOC - return valloc( _size ); -#else -#ifdef POSIX_MEMALIGN - char *buffer; - return posix_memalign((void**)&buffer, 16, _size) == 0 ? buffer : NULL; -#else -#ifdef MEMALIGN - return memalign( 16, _size ); -#else - // Memalign hack from ffmpeg for MinGW - void *ptr; - int diff; - ptr = malloc(_size+16+1); - diff= ((-(int)ptr - 1)&15) + 1; - ptr = (void*)(((char*)ptr)+diff); - ((char*)ptr)[-1]= diff; - return ptr; -#endif //MEMALIGN -#endif //POSIX_MEMALIGN -#endif //VALLOC -#endif //MM_MALLOC -} - -void *ivec_align_buffer(void *buffer, const ILsizei size) -{ - if( (ILsizei)buffer % 16 != 0 ) { - void *aligned_buffer = vec_malloc( size ); - memcpy( aligned_buffer, buffer, size ); - ifree( buffer ); - return aligned_buffer; - } - return buffer; -} -#endif - - -/*** Allocation/Deallocation Function ***/ -void* ILAPIENTRY ialloc(const ILsizei Size) -{ - void *Ptr = ialloc_ptr(Size); - if (Ptr == NULL) - ilSetError(IL_OUT_OF_MEMORY); - return Ptr; -} - -void ILAPIENTRY ifree(const void * CONST_RESTRICT Ptr) -{ - if (Ptr == NULL) - return; - ifree_ptr(Ptr); - return; -} - -void* ILAPIENTRY icalloc(const ILsizei Size, const ILsizei Num) -{ - void *Ptr = ialloc(Size * Num); - if (Ptr == NULL) - return Ptr; - imemclear(Ptr, Size * Num); - return Ptr; -} - -/*** Default Allocation/Deallocation Function ***/ -static void* ILAPIENTRY DefaultAllocFunc(const ILsizei Size) -{ -#ifdef VECTORMEM - return (void*)vec_malloc(Size); -#else - return malloc(Size); -#endif //VECTORMEM -} - -static void ILAPIENTRY DefaultFreeFunc(const void * CONST_RESTRICT ptr) -{ - if (ptr) - { -#if defined(VECTORMEM) & defined(MM_MALLOC) - _mm_free((void*)ptr); -#else -#if defined(VECTORMEM) & !defined(POSIX_MEMALIGN) & !defined(VALLOC) & !defined(MEMALIGN) & !defined(MM_MALLOC) - free(((char*)ptr) - ((char*)ptr)[-1]); -#else - free((void*)ptr); -#endif //OTHERS... -#endif //MM_MALLOC - } -} - -/*** Manipulate Allocation/Deallocation Function ***/ -void ILAPIENTRY ilResetMemory() // Deprecated -{ - ialloc_ptr = DefaultAllocFunc; - ifree_ptr = DefaultFreeFunc; -} - -void ILAPIENTRY ilSetMemory(mAlloc AllocFunc, mFree FreeFunc) -{ - ialloc_ptr = AllocFunc == NULL ? DefaultAllocFunc : AllocFunc; - ifree_ptr = FreeFunc == NULL ? DefaultFreeFunc : FreeFunc; -} - - -/*#if defined(_WIN32) && defined(_MEM_DEBUG) -#include - -int bAtexit = 0; - - -typedef struct ALLOC_INFO -{ - unsigned long address; - unsigned long size; - char file[64]; - unsigned long line; - struct ALLOC_INFO *Next; -} ALLOC_INFO; -ALLOC_INFO *AllocList; - - -void AddTrack(unsigned long addr, unsigned long size, const char *file, unsigned long line) -{ - ALLOC_INFO *Temp; - - if (AllocList == NULL) { - AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO)); // Just assume it succeeds. - AllocList->address = addr; - AllocList->size = size; - AllocList->line = line; - strncpy(AllocList->file, file, 63); - AllocList->Next = NULL; - } - else { - Temp = AllocList; - AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO)); // Just assume it succeeds. - AllocList->address = addr; - AllocList->size = size; - AllocList->line = line; - strncpy(AllocList->file, file, 63); - AllocList->Next = Temp; - } - - return; -} - - -void RemoveTrack(unsigned long addr) -{ - ALLOC_INFO *Temp, *Prev; - - Temp = AllocList; - Prev = NULL; - - if (Temp == NULL) - return; - - while (Temp != NULL) { - if (Temp->address == addr) { - if (Prev == NULL) { - AllocList = Temp->Next; - free(Temp); - } - else { - Prev->Next = Temp->Next; - free(Temp); - } - break; - } - Prev = Temp; - Temp = Temp->Next; - } - - return; -} - - -void DumpUnfreed(void) -{ - unsigned long TotalSize = 0; - char buf[1024]; - ALLOC_INFO *i = AllocList; - - OutputDebugString("DevIL Unfreed Information:\n"); - while (i != NULL) { - sprintf(buf, "%s(%d) : %d bytes unfreed at %d\n", i->file, i->line, i->size, i->address); - OutputDebugString(buf); - TotalSize += i->size; - - AllocList = i->Next; - free(i); - i = AllocList; - } - - sprintf(buf, "-----------------------------------------------------------\n"); - OutputDebugString(buf); - sprintf(buf, "Total Unfreed: %d bytes\n\n\n", TotalSize); - OutputDebugString(buf); -} - -void AddToAtexit() -{ - if (bAtexit) - return; - atexit(DumpUnfreed); - bAtexit = 1; -} - -void *c_alloc(unsigned long size, unsigned long num, const char *file, unsigned long line) -{ - void *ptr; - ptr = calloc(size, num); - if (!ptr) - return NULL; - AddToAtexit(); - AddTrack((unsigned long)ptr, size * num, file, line); - return ptr; -} - - -void *m_alloc(unsigned long size, const char *file, unsigned long line) -{ - void *ptr; - ptr = malloc(size); - if (!ptr) - return NULL; - AddToAtexit(); - AddTrack((unsigned long)ptr, size, file, line); - return ptr; -} - - -void f_ree(void *ptr) -{ - RemoveTrack((unsigned long)ptr); - free(ptr); - return; -} - -#endif//defined(_WIN32) && defined(_MEM_DEBUG)*/ diff --git a/DevIL/src-IL/src/il_alloc.cpp b/DevIL/src-IL/src/il_alloc.cpp new file mode 100644 index 00000000..d41103a8 --- /dev/null +++ b/DevIL/src-IL/src/il_alloc.cpp @@ -0,0 +1,287 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Last modified: 08/17/2009 +// +// Filename: src-IL/src/il_alloc.c +// +// Description: Memory allocation functions +// +//----------------------------------------------------------------------------- + + +#define __ALLOC_C + +// Memory leak detection +#ifdef _WIN32 + #ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #ifndef _WIN32_WCE // Does not have this header. + #include + #endif + #endif +#endif//_WIN32 + +#include "il_internal.h" +#include +#include + +#ifdef MM_MALLOC +#include +#endif + +static void ILAPIENTRY DefaultFreeFunc(const void * CONST_RESTRICT Ptr); +static void* ILAPIENTRY DefaultAllocFunc(const ILsizei Size); + +static mAlloc ialloc_ptr = DefaultAllocFunc; +static mFree ifree_ptr = DefaultFreeFunc; + +/*** Vector Allocation/Deallocation Function ***/ +#ifdef VECTORMEM +void *vec_malloc(const ILsizei size) +{ + const ILsizei _size = size % 16 > 0 ? size + 16 - (size % 16) : size; // align size value + +#ifdef MM_MALLOC + return _mm_malloc(_size,16); +#else +#ifdef VALLOC + return valloc( _size ); +#else +#ifdef POSIX_MEMALIGN + char *buffer; + return posix_memalign((void**)&buffer, 16, _size) == 0 ? buffer : NULL; +#else +#ifdef MEMALIGN + return memalign( 16, _size ); +#else + // Memalign hack from ffmpeg for MinGW + void *ptr; + int diff; + ptr = malloc(_size+16+1); + diff= ((-(int)ptr - 1)&15) + 1; + ptr = (void*)(((char*)ptr)+diff); + ((char*)ptr)[-1]= diff; + return ptr; +#endif //MEMALIGN +#endif //POSIX_MEMALIGN +#endif //VALLOC +#endif //MM_MALLOC +} + +void *ivec_align_buffer(void *buffer, const ILsizei size) +{ + if( (ILsizei)buffer % 16 != 0 ) { + void *aligned_buffer = vec_malloc( size ); + memcpy( aligned_buffer, buffer, size ); + ifree( buffer ); + return aligned_buffer; + } + return buffer; +} +#endif + + +/*** Allocation/Deallocation Function ***/ +void* ILAPIENTRY ialloc(const ILsizei Size) +{ + void *Ptr = ialloc_ptr(Size); + if (Ptr == NULL) + ilSetError(IL_OUT_OF_MEMORY); + return Ptr; +} + +void ILAPIENTRY ifree(const void * CONST_RESTRICT Ptr) +{ + if (Ptr == NULL) + return; + ifree_ptr(Ptr); + return; +} + +void* ILAPIENTRY icalloc(const ILsizei Size, const ILsizei Num) +{ + void *Ptr = ialloc(Size * Num); + if (Ptr == NULL) + return Ptr; + imemclear(Ptr, Size * Num); + return Ptr; +} + +/*** Default Allocation/Deallocation Function ***/ +static void* ILAPIENTRY DefaultAllocFunc(const ILsizei Size) +{ +#ifdef VECTORMEM + return (void*)vec_malloc(Size); +#else + return malloc(Size); +#endif //VECTORMEM +} + +static void ILAPIENTRY DefaultFreeFunc(const void * CONST_RESTRICT ptr) +{ + if (ptr) + { +#if defined(VECTORMEM) & defined(MM_MALLOC) + _mm_free((void*)ptr); +#else +#if defined(VECTORMEM) & !defined(POSIX_MEMALIGN) & !defined(VALLOC) & !defined(MEMALIGN) & !defined(MM_MALLOC) + free(((char*)ptr) - ((char*)ptr)[-1]); +#else + free((void*)ptr); +#endif //OTHERS... +#endif //MM_MALLOC + } +} + +/*** Manipulate Allocation/Deallocation Function ***/ +void ILAPIENTRY ilResetMemory() // Deprecated +{ + ialloc_ptr = DefaultAllocFunc; + ifree_ptr = DefaultFreeFunc; +} + +void ILAPIENTRY ilSetMemory(mAlloc AllocFunc, mFree FreeFunc) +{ + ialloc_ptr = AllocFunc == NULL ? DefaultAllocFunc : AllocFunc; + ifree_ptr = FreeFunc == NULL ? DefaultFreeFunc : FreeFunc; +} + + +/*#if defined(_WIN32) && defined(_MEM_DEBUG) +#include + +int bAtexit = 0; + + +typedef struct ALLOC_INFO +{ + unsigned long address; + unsigned long size; + char file[64]; + unsigned long line; + struct ALLOC_INFO *Next; +} ALLOC_INFO; +ALLOC_INFO *AllocList; + + +void AddTrack(unsigned long addr, unsigned long size, const char *file, unsigned long line) +{ + ALLOC_INFO *Temp; + + if (AllocList == NULL) { + AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO)); // Just assume it succeeds. + AllocList->address = addr; + AllocList->size = size; + AllocList->line = line; + strncpy(AllocList->file, file, 63); + AllocList->Next = NULL; + } + else { + Temp = AllocList; + AllocList = (ALLOC_INFO*)malloc(sizeof(ALLOC_INFO)); // Just assume it succeeds. + AllocList->address = addr; + AllocList->size = size; + AllocList->line = line; + strncpy(AllocList->file, file, 63); + AllocList->Next = Temp; + } + + return; +} + + +void RemoveTrack(unsigned long addr) +{ + ALLOC_INFO *Temp, *Prev; + + Temp = AllocList; + Prev = NULL; + + if (Temp == NULL) + return; + + while (Temp != NULL) { + if (Temp->address == addr) { + if (Prev == NULL) { + AllocList = Temp->Next; + free(Temp); + } + else { + Prev->Next = Temp->Next; + free(Temp); + } + break; + } + Prev = Temp; + Temp = Temp->Next; + } + + return; +} + + +void DumpUnfreed(void) +{ + unsigned long TotalSize = 0; + char buf[1024]; + ALLOC_INFO *i = AllocList; + + OutputDebugString("DevIL Unfreed Information:\n"); + while (i != NULL) { + sprintf(buf, "%s(%d) : %d bytes unfreed at %d\n", i->file, i->line, i->size, i->address); + OutputDebugString(buf); + TotalSize += i->size; + + AllocList = i->Next; + free(i); + i = AllocList; + } + + sprintf(buf, "-----------------------------------------------------------\n"); + OutputDebugString(buf); + sprintf(buf, "Total Unfreed: %d bytes\n\n\n", TotalSize); + OutputDebugString(buf); +} + +void AddToAtexit() +{ + if (bAtexit) + return; + atexit(DumpUnfreed); + bAtexit = 1; +} + +void *c_alloc(unsigned long size, unsigned long num, const char *file, unsigned long line) +{ + void *ptr; + ptr = calloc(size, num); + if (!ptr) + return NULL; + AddToAtexit(); + AddTrack((unsigned long)ptr, size * num, file, line); + return ptr; +} + + +void *m_alloc(unsigned long size, const char *file, unsigned long line) +{ + void *ptr; + ptr = malloc(size); + if (!ptr) + return NULL; + AddToAtexit(); + AddTrack((unsigned long)ptr, size, file, line); + return ptr; +} + + +void f_ree(void *ptr) +{ + RemoveTrack((unsigned long)ptr); + free(ptr); + return; +} + +#endif//defined(_WIN32) && defined(_MEM_DEBUG)*/ diff --git a/DevIL/src-IL/src/il_bits.c b/DevIL/src-IL/src/il_bits.c deleted file mode 100644 index 4e3ba7f4..00000000 --- a/DevIL/src-IL/src/il_bits.c +++ /dev/null @@ -1,185 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 08/14/2004 -// -// Filename: src-IL/src/il_bits.c -// -// Description: Implements a file class that reads/writes bits directly. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include "il_bits.h" - - -// Opens a BITFILE just like fopen opens a FILE. -/*BITFILE *bopen(const char *FileName, const char *Mode) -{ - BITFILE *ToReturn = NULL; - - if (FileName != NULL) { - ToReturn = (BITFILE*)ialloc(sizeof(BITFILE)); - if (ToReturn != NULL) { - iopenr((char*)FileName); - ToReturn->File = iGetFile(); - ToReturn->BitPos = 0; - ToReturn->ByteBitOff = 8; - ToReturn->Buff = 0; - } - } - - return ToReturn; -}*/ - - -// Converts a FILE to a BITFILE. -BITFILE *bfile(ILHANDLE File) -{ - BITFILE *ToReturn = NULL; - - if (File != NULL) { - ToReturn = (BITFILE*)ialloc(sizeof(BITFILE)); - if (ToReturn != NULL) { - ToReturn->File = File; - ToReturn->BitPos = itell() << 3; - ToReturn->ByteBitOff = 8; - ToReturn->Buff = 0; - } - } - - return ToReturn; -} - - -// Closes an open BITFILE and frees memory for it. -ILint bclose(BITFILE *BitFile) -{ - if (BitFile == NULL || BitFile->File == NULL) - return IL_EOF; - - // Removed 01-26-2008. The file will get closed later by - // the calling function. - //icloser(BitFile->File); - ifree(BitFile); - - return 0; -} - - -// Returns the current bit position of a BITFILE. -ILint btell(BITFILE *BitFile) -{ - return BitFile->BitPos; -} - - -// Seeks in a BITFILE just like fseek for FILE. -ILint bseek(BITFILE *BitFile, ILuint Offset, ILuint Mode) -{ - ILint KeepPos, Len; - - if (BitFile == NULL || BitFile->File == NULL) - return 1; - - switch (Mode) - { - case IL_SEEK_SET: - if (!iseek(Offset >> 3, Mode)) { - BitFile->BitPos = Offset; - BitFile->ByteBitOff = BitFile->BitPos % 8; - } - break; - case IL_SEEK_CUR: - if (!iseek(Offset >> 3, Mode)) { - BitFile->BitPos += Offset; - BitFile->ByteBitOff = BitFile->BitPos % 8; - } - break; - case IL_SEEK_END: - KeepPos = itell(); - iseek(0, IL_SEEK_END); - Len = itell(); - iseek(0, IL_SEEK_SET); - - if (!iseek(Offset >> 3, Mode)) { - BitFile->BitPos = (Len << 3) + Offset; - BitFile->ByteBitOff = BitFile->BitPos % 8; - } - - break; - - default: - return 1; - } - - return 0; -} - - -// hehe, "bread". It reads data into Buffer from the BITFILE, just like fread for FILE. -ILint bread(void *Buffer, ILuint Size, ILuint Number, BITFILE *BitFile) -{ - // Note that this function is somewhat useless: In binary image - // formats, there are some pad bits after each scanline. This - // function does not take that into account, so you must use bseek to - // skip the calculated value of bits. - - ILuint BuffPos = 0, Count = Size * Number; - - while (BuffPos < Count) { - if (BitFile->ByteBitOff < 0 || BitFile->ByteBitOff > 7) { - BitFile->ByteBitOff = 7; - if (iread(&BitFile->Buff, 1, 1) != 1) // Reached eof or error... - return BuffPos; - } - - *((ILubyte*)(Buffer) + BuffPos) = (ILubyte)!!(BitFile->Buff & (1 << BitFile->ByteBitOff)); - - BuffPos++; - BitFile->ByteBitOff--; - } - - return BuffPos; -} - - -// Reads bits and puts the first bit in the file as the highest in the return value. -ILuint breadVal(ILuint NumBits, BITFILE *BitFile) -{ - ILuint BuffPos = 0; - ILuint Buffer = 0; - - // Only returning up to 32 bits at one time - if (NumBits > 32) { - ilSetError(IL_INTERNAL_ERROR); - return 0; - } - - while (BuffPos < NumBits) { - Buffer <<= 1; - if (BitFile->ByteBitOff < 0 || BitFile->ByteBitOff > 7) { - BitFile->ByteBitOff = 7; - if (iread(&BitFile->Buff, 1, 1) != 1) // Reached eof or error... - return BuffPos; - } - - Buffer = Buffer + (ILubyte)!!(BitFile->Buff & (1 << BitFile->ByteBitOff)); - - BuffPos++; - BitFile->ByteBitOff--; - } - - return BuffPos; -} - - -// Not implemented yet. -/*ILint bwrite(void *Buffer, ILuint Size, ILuint Number, BITFILE *BitFile) -{ - - - return 0; -}*/ diff --git a/DevIL/src-IL/src/il_bits.cpp b/DevIL/src-IL/src/il_bits.cpp new file mode 100644 index 00000000..4e3ba7f4 --- /dev/null +++ b/DevIL/src-IL/src/il_bits.cpp @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 08/14/2004 +// +// Filename: src-IL/src/il_bits.c +// +// Description: Implements a file class that reads/writes bits directly. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include "il_bits.h" + + +// Opens a BITFILE just like fopen opens a FILE. +/*BITFILE *bopen(const char *FileName, const char *Mode) +{ + BITFILE *ToReturn = NULL; + + if (FileName != NULL) { + ToReturn = (BITFILE*)ialloc(sizeof(BITFILE)); + if (ToReturn != NULL) { + iopenr((char*)FileName); + ToReturn->File = iGetFile(); + ToReturn->BitPos = 0; + ToReturn->ByteBitOff = 8; + ToReturn->Buff = 0; + } + } + + return ToReturn; +}*/ + + +// Converts a FILE to a BITFILE. +BITFILE *bfile(ILHANDLE File) +{ + BITFILE *ToReturn = NULL; + + if (File != NULL) { + ToReturn = (BITFILE*)ialloc(sizeof(BITFILE)); + if (ToReturn != NULL) { + ToReturn->File = File; + ToReturn->BitPos = itell() << 3; + ToReturn->ByteBitOff = 8; + ToReturn->Buff = 0; + } + } + + return ToReturn; +} + + +// Closes an open BITFILE and frees memory for it. +ILint bclose(BITFILE *BitFile) +{ + if (BitFile == NULL || BitFile->File == NULL) + return IL_EOF; + + // Removed 01-26-2008. The file will get closed later by + // the calling function. + //icloser(BitFile->File); + ifree(BitFile); + + return 0; +} + + +// Returns the current bit position of a BITFILE. +ILint btell(BITFILE *BitFile) +{ + return BitFile->BitPos; +} + + +// Seeks in a BITFILE just like fseek for FILE. +ILint bseek(BITFILE *BitFile, ILuint Offset, ILuint Mode) +{ + ILint KeepPos, Len; + + if (BitFile == NULL || BitFile->File == NULL) + return 1; + + switch (Mode) + { + case IL_SEEK_SET: + if (!iseek(Offset >> 3, Mode)) { + BitFile->BitPos = Offset; + BitFile->ByteBitOff = BitFile->BitPos % 8; + } + break; + case IL_SEEK_CUR: + if (!iseek(Offset >> 3, Mode)) { + BitFile->BitPos += Offset; + BitFile->ByteBitOff = BitFile->BitPos % 8; + } + break; + case IL_SEEK_END: + KeepPos = itell(); + iseek(0, IL_SEEK_END); + Len = itell(); + iseek(0, IL_SEEK_SET); + + if (!iseek(Offset >> 3, Mode)) { + BitFile->BitPos = (Len << 3) + Offset; + BitFile->ByteBitOff = BitFile->BitPos % 8; + } + + break; + + default: + return 1; + } + + return 0; +} + + +// hehe, "bread". It reads data into Buffer from the BITFILE, just like fread for FILE. +ILint bread(void *Buffer, ILuint Size, ILuint Number, BITFILE *BitFile) +{ + // Note that this function is somewhat useless: In binary image + // formats, there are some pad bits after each scanline. This + // function does not take that into account, so you must use bseek to + // skip the calculated value of bits. + + ILuint BuffPos = 0, Count = Size * Number; + + while (BuffPos < Count) { + if (BitFile->ByteBitOff < 0 || BitFile->ByteBitOff > 7) { + BitFile->ByteBitOff = 7; + if (iread(&BitFile->Buff, 1, 1) != 1) // Reached eof or error... + return BuffPos; + } + + *((ILubyte*)(Buffer) + BuffPos) = (ILubyte)!!(BitFile->Buff & (1 << BitFile->ByteBitOff)); + + BuffPos++; + BitFile->ByteBitOff--; + } + + return BuffPos; +} + + +// Reads bits and puts the first bit in the file as the highest in the return value. +ILuint breadVal(ILuint NumBits, BITFILE *BitFile) +{ + ILuint BuffPos = 0; + ILuint Buffer = 0; + + // Only returning up to 32 bits at one time + if (NumBits > 32) { + ilSetError(IL_INTERNAL_ERROR); + return 0; + } + + while (BuffPos < NumBits) { + Buffer <<= 1; + if (BitFile->ByteBitOff < 0 || BitFile->ByteBitOff > 7) { + BitFile->ByteBitOff = 7; + if (iread(&BitFile->Buff, 1, 1) != 1) // Reached eof or error... + return BuffPos; + } + + Buffer = Buffer + (ILubyte)!!(BitFile->Buff & (1 << BitFile->ByteBitOff)); + + BuffPos++; + BitFile->ByteBitOff--; + } + + return BuffPos; +} + + +// Not implemented yet. +/*ILint bwrite(void *Buffer, ILuint Size, ILuint Number, BITFILE *BitFile) +{ + + + return 0; +}*/ diff --git a/DevIL/src-IL/src/il_blp.c b/DevIL/src-IL/src/il_blp.c deleted file mode 100755 index 24044519..00000000 --- a/DevIL/src-IL/src/il_blp.c +++ /dev/null @@ -1,736 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/14/2009 -// -// Filename: src-IL/src/il_blp.c -// -// Description: Reads from a Blizzard Texture (.blp). -// Specifications were found at http://www.wowwiki.com/BLP_files -// for BLP2 and from -// http://web.archive.org/web/20080117120549/magos.thejefffiles.com/War3ModelEditor/MagosBlpFormat.txt -// for BLP1. -// -//----------------------------------------------------------------------------- - -//@TODO: Add support for the BLP1 format as well. - -#include "il_internal.h" -#ifndef IL_NO_BLP -#include "il_dds.h" - - -typedef struct BLP1HEAD -{ - ILubyte Sig[4]; - ILuint Compression; // Texture type: 0 = JPG, 1 = Paletted - ILuint Flags; // #8 - Uses alpha channel (?) - ILuint Width; // Image width in pixels - ILuint Height; // Image height in pixels - ILuint PictureType; // 3 - Uncompressed index list + alpha list - // 4 - Uncompressed index list + alpha list - // 5 - Uncompressed index list - ILuint PictureSubType; // 1 - ??? - ILuint MipOffsets[16]; // The file offsets of each mipmap, 0 for unused - ILuint MipLengths[16]; // The length of each mipmap data block -} BLP1HEAD; - -typedef struct BLP2HEAD -{ - ILubyte Sig[4]; // "BLP2" signature - ILuint Type; // Texture type: 0 = JPG, 1 = DXTC - ILubyte Compression; // Compression mode: 1 = raw, 2 = DXTC - ILubyte AlphaBits; // 0, 1, or 8 - ILubyte AlphaType; // 0, 1, 7 or 8 - ILubyte HasMips; // 0 = no mips levels, 1 = has mips (number of levels determined by image size) - ILuint Width; // Image width in pixels - ILuint Height; // Image height in pixels - ILuint MipOffsets[16]; // The file offsets of each mipmap, 0 for unused - ILuint MipLengths[16]; // The length of each mipmap data block -} BLP2HEAD; - -// Data formats -#define BLP_TYPE_JPG 0 -#define BLP_TYPE_DXTC_RAW 1 -#define BLP_RAW 1 -#define BLP_DXTC 2 - -#define BLP_RAW_PLUS_ALPHA1 3 -#define BLP_RAW_PLUS_ALPHA2 4 -#define BLP_RAW_NO_ALPHA 5 - - -ILboolean iIsValidBlp2(void); -ILboolean iCheckBlp2(BLP2HEAD *Header); -ILboolean iLoadBlpInternal(void); -ILboolean iLoadBlp1(void); -ILboolean iCheckBlp1(BLP1HEAD *Header); -ILboolean iGetBlp1Head(BLP1HEAD *Header); - - -//! Checks if the file specified in FileName is a valid BLP file. -ILboolean ilIsValidBlp(ILconst_string FileName) -{ - ILHANDLE BlpFile; - ILboolean bBlp = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("blp"))) { - ilSetError(IL_INVALID_EXTENSION); - return bBlp; - } - - BlpFile = iopenr(FileName); - if (BlpFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bBlp; - } - - bBlp = ilIsValidBlpF(BlpFile); - icloser(BlpFile); - - return bBlp; -} - - -//! Checks if the ILHANDLE contains a valid BLP file at the current position. -ILboolean ilIsValidBlpF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidBlp2(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid BLP lump. -ILboolean ilIsValidBlpL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidBlp2(); -} - - -// Internal function used to get the BLP header from the current file. -ILboolean iGetBlp2Head(BLP2HEAD *Header) -{ - ILuint i; - - iread(Header->Sig, 1, 4); - Header->Type = GetLittleUInt(); - Header->Compression = igetc(); - Header->AlphaBits = igetc(); - Header->AlphaType = igetc(); - Header->HasMips = igetc(); - Header->Width = GetLittleUInt(); - Header->Height = GetLittleUInt(); - for (i = 0; i < 16; i++) - Header->MipOffsets[i] = GetLittleUInt(); - for (i = 0; i < 16; i++) - Header->MipLengths[i] = GetLittleUInt(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidBlp2(void) -{ - BLP2HEAD Header; - - if (!iGetBlp2Head(&Header)) - return IL_FALSE; - iseek(-148, IL_SEEK_CUR); - - return iCheckBlp2(&Header); -} - - -// Internal function used to check if the HEADER is a valid BLP header. -ILboolean iCheckBlp2(BLP2HEAD *Header) -{ - // The file signature is 'BLP2'. - if (strncmp(Header->Sig, "BLP2", 4)) - return IL_FALSE; - // Valid types are JPEG and DXTC. JPEG is not common, though. - // WoW only uses DXTC. - if (Header->Type != BLP_TYPE_JPG && Header->Type != BLP_TYPE_DXTC_RAW) - return IL_FALSE; - // For BLP_TYPE_DXTC_RAW, we can have RAW and DXTC compression. - if (Header->Compression != BLP_RAW && Header->Compression != BLP_DXTC) - return IL_FALSE; - // Alpha bits can only be 0, 1 and 8. - if (Header->AlphaBits != 0 && Header->AlphaBits != 1 && Header->AlphaBits != 8) - return IL_FALSE; - // Alpha type can only be 0, 1, 7 and 8. - if (Header->AlphaType != 0 && Header->AlphaType != 1 && Header->AlphaType != 7 && Header->AlphaType != 8) - return IL_FALSE; - // Width or height of 0 makes no sense. - if (Header->Width == 0 || Header->Height == 0) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a BLP file -ILboolean ilLoadBlp(ILconst_string FileName) -{ - ILHANDLE BlpFile; - ILboolean bBlp = IL_FALSE; - - BlpFile = iopenr(FileName); - if (BlpFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bBlp; - } - - bBlp = ilLoadBlpF(BlpFile); - icloser(BlpFile); - - return bBlp; -} - - -//! Reads an already-opened BLP file -ILboolean ilLoadBlpF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadBlpInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a BLP -ILboolean ilLoadBlpL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadBlpInternal(); -} - - -// Internal function used to load the BLP. -ILboolean iLoadBlpInternal(void) -{ - BLP2HEAD Header; - ILubyte *CompData; - ILimage *Image; - ILuint Mip, j, x, CompSize, AlphaSize, AlphaOff; - ILint y; - ILboolean BaseCreated = IL_FALSE; - ILubyte *DataAndAlpha = NULL, *Palette = NULL, AlphaMask; //, *JpegHeader, *JpegData; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetBlp2Head(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - if (!iCheckBlp2(&Header)) { - goto check_blp1; - } - -//@TODO: Remove this! - if (Header.Type != BLP_TYPE_DXTC_RAW) - return IL_FALSE; - - switch (Header.Compression) - { - case BLP_RAW: - for (Mip = 0; Mip < 16; Mip++) { // Possible maximum of 16 mipmaps - if (BaseCreated) { - if (Header.HasMips == 0) // Does not have mipmaps, so we are done. - break; - if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. - break; - if (Header.MipOffsets[Mip] == 0 || Header.MipLengths == 0) // No more mipmaps in the file. - break; - } - - switch (Header.AlphaBits) - { - case 0: - if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - Image = iCurImage; - BaseCreated = IL_TRUE; - - Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); // 256 entries of ARGB8888 values (1024). - if (Image->Pal.Palette == NULL) - return IL_FALSE; - Image->Pal.PalSize = 1024; - Image->Pal.PalType = IL_PAL_BGRA32; //@TODO: Find out if this is really BGRA data. - if (iread(Image->Pal.Palette, 1, 1024) != 1024) // Read in the palette. - return IL_FALSE; - } - else { - Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); - if (Image->Mipmaps == NULL) - return IL_FALSE; - - // Copy the palette from the first image before we change our Image pointer. - iCopyPalette(&Image->Mipmaps->Pal, &Image->Pal); - // Move to the next mipmap in the linked list. - Image = Image->Mipmaps; - } - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - // These two should be the same (tells us how much data is in the file for this mipmap level). - if (Header.MipLengths[Mip] != Image->SizeOfData) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - // Finally read in the image data. - iseek(Header.MipOffsets[Mip], IL_SEEK_SET); - if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) - return IL_FALSE; - break; - - case 1: - if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. - if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - Image = iCurImage; - BaseCreated = IL_TRUE; - - Palette = (ILubyte*)ialloc(256 * 4); - if (Palette == NULL) - return IL_FALSE; - - // Read in the palette. - if (iread(Palette, 1, 1024) != 1024) { - ifree(Palette); - return IL_FALSE; - } - - // We only allocate this once and reuse this buffer with every mipmap (since successive ones are smaller). - DataAndAlpha = (ILubyte*)ialloc(Image->Width * Image->Height); - if (DataAndAlpha == NULL) { - ifree(DataAndAlpha); - ifree(Palette); - return IL_FALSE; - } - } - else { - Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); - if (Image->Mipmaps == NULL) - return IL_FALSE; - - // Move to the next mipmap in the linked list. - Image = Image->Mipmaps; - } - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - // Determine the size of the alpha data following the color indices. - AlphaSize = Image->Width * Image->Height / 8; - if (AlphaSize == 0) - AlphaSize = 1; // Should never be 0. - // These two should be the same (tells us how much data is in the file for this mipmap level). - if (Header.MipLengths[Mip] != Image->SizeOfData / 4 + AlphaSize) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Seek to the data and read it. - iseek(Header.MipOffsets[Mip], IL_SEEK_SET); - if (iread(DataAndAlpha, Image->Width * Image->Height, 1) != 1) { - ifree(DataAndAlpha); - ifree(Palette); - return IL_FALSE; - } - - // Convert the color-indexed data to BGRX. - for (j = 0; j < Image->Width * Image->Height; j++) { - Image->Data[j*4] = Palette[DataAndAlpha[j]*4]; - Image->Data[j*4+1] = Palette[DataAndAlpha[j]*4+1]; - Image->Data[j*4+2] = Palette[DataAndAlpha[j]*4+2]; - } - - // Read in the alpha list. - if (iread(DataAndAlpha, AlphaSize, 1) != 1) { - ifree(DataAndAlpha); - ifree(Palette); - return IL_FALSE; - } - - AlphaMask = 0x01; // Lowest bit - AlphaOff = 0; - // The really strange thing about this alpha data is that it is upside-down when compared to the - // regular color-indexed data, so we have to flip it. - for (y = Image->Height - 1; y >= 0; y--) { - for (x = 0; x < Image->Width; x++) { - if (AlphaMask == 0) { // Shifting it past the highest bit makes it 0, since we only have 1 byte. - AlphaOff++; // Move along the alpha buffer. - AlphaMask = 0x01; // Reset the alpha mask. - } - // This is just 1-bit alpha, so it is either on or off. - Image->Data[Image->Bps * y + x * 4 + 3] = DataAndAlpha[AlphaOff] & AlphaMask ? 0xFF : 0x00; - AlphaMask <<= 1; - } - } - - break; - - default: - //@TODO: Accept any other alpha values? - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - } - - // Done, so we can finally free these two. - ifree(DataAndAlpha); - ifree(Palette); - - break; - - case BLP_DXTC: - for (Mip = 0; Mip < 16; Mip++) { // Possible maximum of 16 mipmaps - //@TODO: Other formats - //if (Header.AlphaBits == 0) - // if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - // return IL_FALSE; - if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. - if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - Image = iCurImage; - BaseCreated = IL_TRUE; - } - else { - if (Header.HasMips == 0) // Does not have mipmaps, so we are done. - break; - if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. - break; - if (Header.MipOffsets[Mip] == 0 || Header.MipLengths[Mip] == 0) // No more mipmaps in the file. - break; - - //@TODO: Other formats - // ilNewImageFull automatically changes widths and heights of 0 to 1, so we do not have to worry about it. - Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - if (Image->Mipmaps == NULL) - return IL_FALSE; - Image = Image->Mipmaps; - } - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - //@TODO: Only do the allocation once. - CompData = (ILubyte*)ialloc(Header.MipLengths[Mip]); - if (CompData == NULL) - return IL_FALSE; - - // Read in the compressed mipmap data. - iseek(Header.MipOffsets[Mip], IL_SEEK_SET); - if (iread(CompData, 1, Header.MipLengths[Mip]) != Header.MipLengths[Mip]) { - ifree(CompData); - return IL_FALSE; - } - - switch (Header.AlphaBits) - { - case 0: // DXT1 without alpha - case 1: // DXT1 with alpha - // Check to make sure that the MipLength reported is the size needed, so that - // DecompressDXT1 does not crash. - CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 8; - if (CompSize != Header.MipLengths[Mip]) { - ilSetError(IL_INVALID_FILE_HEADER); - ifree(CompData); - return IL_FALSE; - } - if (!DecompressDXT1(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - break; - - case 8: - // Check to make sure that the MipLength reported is the size needed, so that - // DecompressDXT3/5 do not crash. - CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 16; - if (CompSize != Header.MipLengths[Mip]) { - ifree(CompData); - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - switch (Header.AlphaType) - { - case 0: // All three of - case 1: // these refer to - case 8: // DXT3... - if (!DecompressDXT3(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - break; - - case 7: // DXT5 compression - if (!DecompressDXT5(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - break; - - //default: // Should already be checked by iCheckBlp2. - } - break; - //default: // Should already be checked by iCheckBlp2. - } - //@TODO: Save DXTC data. - ifree(CompData); - } - break; - //default: - } - - return ilFixImage(); - -check_blp1: - iseek(-148, IL_SEEK_CUR); // Go back the size of the BLP2 header, since we tried reading it. - return iLoadBlp1(); -} - - -ILboolean iGetBlp1Head(BLP1HEAD *Header) -{ - ILuint i; - - iread(Header->Sig, 1, 4); - Header->Compression = GetLittleUInt(); - Header->Flags = GetLittleUInt(); - Header->Width = GetLittleUInt(); - Header->Height = GetLittleUInt(); - Header->PictureType = GetLittleUInt(); - Header->PictureSubType = GetLittleUInt(); - for (i = 0; i < 16; i++) - Header->MipOffsets[i] = GetLittleUInt(); - for (i = 0; i < 16; i++) - Header->MipLengths[i] = GetLittleUInt(); - - return IL_TRUE; -} - - -ILboolean iCheckBlp1(BLP1HEAD *Header) -{ - // The file signature is 'BLP1'. - if (strncmp(Header->Sig, "BLP1", 4)) - return IL_FALSE; - // Valid types are JPEG and RAW. JPEG is not common, though. - if (Header->Compression != BLP_TYPE_JPG && Header->Compression != BLP_RAW) - return IL_FALSE; -//@TODO: Find out what Flags is for. - - // PictureType determines whether this has an alpha list. - if (Header->PictureType != BLP_RAW_PLUS_ALPHA1 && Header->PictureType != BLP_RAW_PLUS_ALPHA2 - && Header->PictureType != BLP_RAW_NO_ALPHA) - return IL_FALSE; - // Width or height of 0 makes no sense. - if (Header->Width == 0 || Header->Height == 0) - return IL_FALSE; - - return IL_TRUE; -} - - -ILboolean iLoadBlp1() -{ - BLP1HEAD Header; - ILubyte *DataAndAlpha, *Palette; - ILuint i; - ILimage *Image = iCurImage; - ILboolean BaseCreated = IL_FALSE; -#ifndef IL_NO_JPG - ILubyte *JpegHeader, *JpegData; - ILuint JpegHeaderSize; -#endif//IL_NO_JPG - - if (!iGetBlp1Head(&Header)) - return IL_FALSE; - if (!iCheckBlp1(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - //@TODO: Remove this. - i = 0; - - switch (Header.Compression) - { - case BLP_TYPE_JPG: -#ifdef IL_NO_JPG - // We can only do the Jpeg decoding if we do not have IL_NO_JPEG defined. - return IL_FALSE; -#else - JpegHeaderSize = GetLittleUInt(); - JpegHeader = (ILubyte*)ialloc(JpegHeaderSize); - if (JpegHeader == NULL) - return IL_FALSE; - // Read the shared Jpeg header. - if (iread(JpegHeader, 1, JpegHeaderSize) != JpegHeaderSize) { - ifree(JpegHeader); - return IL_FALSE; - } - - //for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps - //@TODO: Check return value? - iseek(Header.MipOffsets[i], IL_SEEK_SET); - JpegData = (ILubyte*)ialloc(JpegHeaderSize + Header.MipLengths[i]); - if (JpegData == NULL) { - ifree(JpegHeader); - return IL_FALSE; - } - memcpy(JpegData, JpegHeader, JpegHeaderSize); - if (iread(JpegData + JpegHeaderSize, Header.MipLengths[i], 1) != 1) - return IL_FALSE; - - // Just send the data straight to the Jpeg loader. - if (!ilLoadJpegL(JpegData, JpegHeaderSize + Header.MipLengths[i])) - return IL_FALSE; - - // The image data is in BGR(A) order, even though it is Jpeg-compressed. - if (Image->Format == IL_RGBA) - Image->Format = IL_BGRA; - if (Image->Format == IL_RGB) - Image->Format = IL_BGR; - - ifree(JpegData); - //} - ifree(JpegHeader); -#endif//IL_NO_JPG - break; - - case BLP_RAW: - switch (Header.PictureType) - { - // There is no alpha list, so we just read like a normal indexed image. - case BLP_RAW_NO_ALPHA: - for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps - if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - Image = iCurImage; - BaseCreated = IL_TRUE; - - // We have a BGRA palette. - Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); - if (Image->Pal.Palette == NULL) - return IL_FALSE; - Image->Pal.PalSize = 1024; - Image->Pal.PalType = IL_PAL_BGRA32; - - // Read in the palette ... - if (iread(Image->Pal.Palette, 1, 1024) != 1024) - return IL_FALSE; - } - else { - if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. - break; - if (Header.MipOffsets[i] == 0 || Header.MipLengths[i] == 0) // No more mipmaps in the file. - break; - - Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOR_INDEX, IL_UNSIGNED_BYTE, NULL); - if (Image->Mipmaps == NULL) - return IL_FALSE; - - // Copy the palette from the first image before we change our Image pointer. - Image->Mipmaps->Pal.Palette = (ILubyte*)ialloc(256 * 4); - if (Image->Mipmaps->Pal.Palette == NULL) - return IL_FALSE; - Image->Mipmaps->Pal.PalSize = 1024; - Image->Mipmaps->Pal.PalType = IL_PAL_BGRA32; - memcpy(Image->Mipmaps->Pal.Palette, Image->Pal.Palette, 1024); - - // Move to the next mipmap in the linked list. - Image = Image->Mipmaps; - } - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - // Seek to the data and read it. - iseek(Header.MipOffsets[i], IL_SEEK_SET); - if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) - return IL_FALSE; - } - break; - - // These cases are identical and have an alpha list following the image data. - case BLP_RAW_PLUS_ALPHA1: - case BLP_RAW_PLUS_ALPHA2: - // Create the image. - if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - - DataAndAlpha = (ILubyte*)ialloc(Header.Width * Header.Height); - Palette = (ILubyte*)ialloc(256 * 4); - if (DataAndAlpha == NULL || Palette == NULL) { - ifree(DataAndAlpha); - ifree(Palette); - return IL_FALSE; - } - - // Read in the data and the palette. - if (iread(Palette, 1, 1024) != 1024) { - ifree(Palette); - return IL_FALSE; - } - // Seek to the data and read it. - iseek(Header.MipOffsets[i], IL_SEEK_SET); - if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { - ifree(DataAndAlpha); - ifree(Palette); - return IL_FALSE; - } - - // Convert the color-indexed data to BGRX. - for (i = 0; i < Header.Width * Header.Height; i++) { - Image->Data[i*4] = Palette[DataAndAlpha[i]*4]; - Image->Data[i*4+1] = Palette[DataAndAlpha[i]*4+1]; - Image->Data[i*4+2] = Palette[DataAndAlpha[i]*4+2]; - } - - // Read in the alpha list. - if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { - ifree(DataAndAlpha); - ifree(Palette); - return IL_FALSE; - } - // Finally put the alpha data into the image data. - for (i = 0; i < Header.Width * Header.Height; i++) { - Image->Data[i*4+3] = DataAndAlpha[i]; - } - - ifree(DataAndAlpha); - ifree(Palette); - break; - } - break; - - //default: // Should already be checked by iCheckBlp1. - } - - // Set the origin (always upper left). - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - return ilFixImage(); -} - - -#endif//IL_NO_BLP diff --git a/DevIL/src-IL/src/il_blp.cpp b/DevIL/src-IL/src/il_blp.cpp new file mode 100755 index 00000000..24044519 --- /dev/null +++ b/DevIL/src-IL/src/il_blp.cpp @@ -0,0 +1,736 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/14/2009 +// +// Filename: src-IL/src/il_blp.c +// +// Description: Reads from a Blizzard Texture (.blp). +// Specifications were found at http://www.wowwiki.com/BLP_files +// for BLP2 and from +// http://web.archive.org/web/20080117120549/magos.thejefffiles.com/War3ModelEditor/MagosBlpFormat.txt +// for BLP1. +// +//----------------------------------------------------------------------------- + +//@TODO: Add support for the BLP1 format as well. + +#include "il_internal.h" +#ifndef IL_NO_BLP +#include "il_dds.h" + + +typedef struct BLP1HEAD +{ + ILubyte Sig[4]; + ILuint Compression; // Texture type: 0 = JPG, 1 = Paletted + ILuint Flags; // #8 - Uses alpha channel (?) + ILuint Width; // Image width in pixels + ILuint Height; // Image height in pixels + ILuint PictureType; // 3 - Uncompressed index list + alpha list + // 4 - Uncompressed index list + alpha list + // 5 - Uncompressed index list + ILuint PictureSubType; // 1 - ??? + ILuint MipOffsets[16]; // The file offsets of each mipmap, 0 for unused + ILuint MipLengths[16]; // The length of each mipmap data block +} BLP1HEAD; + +typedef struct BLP2HEAD +{ + ILubyte Sig[4]; // "BLP2" signature + ILuint Type; // Texture type: 0 = JPG, 1 = DXTC + ILubyte Compression; // Compression mode: 1 = raw, 2 = DXTC + ILubyte AlphaBits; // 0, 1, or 8 + ILubyte AlphaType; // 0, 1, 7 or 8 + ILubyte HasMips; // 0 = no mips levels, 1 = has mips (number of levels determined by image size) + ILuint Width; // Image width in pixels + ILuint Height; // Image height in pixels + ILuint MipOffsets[16]; // The file offsets of each mipmap, 0 for unused + ILuint MipLengths[16]; // The length of each mipmap data block +} BLP2HEAD; + +// Data formats +#define BLP_TYPE_JPG 0 +#define BLP_TYPE_DXTC_RAW 1 +#define BLP_RAW 1 +#define BLP_DXTC 2 + +#define BLP_RAW_PLUS_ALPHA1 3 +#define BLP_RAW_PLUS_ALPHA2 4 +#define BLP_RAW_NO_ALPHA 5 + + +ILboolean iIsValidBlp2(void); +ILboolean iCheckBlp2(BLP2HEAD *Header); +ILboolean iLoadBlpInternal(void); +ILboolean iLoadBlp1(void); +ILboolean iCheckBlp1(BLP1HEAD *Header); +ILboolean iGetBlp1Head(BLP1HEAD *Header); + + +//! Checks if the file specified in FileName is a valid BLP file. +ILboolean ilIsValidBlp(ILconst_string FileName) +{ + ILHANDLE BlpFile; + ILboolean bBlp = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("blp"))) { + ilSetError(IL_INVALID_EXTENSION); + return bBlp; + } + + BlpFile = iopenr(FileName); + if (BlpFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bBlp; + } + + bBlp = ilIsValidBlpF(BlpFile); + icloser(BlpFile); + + return bBlp; +} + + +//! Checks if the ILHANDLE contains a valid BLP file at the current position. +ILboolean ilIsValidBlpF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidBlp2(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid BLP lump. +ILboolean ilIsValidBlpL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidBlp2(); +} + + +// Internal function used to get the BLP header from the current file. +ILboolean iGetBlp2Head(BLP2HEAD *Header) +{ + ILuint i; + + iread(Header->Sig, 1, 4); + Header->Type = GetLittleUInt(); + Header->Compression = igetc(); + Header->AlphaBits = igetc(); + Header->AlphaType = igetc(); + Header->HasMips = igetc(); + Header->Width = GetLittleUInt(); + Header->Height = GetLittleUInt(); + for (i = 0; i < 16; i++) + Header->MipOffsets[i] = GetLittleUInt(); + for (i = 0; i < 16; i++) + Header->MipLengths[i] = GetLittleUInt(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidBlp2(void) +{ + BLP2HEAD Header; + + if (!iGetBlp2Head(&Header)) + return IL_FALSE; + iseek(-148, IL_SEEK_CUR); + + return iCheckBlp2(&Header); +} + + +// Internal function used to check if the HEADER is a valid BLP header. +ILboolean iCheckBlp2(BLP2HEAD *Header) +{ + // The file signature is 'BLP2'. + if (strncmp(Header->Sig, "BLP2", 4)) + return IL_FALSE; + // Valid types are JPEG and DXTC. JPEG is not common, though. + // WoW only uses DXTC. + if (Header->Type != BLP_TYPE_JPG && Header->Type != BLP_TYPE_DXTC_RAW) + return IL_FALSE; + // For BLP_TYPE_DXTC_RAW, we can have RAW and DXTC compression. + if (Header->Compression != BLP_RAW && Header->Compression != BLP_DXTC) + return IL_FALSE; + // Alpha bits can only be 0, 1 and 8. + if (Header->AlphaBits != 0 && Header->AlphaBits != 1 && Header->AlphaBits != 8) + return IL_FALSE; + // Alpha type can only be 0, 1, 7 and 8. + if (Header->AlphaType != 0 && Header->AlphaType != 1 && Header->AlphaType != 7 && Header->AlphaType != 8) + return IL_FALSE; + // Width or height of 0 makes no sense. + if (Header->Width == 0 || Header->Height == 0) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a BLP file +ILboolean ilLoadBlp(ILconst_string FileName) +{ + ILHANDLE BlpFile; + ILboolean bBlp = IL_FALSE; + + BlpFile = iopenr(FileName); + if (BlpFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bBlp; + } + + bBlp = ilLoadBlpF(BlpFile); + icloser(BlpFile); + + return bBlp; +} + + +//! Reads an already-opened BLP file +ILboolean ilLoadBlpF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadBlpInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a BLP +ILboolean ilLoadBlpL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadBlpInternal(); +} + + +// Internal function used to load the BLP. +ILboolean iLoadBlpInternal(void) +{ + BLP2HEAD Header; + ILubyte *CompData; + ILimage *Image; + ILuint Mip, j, x, CompSize, AlphaSize, AlphaOff; + ILint y; + ILboolean BaseCreated = IL_FALSE; + ILubyte *DataAndAlpha = NULL, *Palette = NULL, AlphaMask; //, *JpegHeader, *JpegData; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetBlp2Head(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!iCheckBlp2(&Header)) { + goto check_blp1; + } + +//@TODO: Remove this! + if (Header.Type != BLP_TYPE_DXTC_RAW) + return IL_FALSE; + + switch (Header.Compression) + { + case BLP_RAW: + for (Mip = 0; Mip < 16; Mip++) { // Possible maximum of 16 mipmaps + if (BaseCreated) { + if (Header.HasMips == 0) // Does not have mipmaps, so we are done. + break; + if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. + break; + if (Header.MipOffsets[Mip] == 0 || Header.MipLengths == 0) // No more mipmaps in the file. + break; + } + + switch (Header.AlphaBits) + { + case 0: + if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + Image = iCurImage; + BaseCreated = IL_TRUE; + + Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); // 256 entries of ARGB8888 values (1024). + if (Image->Pal.Palette == NULL) + return IL_FALSE; + Image->Pal.PalSize = 1024; + Image->Pal.PalType = IL_PAL_BGRA32; //@TODO: Find out if this is really BGRA data. + if (iread(Image->Pal.Palette, 1, 1024) != 1024) // Read in the palette. + return IL_FALSE; + } + else { + Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); + if (Image->Mipmaps == NULL) + return IL_FALSE; + + // Copy the palette from the first image before we change our Image pointer. + iCopyPalette(&Image->Mipmaps->Pal, &Image->Pal); + // Move to the next mipmap in the linked list. + Image = Image->Mipmaps; + } + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + // These two should be the same (tells us how much data is in the file for this mipmap level). + if (Header.MipLengths[Mip] != Image->SizeOfData) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + // Finally read in the image data. + iseek(Header.MipOffsets[Mip], IL_SEEK_SET); + if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) + return IL_FALSE; + break; + + case 1: + if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. + if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + Image = iCurImage; + BaseCreated = IL_TRUE; + + Palette = (ILubyte*)ialloc(256 * 4); + if (Palette == NULL) + return IL_FALSE; + + // Read in the palette. + if (iread(Palette, 1, 1024) != 1024) { + ifree(Palette); + return IL_FALSE; + } + + // We only allocate this once and reuse this buffer with every mipmap (since successive ones are smaller). + DataAndAlpha = (ILubyte*)ialloc(Image->Width * Image->Height); + if (DataAndAlpha == NULL) { + ifree(DataAndAlpha); + ifree(Palette); + return IL_FALSE; + } + } + else { + Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); + if (Image->Mipmaps == NULL) + return IL_FALSE; + + // Move to the next mipmap in the linked list. + Image = Image->Mipmaps; + } + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + // Determine the size of the alpha data following the color indices. + AlphaSize = Image->Width * Image->Height / 8; + if (AlphaSize == 0) + AlphaSize = 1; // Should never be 0. + // These two should be the same (tells us how much data is in the file for this mipmap level). + if (Header.MipLengths[Mip] != Image->SizeOfData / 4 + AlphaSize) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Seek to the data and read it. + iseek(Header.MipOffsets[Mip], IL_SEEK_SET); + if (iread(DataAndAlpha, Image->Width * Image->Height, 1) != 1) { + ifree(DataAndAlpha); + ifree(Palette); + return IL_FALSE; + } + + // Convert the color-indexed data to BGRX. + for (j = 0; j < Image->Width * Image->Height; j++) { + Image->Data[j*4] = Palette[DataAndAlpha[j]*4]; + Image->Data[j*4+1] = Palette[DataAndAlpha[j]*4+1]; + Image->Data[j*4+2] = Palette[DataAndAlpha[j]*4+2]; + } + + // Read in the alpha list. + if (iread(DataAndAlpha, AlphaSize, 1) != 1) { + ifree(DataAndAlpha); + ifree(Palette); + return IL_FALSE; + } + + AlphaMask = 0x01; // Lowest bit + AlphaOff = 0; + // The really strange thing about this alpha data is that it is upside-down when compared to the + // regular color-indexed data, so we have to flip it. + for (y = Image->Height - 1; y >= 0; y--) { + for (x = 0; x < Image->Width; x++) { + if (AlphaMask == 0) { // Shifting it past the highest bit makes it 0, since we only have 1 byte. + AlphaOff++; // Move along the alpha buffer. + AlphaMask = 0x01; // Reset the alpha mask. + } + // This is just 1-bit alpha, so it is either on or off. + Image->Data[Image->Bps * y + x * 4 + 3] = DataAndAlpha[AlphaOff] & AlphaMask ? 0xFF : 0x00; + AlphaMask <<= 1; + } + } + + break; + + default: + //@TODO: Accept any other alpha values? + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + } + + // Done, so we can finally free these two. + ifree(DataAndAlpha); + ifree(Palette); + + break; + + case BLP_DXTC: + for (Mip = 0; Mip < 16; Mip++) { // Possible maximum of 16 mipmaps + //@TODO: Other formats + //if (Header.AlphaBits == 0) + // if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + // return IL_FALSE; + if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. + if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + Image = iCurImage; + BaseCreated = IL_TRUE; + } + else { + if (Header.HasMips == 0) // Does not have mipmaps, so we are done. + break; + if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. + break; + if (Header.MipOffsets[Mip] == 0 || Header.MipLengths[Mip] == 0) // No more mipmaps in the file. + break; + + //@TODO: Other formats + // ilNewImageFull automatically changes widths and heights of 0 to 1, so we do not have to worry about it. + Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + if (Image->Mipmaps == NULL) + return IL_FALSE; + Image = Image->Mipmaps; + } + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + //@TODO: Only do the allocation once. + CompData = (ILubyte*)ialloc(Header.MipLengths[Mip]); + if (CompData == NULL) + return IL_FALSE; + + // Read in the compressed mipmap data. + iseek(Header.MipOffsets[Mip], IL_SEEK_SET); + if (iread(CompData, 1, Header.MipLengths[Mip]) != Header.MipLengths[Mip]) { + ifree(CompData); + return IL_FALSE; + } + + switch (Header.AlphaBits) + { + case 0: // DXT1 without alpha + case 1: // DXT1 with alpha + // Check to make sure that the MipLength reported is the size needed, so that + // DecompressDXT1 does not crash. + CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 8; + if (CompSize != Header.MipLengths[Mip]) { + ilSetError(IL_INVALID_FILE_HEADER); + ifree(CompData); + return IL_FALSE; + } + if (!DecompressDXT1(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + break; + + case 8: + // Check to make sure that the MipLength reported is the size needed, so that + // DecompressDXT3/5 do not crash. + CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 16; + if (CompSize != Header.MipLengths[Mip]) { + ifree(CompData); + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + switch (Header.AlphaType) + { + case 0: // All three of + case 1: // these refer to + case 8: // DXT3... + if (!DecompressDXT3(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + break; + + case 7: // DXT5 compression + if (!DecompressDXT5(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + break; + + //default: // Should already be checked by iCheckBlp2. + } + break; + //default: // Should already be checked by iCheckBlp2. + } + //@TODO: Save DXTC data. + ifree(CompData); + } + break; + //default: + } + + return ilFixImage(); + +check_blp1: + iseek(-148, IL_SEEK_CUR); // Go back the size of the BLP2 header, since we tried reading it. + return iLoadBlp1(); +} + + +ILboolean iGetBlp1Head(BLP1HEAD *Header) +{ + ILuint i; + + iread(Header->Sig, 1, 4); + Header->Compression = GetLittleUInt(); + Header->Flags = GetLittleUInt(); + Header->Width = GetLittleUInt(); + Header->Height = GetLittleUInt(); + Header->PictureType = GetLittleUInt(); + Header->PictureSubType = GetLittleUInt(); + for (i = 0; i < 16; i++) + Header->MipOffsets[i] = GetLittleUInt(); + for (i = 0; i < 16; i++) + Header->MipLengths[i] = GetLittleUInt(); + + return IL_TRUE; +} + + +ILboolean iCheckBlp1(BLP1HEAD *Header) +{ + // The file signature is 'BLP1'. + if (strncmp(Header->Sig, "BLP1", 4)) + return IL_FALSE; + // Valid types are JPEG and RAW. JPEG is not common, though. + if (Header->Compression != BLP_TYPE_JPG && Header->Compression != BLP_RAW) + return IL_FALSE; +//@TODO: Find out what Flags is for. + + // PictureType determines whether this has an alpha list. + if (Header->PictureType != BLP_RAW_PLUS_ALPHA1 && Header->PictureType != BLP_RAW_PLUS_ALPHA2 + && Header->PictureType != BLP_RAW_NO_ALPHA) + return IL_FALSE; + // Width or height of 0 makes no sense. + if (Header->Width == 0 || Header->Height == 0) + return IL_FALSE; + + return IL_TRUE; +} + + +ILboolean iLoadBlp1() +{ + BLP1HEAD Header; + ILubyte *DataAndAlpha, *Palette; + ILuint i; + ILimage *Image = iCurImage; + ILboolean BaseCreated = IL_FALSE; +#ifndef IL_NO_JPG + ILubyte *JpegHeader, *JpegData; + ILuint JpegHeaderSize; +#endif//IL_NO_JPG + + if (!iGetBlp1Head(&Header)) + return IL_FALSE; + if (!iCheckBlp1(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + //@TODO: Remove this. + i = 0; + + switch (Header.Compression) + { + case BLP_TYPE_JPG: +#ifdef IL_NO_JPG + // We can only do the Jpeg decoding if we do not have IL_NO_JPEG defined. + return IL_FALSE; +#else + JpegHeaderSize = GetLittleUInt(); + JpegHeader = (ILubyte*)ialloc(JpegHeaderSize); + if (JpegHeader == NULL) + return IL_FALSE; + // Read the shared Jpeg header. + if (iread(JpegHeader, 1, JpegHeaderSize) != JpegHeaderSize) { + ifree(JpegHeader); + return IL_FALSE; + } + + //for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps + //@TODO: Check return value? + iseek(Header.MipOffsets[i], IL_SEEK_SET); + JpegData = (ILubyte*)ialloc(JpegHeaderSize + Header.MipLengths[i]); + if (JpegData == NULL) { + ifree(JpegHeader); + return IL_FALSE; + } + memcpy(JpegData, JpegHeader, JpegHeaderSize); + if (iread(JpegData + JpegHeaderSize, Header.MipLengths[i], 1) != 1) + return IL_FALSE; + + // Just send the data straight to the Jpeg loader. + if (!ilLoadJpegL(JpegData, JpegHeaderSize + Header.MipLengths[i])) + return IL_FALSE; + + // The image data is in BGR(A) order, even though it is Jpeg-compressed. + if (Image->Format == IL_RGBA) + Image->Format = IL_BGRA; + if (Image->Format == IL_RGB) + Image->Format = IL_BGR; + + ifree(JpegData); + //} + ifree(JpegHeader); +#endif//IL_NO_JPG + break; + + case BLP_RAW: + switch (Header.PictureType) + { + // There is no alpha list, so we just read like a normal indexed image. + case BLP_RAW_NO_ALPHA: + for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps + if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + Image = iCurImage; + BaseCreated = IL_TRUE; + + // We have a BGRA palette. + Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); + if (Image->Pal.Palette == NULL) + return IL_FALSE; + Image->Pal.PalSize = 1024; + Image->Pal.PalType = IL_PAL_BGRA32; + + // Read in the palette ... + if (iread(Image->Pal.Palette, 1, 1024) != 1024) + return IL_FALSE; + } + else { + if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. + break; + if (Header.MipOffsets[i] == 0 || Header.MipLengths[i] == 0) // No more mipmaps in the file. + break; + + Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOR_INDEX, IL_UNSIGNED_BYTE, NULL); + if (Image->Mipmaps == NULL) + return IL_FALSE; + + // Copy the palette from the first image before we change our Image pointer. + Image->Mipmaps->Pal.Palette = (ILubyte*)ialloc(256 * 4); + if (Image->Mipmaps->Pal.Palette == NULL) + return IL_FALSE; + Image->Mipmaps->Pal.PalSize = 1024; + Image->Mipmaps->Pal.PalType = IL_PAL_BGRA32; + memcpy(Image->Mipmaps->Pal.Palette, Image->Pal.Palette, 1024); + + // Move to the next mipmap in the linked list. + Image = Image->Mipmaps; + } + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + // Seek to the data and read it. + iseek(Header.MipOffsets[i], IL_SEEK_SET); + if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) + return IL_FALSE; + } + break; + + // These cases are identical and have an alpha list following the image data. + case BLP_RAW_PLUS_ALPHA1: + case BLP_RAW_PLUS_ALPHA2: + // Create the image. + if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + + DataAndAlpha = (ILubyte*)ialloc(Header.Width * Header.Height); + Palette = (ILubyte*)ialloc(256 * 4); + if (DataAndAlpha == NULL || Palette == NULL) { + ifree(DataAndAlpha); + ifree(Palette); + return IL_FALSE; + } + + // Read in the data and the palette. + if (iread(Palette, 1, 1024) != 1024) { + ifree(Palette); + return IL_FALSE; + } + // Seek to the data and read it. + iseek(Header.MipOffsets[i], IL_SEEK_SET); + if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { + ifree(DataAndAlpha); + ifree(Palette); + return IL_FALSE; + } + + // Convert the color-indexed data to BGRX. + for (i = 0; i < Header.Width * Header.Height; i++) { + Image->Data[i*4] = Palette[DataAndAlpha[i]*4]; + Image->Data[i*4+1] = Palette[DataAndAlpha[i]*4+1]; + Image->Data[i*4+2] = Palette[DataAndAlpha[i]*4+2]; + } + + // Read in the alpha list. + if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { + ifree(DataAndAlpha); + ifree(Palette); + return IL_FALSE; + } + // Finally put the alpha data into the image data. + for (i = 0; i < Header.Width * Header.Height; i++) { + Image->Data[i*4+3] = DataAndAlpha[i]; + } + + ifree(DataAndAlpha); + ifree(Palette); + break; + } + break; + + //default: // Should already be checked by iCheckBlp1. + } + + // Set the origin (always upper left). + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + return ilFixImage(); +} + + +#endif//IL_NO_BLP diff --git a/DevIL/src-IL/src/il_bmp.c b/DevIL/src-IL/src/il_bmp.c deleted file mode 100644 index e4719e1c..00000000 --- a/DevIL/src-IL/src/il_bmp.c +++ /dev/null @@ -1,1048 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 02/09/2009 -// -// Filename: src-IL/src/il_bmp.c -// -// Description: Reads from and writes to a bitmap (.bmp) file. -// -//----------------------------------------------------------------------------- - -#define IL_BMP_C - -#include "il_internal.h" -#ifndef IL_NO_BMP -#include "il_bmp.h" -#include "il_endian.h" -#include -void GetShiftFromMask(const ILuint Mask, ILuint * CONST_RESTRICT ShiftLeft, ILuint * CONST_RESTRICT ShiftRight); - -//! Checks if the file specified in FileName is a valid .bmp file. -ILboolean ilIsValidBmp(ILconst_string CONST_RESTRICT FileName) -{ - ILHANDLE BitmapFile; - ILboolean bBitmap = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("bmp"))) { - ilSetError(IL_INVALID_EXTENSION); - return bBitmap; - } - - BitmapFile = iopenr(FileName); - if (BitmapFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bBitmap; - } - - bBitmap = ilIsValidBmpF(BitmapFile); - icloser(BitmapFile); - - return bBitmap; -} - - -//! Checks if the ILHANDLE contains a valid .bmp file at the current position. -ILboolean ilIsValidBmpF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidBmp(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .bmp lump. -ILboolean ilIsValidBmpL(const void * Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidBmp(); -} - -// Internal function used to get the .bmp header from the current file. -ILboolean iGetBmpHead(BMPHEAD * const Header) -{ - Header->bfType = GetLittleUShort(); - Header->bfSize = GetLittleInt(); - Header->bfReserved = GetLittleUInt(); - Header->bfDataOff = GetLittleInt(); - Header->biSize = GetLittleInt(); - Header->biWidth = GetLittleInt(); - Header->biHeight = GetLittleInt(); - Header->biPlanes = GetLittleShort(); - Header->biBitCount = GetLittleShort(); - Header->biCompression = GetLittleInt(); - Header->biSizeImage = GetLittleInt(); - Header->biXPelsPerMeter = GetLittleInt(); - Header->biYPelsPerMeter = GetLittleInt(); - Header->biClrUsed = GetLittleInt(); - Header->biClrImportant = GetLittleInt(); - return IL_TRUE; -} - - -ILboolean iGetOS2Head(OS2_HEAD * const Header) -{ - if (iread(Header, sizeof(OS2_HEAD), 1) != 1) - return IL_FALSE; - - UShort(&Header->bfType); - UInt(&Header->biSize); - Short(&Header->xHotspot); - Short(&Header->yHotspot); - UInt(&Header->DataOff); - UInt(&Header->cbFix); - - //2003-09-01 changed to UShort according to MSDN - UShort(&Header->cx); - UShort(&Header->cy); - UShort(&Header->cPlanes); - UShort(&Header->cBitCount); - - iseek((ILint)Header->cbFix - 12, IL_SEEK_CUR); // Skip rest of header, if any. - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidBmp() -{ - BMPHEAD Head; - OS2_HEAD Os2Head; - ILboolean IsValid; - - iGetBmpHead(&Head); - iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR); // Go ahead and restore to previous state - - IsValid = iCheckBmp(&Head); - if (!IsValid) { - iGetOS2Head(&Os2Head); - iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR); - IsValid = iCheckOS2(&Os2Head); - } - return IsValid; -} - - -// Internal function used to check if the HEADER is a valid .bmp header. -ILboolean iCheckBmp (const BMPHEAD * CONST_RESTRICT Header) -{ - //if ((Header->bfType != ('B'|('M'<<8))) || ((Header->biSize != 0x28) && (Header->biSize != 0x0C))) - if ((Header->bfType != ('B'|('M'<<8))) || (Header->biSize != 0x28)) - return IL_FALSE; - if (Header->biHeight == 0 || Header->biWidth < 1) - return IL_FALSE; - if (Header->biPlanes > 1) // Not sure... - return IL_FALSE; - if(Header->biCompression != 0 && Header->biCompression != 1 && - Header->biCompression != 2 && Header->biCompression != 3) - return IL_FALSE; - if(Header->biCompression == 3 && Header->biBitCount != 16 && Header->biBitCount != 32) - return IL_FALSE; - if (Header->biBitCount != 1 && Header->biBitCount != 4 && Header->biBitCount != 8 && - Header->biBitCount != 16 && Header->biBitCount != 24 && Header->biBitCount != 32) - return IL_FALSE; - return IL_TRUE; -} - - -ILboolean iCheckOS2 (const OS2_HEAD * CONST_RESTRICT Header) -{ - if ((Header->bfType != ('B'|('M'<<8))) || (Header->DataOff < 26) || (Header->cbFix < 12)) - return IL_FALSE; - if (Header->cPlanes != 1) - return IL_FALSE; - if (Header->cx == 0 || Header->cy == 0) - return IL_FALSE; - if (Header->cBitCount != 1 && Header->cBitCount != 4 && Header->cBitCount != 8 && - Header->cBitCount != 24) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a .bmp file -ILboolean ilLoadBmp(ILconst_string FileName) { - ILHANDLE BitmapFile; - ILboolean bBitmap = IL_FALSE; - - BitmapFile = iopenr(FileName); - if (BitmapFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bBitmap; - } - - bBitmap = ilLoadBmpF(BitmapFile); - icloser(BitmapFile); - - return bBitmap; -} - - -//! Reads an already-opened .bmp file -ILboolean ilLoadBmpF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadBitmapInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .bmp -ILboolean ilLoadBmpL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadBitmapInternal(); -} - - -// Internal function used to load the .bmp. -ILboolean iLoadBitmapInternal() -{ - BMPHEAD Header; - OS2_HEAD Os2Head; - ILboolean bBitmap; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iGetBmpHead(&Header); - if (!iCheckBmp(&Header)) { - iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR); - iGetOS2Head(&Os2Head); - if (!iCheckOS2(&Os2Head)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - else { - return iGetOS2Bmp(&Os2Head); - } - } - - // Don't know what to do if it has more than one plane... - if (Header.biPlanes != 1) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - switch (Header.biCompression) - { - case 0: // No compression - case 3: // BITFIELDS compression is handled in 16 bit - // and 32 bit code in ilReadUncompBmp() - bBitmap = ilReadUncompBmp(&Header); - break; - case 1: // RLE 8-bit / pixel (BI_RLE8) - bBitmap = ilReadRLE8Bmp(&Header); - break; - case 2: // RLE 4-bit / pixel (BI_RLE4) - bBitmap = ilReadRLE4Bmp(&Header); - break; - - default: - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ilFixImage()) - return IL_FALSE; - - return bBitmap; -} - - -// Reads an uncompressed .bmp -// One of the absolute ugliest functions I've ever written! -ILboolean ilReadUncompBmp(BMPHEAD * Header) -{ - ILuint i, j, k, c, Read; - ILubyte Bpp, ByteData, PadSize, Padding[4]; - ILuint rMask, gMask, bMask; //required for bitfields packing - ILuint rShiftR, gShiftR, bShiftR; //required for bitfields packing - ILuint rShiftL, gShiftL, bShiftL; //required for bitfields packing - ILushort Read16; //used for 16bit bmp loading - - if (Header->biBitCount < 8) - Bpp = 1; // We can't have an integral number less than one and greater than 0 - else - Bpp = (ILubyte)(Header->biBitCount >> 3); // Convert to bytes per pixel - - if(Bpp == 2 || Bpp == 4) - Bpp = 3; - - // Update the current image with the new dimensions - if (!ilTexImage(Header->biWidth, abs(Header->biHeight), 1, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - switch (Header->biBitCount) - { - case 1: - //iCurImage->Format = IL_LUMINANCE; - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalType = IL_PAL_BGR32; - iCurImage->Pal.PalSize = 2 * 4; - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - break; - - case 4: - case 8: - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalType = IL_PAL_BGR32; - - // if there are 256 colors biClrUsed is 0 - iCurImage->Pal.PalSize = Header->biClrUsed ? - Header->biClrUsed * 4 : 256 * 4; - - if (Header->biBitCount == 4) // biClrUsed is 0 for 4-bit bitmaps - iCurImage->Pal.PalSize = 16 * 4; - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - break; - - case 16: - case 24: - case 32: - iCurImage->Format = IL_BGR; - break; - - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - // A height of 0 is illegal - if (Header->biHeight == 0) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - if (iCurImage->Pal.Palette) - ifree(iCurImage->Pal.Palette); - return IL_FALSE; - } - - // If the image height is negative, then the image is flipped - // (Normal is IL_ORIGIN_LOWER_LEFT) - if (Header->biHeight < 0) { - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - } - else { - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - } - - // Read the palette - iseek(sizeof(BMPHEAD), IL_SEEK_SET); - if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) - return IL_FALSE; - - // Seek to the data from the "beginning" of the file - iseek(Header->bfDataOff, IL_SEEK_SET); - - // We have to handle 1 and 4-bit images separately, because we have to expand them. - switch (Header->biBitCount) - { - case 1: - //changed 2003-09-01 - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->Width / 8 * iCurImage->Height); - - PadSize = ((32 - (iCurImage->Width % 32)) / 8) % 4; // Has to truncate - for (j = 0; j < iCurImage->Height; j++) { - Read = 0; - for (i = 0; i < iCurImage->Width; ) { - if (iread(&ByteData, 1, 1) != 1) { - iUnCache(); - return IL_FALSE; - } - Read++; - k = 128; - for (c = 0; c < 8; c++) { - iCurImage->Data[j * iCurImage->Width + i] = - (!!(ByteData & k) == 1 ? 1 : 0); - k >>= 1; - if (++i >= iCurImage->Width) - break; - } - } - //iseek(PadSize, IL_SEEK_CUR); - iread(Padding, 1, PadSize); - } - - iUnCache(); - break; - - case 4: - //changed 2003-09-01 - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->Width / 2 * iCurImage->Height); - - PadSize = ((8 - (iCurImage->Width % 8)) / 2) % 4; // Has to truncate - for (j = 0; j < iCurImage->Height; j++) { - for (i = 0; i < iCurImage->Width; i++) { - if (iread(&ByteData, 1, 1) != 1) { - iUnCache(); - return IL_FALSE; - } - iCurImage->Data[j * iCurImage->Width + i] = ByteData >> 4; - if (++i == iCurImage->Width) - break; - iCurImage->Data[j * iCurImage->Width + i] = ByteData & 0x0F; - } - iread(Padding, 1, PadSize);//iseek(PadSize, IL_SEEK_CUR); - } - - iUnCache(); - break; - - case 16: - //padding - //2003-09-09: changed iCurImage->Bps to iCurImage->Width*2, - //because iCurImage->Bps refers to the 24 bit devil image - PadSize = (4 - (iCurImage->Width*2 % 4)) % 4; - - //check if bitfield compression is used - rMask = 0x7C00; - gMask = 0x03E0; - bMask = 0x001F; - rShiftR = 10; - gShiftR = 5; - bShiftR = 0; - rShiftL = 3; - gShiftL = 3; - bShiftL = 3; - if (Header->biCompression == 3) //bitfields - { - iseek(Header->bfDataOff - 12, IL_SEEK_SET); //seek to bitfield data - iread(&rMask, 4, 1); - iread(&gMask, 4, 1); - iread(&bMask, 4, 1); - UInt(&rMask); - UInt(&gMask); - UInt(&bMask); - GetShiftFromMask(rMask, &rShiftL, &rShiftR); - GetShiftFromMask(gMask, &gShiftL, &gShiftR); - GetShiftFromMask(bMask, &bShiftL, &bShiftR); - } - - k = 0; - - //changed 2003-09-01 - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->Width * iCurImage->Height); - - //@TODO: This may not be safe for Big Endian. - for (j = 0; j < iCurImage->Height; j++) { - for(i = 0; i < iCurImage->Width; i++, k += 3) { - if (iread(&Read16, 2, 1) != 1) { - iUnCache(); - return IL_FALSE; - } - iCurImage->Data[k] = ((Read16 & bMask) >> bShiftR) << bShiftL; - iCurImage->Data[k + 1] = ((Read16 & gMask) >> gShiftR) << gShiftL; - iCurImage->Data[k + 2] = ((Read16 & rMask) >> rShiftR) << rShiftL; - } - iread(Padding, 1, PadSize); - } - - iUnCache(); - break; - - case 8: - case 24: - // For 8 and 24 bit, Bps is equal to the bmps bps - PadSize = (4 - (iCurImage->Bps % 4)) % 4; - if (PadSize == 0) { - if (iread(iCurImage->Data, 1, iCurImage->SizeOfPlane) != iCurImage->SizeOfPlane) - return IL_FALSE; - } - else { // Microsoft requires lines to be padded if the widths aren't multiples of 4. - //changed 2003-09-01 - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->Width * iCurImage->Height); - - PadSize = (4 - (iCurImage->Bps % 4)); - for (i = 0; i < iCurImage->SizeOfPlane; i += iCurImage->Bps) { - if (iread(iCurImage->Data + i, 1, iCurImage->Bps) != iCurImage->Bps) { - iUnCache(); - return IL_FALSE; - } - //iseek(PadSize, IL_SEEK_CUR); - iread(Padding, 1, PadSize); - } - - iUnCache(); - } - break; - - case 32: - //32bit files are always padded to 4 byte... - //check if bitfield compression is used - rMask = 0xFF0000; - gMask = 0x00FF00; - bMask = 0x0000FF; - rShiftR = 16; - gShiftR = 8; - bShiftR = 0; - rShiftL = 0; - gShiftL = 0; - bShiftL = 0; - if (Header->biCompression == 3) //bitfields - { - iseek(Header->bfDataOff - 12, IL_SEEK_SET); //seek to bitfield data - iread(&rMask, 4, 1); - iread(&gMask, 4, 1); - iread(&bMask, 4, 1); - UInt(&rMask); - UInt(&gMask); - UInt(&bMask); - GetShiftFromMask(rMask, &rShiftL, &rShiftR); - GetShiftFromMask(gMask, &gShiftL, &gShiftR); - GetShiftFromMask(bMask, &bShiftL, &bShiftR); - } - - //TODO: win98 supports per-pixel alpha, so - //load to rgba???? - - //changed 2003-09-01 - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->Width * iCurImage->Height); - - for(i = 0; i < iCurImage->SizeOfData; i += 3) { - if (iread(&Read, 4, 1) != 1) { - iUnCache(); - return IL_FALSE; - } - - iCurImage->Data[i] = ((Read & bMask) >> bShiftR) << bShiftL; - iCurImage->Data[i + 1] = ((Read & gMask) >> gShiftR) << gShiftL; - iCurImage->Data[i + 2] = ((Read & rMask) >> rShiftR) << rShiftL; - } - - iUnCache(); - break; - - default: - return IL_FALSE; //shouldn't happen, we checked that before - } - - return IL_TRUE; -} - - -ILboolean ilReadRLE8Bmp(BMPHEAD *Header) -{ - ILubyte Bytes[2]; - size_t offset = 0, count, endOfLine = Header->biWidth; - - // Update the current image with the new dimensions - if (!ilTexImage(Header->biWidth, abs(Header->biHeight), 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - // A height of 0 is illegal - if (Header->biHeight == 0) - return IL_FALSE; - - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalType = IL_PAL_BGR32; - iCurImage->Pal.PalSize = Header->biClrUsed * 4; // 256 * 4 for most images - if (iCurImage->Pal.PalSize == 0) - iCurImage->Pal.PalSize = 256 * 4; - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) - return IL_FALSE; - - // If the image height is negative, then the image is flipped - // (Normal is IL_ORIGIN_LOWER_LEFT) - iCurImage->Origin = Header->biHeight < 0 ? - IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT; - - // Read the palette - iseek(sizeof(BMPHEAD), IL_SEEK_SET); - if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) - return IL_FALSE; - - // Seek to the data from the "beginning" of the file - iseek(Header->bfDataOff, IL_SEEK_SET); - - while (offset < iCurImage->SizeOfData) { - if (iread(Bytes, sizeof(Bytes), 1) != 1) - return IL_FALSE; - if (Bytes[0] == 0x00) { // Escape sequence - switch (Bytes[1]) - { - case 0x00: // End of line - offset = endOfLine; - endOfLine += iCurImage->Width; - break; - case 0x01: // End of bitmap - offset = iCurImage->SizeOfData; - break; - case 0x2: - if (iread(Bytes, sizeof(Bytes), 1) != 1) - return IL_FALSE; - offset += Bytes[0] + Bytes[1] * iCurImage->Width; - endOfLine += Bytes[1] * iCurImage->Width; - break; - default: - count = IL_MIN(Bytes[1], iCurImage->SizeOfData-offset); - if (iread(iCurImage->Data + offset, (ILuint)count, 1) != 1) - return IL_FALSE; - offset += count; - if ((count & 1) == 1) // Must be on a word boundary - if (iread(Bytes, 1, 1) != 1) - return IL_FALSE; - break; - } - } else { - count = IL_MIN (Bytes[0], iCurImage->SizeOfData-offset); - memset(iCurImage->Data + offset, Bytes[1], count); - offset += count; - } - } - return IL_TRUE; -} - - -//changed 2003-09-01 -//deleted ilReadRLE8Bmp() USE_POINTER version - -ILboolean ilReadRLE4Bmp(BMPHEAD *Header) -{ - ILubyte Bytes[2]; - ILuint i; - size_t offset = 0, count, endOfLine = Header->biWidth; - - // Update the current image with the new dimensions - if (!ilTexImage(Header->biWidth, abs(Header->biHeight), 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - // A height of 0 is illegal - if (Header->biHeight == 0) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalType = IL_PAL_BGR32; - iCurImage->Pal.PalSize = 16 * 4; //Header->biClrUsed * 4; // 16 * 4 for most images - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) - return IL_FALSE; - - // If the image height is negative, then the image is flipped - // (Normal is IL_ORIGIN_LOWER_LEFT) - iCurImage->Origin = Header->biHeight < 0 ? - IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT; - - // Read the palette - iseek(sizeof(BMPHEAD), IL_SEEK_SET); - - if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) - return IL_FALSE; - - // Seek to the data from the "beginning" of the file - iseek(Header->bfDataOff, IL_SEEK_SET); - - while (offset < iCurImage->SizeOfData) { - int align; - if (iread(&Bytes[0], sizeof(Bytes), 1) != 1) - return IL_FALSE; - if (Bytes[0] == 0x0) { // Escape sequence - switch (Bytes[1]) { - case 0x0: // End of line - offset = endOfLine; - endOfLine += iCurImage->Width; - break; - case 0x1: // End of bitmap - offset = iCurImage->SizeOfData; - break; - case 0x2: - if (iread(&Bytes[0], sizeof(Bytes), 1) != 1) - return IL_FALSE; - offset += Bytes[0] + Bytes[1] * iCurImage->Width; - endOfLine += Bytes[1] * iCurImage->Width; - break; - default: // Run of pixels - count = IL_MIN (Bytes[1], iCurImage->SizeOfData-offset); - - for (i = 0; i < count; i++) { - int byte; - - if ((i & 0x01) == 0) { - if (iread(&Bytes[0], sizeof(Bytes[0]), 1) != 1) - return IL_FALSE; - byte = (Bytes[0] >> 4); - } - else - byte = (Bytes[0] & 0x0F); - iCurImage->Data[offset++] = byte; - } - - align = Bytes[1] % 4; - - if (align == 1 || align == 2) // Must be on a word boundary - if (iread(&Bytes[0], sizeof(Bytes[0]), 1) != 1) - return IL_FALSE; - } - } else { - count = IL_MIN (Bytes[0], iCurImage->SizeOfData-offset); - Bytes[0] = (Bytes[1] >> 4); - Bytes[1] &= 0x0F; - for (i = 0; i < count; i++) - iCurImage->Data[offset++] = Bytes [i & 1]; - } - } - - return IL_TRUE; -} - - -//changed 2003-09-01 -//deleted ilReadRLE4Bmp() USE_POINTER version - -ILboolean iGetOS2Bmp(OS2_HEAD *Header) -{ - ILuint PadSize, Read, i, j, k, c; - ILubyte ByteData; - - if (Header->cBitCount == 1) { - if (!ilTexImage(Header->cx, Header->cy, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(2 * 3); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - iCurImage->Pal.PalSize = 2 * 3; - iCurImage->Pal.PalType = IL_PAL_BGR24; - - if (iread(iCurImage->Pal.Palette, 1, 2 * 3) != 6) - return IL_FALSE; - - PadSize = ((32 - (iCurImage->Width % 32)) / 8) % 4; // Has to truncate. - iseek(Header->DataOff, IL_SEEK_SET); - - for (j = 0; j < iCurImage->Height; j++) { - Read = 0; - for (i = 0; i < iCurImage->Width; ) { - if (iread(&ByteData, 1, 1) != 1) - return IL_FALSE; - Read++; - k = 128; - for (c = 0; c < 8; c++) { - iCurImage->Data[j * iCurImage->Width + i] = - (!!(ByteData & k) == 1 ? 1 : 0); - k >>= 1; - if (++i >= iCurImage->Width) - break; - } - } - iseek(PadSize, IL_SEEK_CUR); - } - return IL_TRUE; - } - - if (Header->cBitCount == 4) { - if (!ilTexImage(Header->cx, Header->cy, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - iCurImage->Pal.PalSize = 16 * 3; - iCurImage->Pal.PalType = IL_PAL_BGR24; - - if (iread(iCurImage->Pal.Palette, 1, 16 * 3) != 16*3) - return IL_FALSE; - - PadSize = ((8 - (iCurImage->Width % 8)) / 2) % 4; // Has to truncate - iseek(Header->DataOff, IL_SEEK_SET); - - for (j = 0; j < iCurImage->Height; j++) { - for (i = 0; i < iCurImage->Width; i++) { - if (iread(&ByteData, 1, 1) != 1) - return IL_FALSE; - iCurImage->Data[j * iCurImage->Width + i] = ByteData >> 4; - if (++i == iCurImage->Width) - break; - iCurImage->Data[j * iCurImage->Width + i] = ByteData & 0x0F; - } - iseek(PadSize, IL_SEEK_CUR); - } - - return IL_TRUE; - } - - if (Header->cBitCount == 8) { - //added this line 2003-09-01...strange no-one noticed before... - if (!ilTexImage(Header->cx, Header->cy, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(256 * 3); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - iCurImage->Pal.PalSize = 256 * 3; - iCurImage->Pal.PalType = IL_PAL_BGR24; - - if (iread(iCurImage->Pal.Palette, 1, 256 * 3) != 256*3) - return IL_FALSE; - } - else { //has to be 24 bpp - if (!ilTexImage(Header->cx, Header->cy, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - iseek(Header->DataOff, IL_SEEK_SET); - - PadSize = (4 - (iCurImage->Bps % 4)) % 4; - if (PadSize == 0) { - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) - return IL_FALSE; - } - else { - for (i = 0; i < iCurImage->Height; i++) { - if (iread(iCurImage->Data + i * iCurImage->Bps, 1, iCurImage->Bps) != iCurImage->Bps) - return IL_FALSE; - iseek(PadSize, IL_SEEK_CUR); - } - } - - return IL_TRUE; -} - - -//! Writes a Bmp file -ILboolean ilSaveBmp(const ILstring FileName) -{ - ILHANDLE BitmapFile; - ILuint BitmapSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - BitmapFile = iopenw(FileName); - if (BitmapFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - BitmapSize = ilSaveBmpF(BitmapFile); - iclosew(BitmapFile); - - if (BitmapSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Bmp to an already-opened file -ILuint ilSaveBmpF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveBitmapInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Bmp to a memory "lump" -ILuint ilSaveBmpL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveBitmapInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the .bmp. -ILboolean iSaveBitmapInternal() -{ - //int compress_rle8 = ilGetInteger(IL_BMP_RLE); - int compress_rle8 = IL_FALSE; // disabled BMP RLE compression. broken - ILuint FileSize, i, PadSize, Padding = 0; - ILimage *TempImage = NULL; - ILpal *TempPal; - ILubyte *TempData; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iputc('B'); // Comprises the - iputc('M'); // "signature" - - SaveLittleUInt(0); // Will come back and change later in this function (filesize) - SaveLittleUInt(0); // Reserved - - if (compress_rle8 == IL_TRUE) - { - TempImage = iConvertImage(iCurImage, IL_COLOR_INDEX, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - TempPal = iConvertPal(&TempImage->Pal, IL_PAL_BGR32); - if (TempPal == NULL) - { - ilCloseImage(TempImage); - return IL_FALSE; - } - } - - // If the current image has a palette, take care of it - TempPal = &iCurImage->Pal; - if( iCurImage->Pal.PalSize && iCurImage->Pal.Palette && iCurImage->Pal.PalType != IL_PAL_NONE ) { - // If the palette in .bmp format, write it directly - if (iCurImage->Pal.PalType == IL_PAL_BGR32) { - TempPal = &iCurImage->Pal; - } else { - TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_BGR32); - if (TempPal == NULL) { - return IL_FALSE; - } - } - } - - SaveLittleUInt(54 + TempPal->PalSize); // Offset of the data - - //Changed 20040923: moved this block above writing of - //BITMAPINFOHEADER, so that the written header refers to - //TempImage instead of the original image - - // @TODO LUMINANCE converted to BGR insteaf of beign saved to luminance - if (iCurImage->Format != IL_BGR && iCurImage->Format != IL_BGRA && iCurImage->Format != IL_COLOUR_INDEX) { - if (iCurImage->Format == IL_RGBA) { - TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); - } else { - TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); - } - if (TempImage == NULL) - return IL_FALSE; - } else if (iCurImage->Bpc > 1) { - TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - } else { - TempImage = iCurImage; - } - - if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - ilCloseImage(TempImage); - return IL_FALSE; - } - } else { - TempData = TempImage->Data; - } - - SaveLittleUInt(0x28); // Header size - SaveLittleUInt(iCurImage->Width); - - // Removed because some image viewers don't like the negative height. - // even if it is standard. @TODO should be enabled or disabled - // usually enabled. - /*if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) - SaveLittleInt(-(ILint)iCurImage->Height); - else*/ - SaveLittleInt(TempImage->Height); - - SaveLittleUShort(1); // Number of planes - SaveLittleUShort((ILushort)((ILushort)TempImage->Bpp << 3)); // Bpp - if( compress_rle8 == IL_TRUE ) { - SaveLittleInt(1); // rle8 compression - } else { - SaveLittleInt(0); - } - SaveLittleInt(0); // Size of image (Obsolete) - SaveLittleInt(0); // (Obsolete) - SaveLittleInt(0); // (Obsolete) - - if (TempImage->Pal.PalType != IL_PAL_NONE) { - SaveLittleInt(ilGetInteger(IL_PALETTE_NUM_COLS)); // Num colours used - } else { - SaveLittleInt(0); - } - SaveLittleInt(0); // Important colour (none) - - iwrite(TempPal->Palette, 1, TempPal->PalSize); - - - if( compress_rle8 == IL_TRUE ) { - //@TODO compress and save - ILubyte *Dest = (ILubyte*)ialloc((long)((double)TempImage->SizeOfPlane*130/127)); - FileSize = ilRleCompress(TempImage->Data,TempImage->Width,TempImage->Height, - TempImage->Depth,TempImage->Bpp,Dest,IL_BMPCOMP,NULL); - iwrite(Dest,1,FileSize); - } else { - PadSize = (4 - (TempImage->Bps % 4)) % 4; - // No padding, so write data directly. - if (PadSize == 0) { - iwrite(TempData, 1, TempImage->SizeOfPlane); - } else { // Odd width, so we must pad each line. - for (i = 0; i < TempImage->SizeOfPlane; i += TempImage->Bps) { - iwrite(TempData + i, 1, TempImage->Bps); // Write data - iwrite(&Padding, 1, PadSize); // Write pad byte(s) - } - } - } - - // Write the filesize - FileSize = itellw(); - iseekw(2, IL_SEEK_SET); - SaveLittleUInt(FileSize); - - if (TempPal != &iCurImage->Pal) { - ifree(TempPal->Palette); - ifree(TempPal); - } - if (TempData != TempImage->Data) - ifree(TempData); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - iseekw(FileSize, IL_SEEK_SET); - - return IL_TRUE; -} - - -#endif//IL_NO_BMP diff --git a/DevIL/src-IL/src/il_bmp.cpp b/DevIL/src-IL/src/il_bmp.cpp new file mode 100644 index 00000000..e4719e1c --- /dev/null +++ b/DevIL/src-IL/src/il_bmp.cpp @@ -0,0 +1,1048 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 02/09/2009 +// +// Filename: src-IL/src/il_bmp.c +// +// Description: Reads from and writes to a bitmap (.bmp) file. +// +//----------------------------------------------------------------------------- + +#define IL_BMP_C + +#include "il_internal.h" +#ifndef IL_NO_BMP +#include "il_bmp.h" +#include "il_endian.h" +#include +void GetShiftFromMask(const ILuint Mask, ILuint * CONST_RESTRICT ShiftLeft, ILuint * CONST_RESTRICT ShiftRight); + +//! Checks if the file specified in FileName is a valid .bmp file. +ILboolean ilIsValidBmp(ILconst_string CONST_RESTRICT FileName) +{ + ILHANDLE BitmapFile; + ILboolean bBitmap = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("bmp"))) { + ilSetError(IL_INVALID_EXTENSION); + return bBitmap; + } + + BitmapFile = iopenr(FileName); + if (BitmapFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bBitmap; + } + + bBitmap = ilIsValidBmpF(BitmapFile); + icloser(BitmapFile); + + return bBitmap; +} + + +//! Checks if the ILHANDLE contains a valid .bmp file at the current position. +ILboolean ilIsValidBmpF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidBmp(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .bmp lump. +ILboolean ilIsValidBmpL(const void * Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidBmp(); +} + +// Internal function used to get the .bmp header from the current file. +ILboolean iGetBmpHead(BMPHEAD * const Header) +{ + Header->bfType = GetLittleUShort(); + Header->bfSize = GetLittleInt(); + Header->bfReserved = GetLittleUInt(); + Header->bfDataOff = GetLittleInt(); + Header->biSize = GetLittleInt(); + Header->biWidth = GetLittleInt(); + Header->biHeight = GetLittleInt(); + Header->biPlanes = GetLittleShort(); + Header->biBitCount = GetLittleShort(); + Header->biCompression = GetLittleInt(); + Header->biSizeImage = GetLittleInt(); + Header->biXPelsPerMeter = GetLittleInt(); + Header->biYPelsPerMeter = GetLittleInt(); + Header->biClrUsed = GetLittleInt(); + Header->biClrImportant = GetLittleInt(); + return IL_TRUE; +} + + +ILboolean iGetOS2Head(OS2_HEAD * const Header) +{ + if (iread(Header, sizeof(OS2_HEAD), 1) != 1) + return IL_FALSE; + + UShort(&Header->bfType); + UInt(&Header->biSize); + Short(&Header->xHotspot); + Short(&Header->yHotspot); + UInt(&Header->DataOff); + UInt(&Header->cbFix); + + //2003-09-01 changed to UShort according to MSDN + UShort(&Header->cx); + UShort(&Header->cy); + UShort(&Header->cPlanes); + UShort(&Header->cBitCount); + + iseek((ILint)Header->cbFix - 12, IL_SEEK_CUR); // Skip rest of header, if any. + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidBmp() +{ + BMPHEAD Head; + OS2_HEAD Os2Head; + ILboolean IsValid; + + iGetBmpHead(&Head); + iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR); // Go ahead and restore to previous state + + IsValid = iCheckBmp(&Head); + if (!IsValid) { + iGetOS2Head(&Os2Head); + iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR); + IsValid = iCheckOS2(&Os2Head); + } + return IsValid; +} + + +// Internal function used to check if the HEADER is a valid .bmp header. +ILboolean iCheckBmp (const BMPHEAD * CONST_RESTRICT Header) +{ + //if ((Header->bfType != ('B'|('M'<<8))) || ((Header->biSize != 0x28) && (Header->biSize != 0x0C))) + if ((Header->bfType != ('B'|('M'<<8))) || (Header->biSize != 0x28)) + return IL_FALSE; + if (Header->biHeight == 0 || Header->biWidth < 1) + return IL_FALSE; + if (Header->biPlanes > 1) // Not sure... + return IL_FALSE; + if(Header->biCompression != 0 && Header->biCompression != 1 && + Header->biCompression != 2 && Header->biCompression != 3) + return IL_FALSE; + if(Header->biCompression == 3 && Header->biBitCount != 16 && Header->biBitCount != 32) + return IL_FALSE; + if (Header->biBitCount != 1 && Header->biBitCount != 4 && Header->biBitCount != 8 && + Header->biBitCount != 16 && Header->biBitCount != 24 && Header->biBitCount != 32) + return IL_FALSE; + return IL_TRUE; +} + + +ILboolean iCheckOS2 (const OS2_HEAD * CONST_RESTRICT Header) +{ + if ((Header->bfType != ('B'|('M'<<8))) || (Header->DataOff < 26) || (Header->cbFix < 12)) + return IL_FALSE; + if (Header->cPlanes != 1) + return IL_FALSE; + if (Header->cx == 0 || Header->cy == 0) + return IL_FALSE; + if (Header->cBitCount != 1 && Header->cBitCount != 4 && Header->cBitCount != 8 && + Header->cBitCount != 24) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a .bmp file +ILboolean ilLoadBmp(ILconst_string FileName) { + ILHANDLE BitmapFile; + ILboolean bBitmap = IL_FALSE; + + BitmapFile = iopenr(FileName); + if (BitmapFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bBitmap; + } + + bBitmap = ilLoadBmpF(BitmapFile); + icloser(BitmapFile); + + return bBitmap; +} + + +//! Reads an already-opened .bmp file +ILboolean ilLoadBmpF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadBitmapInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .bmp +ILboolean ilLoadBmpL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadBitmapInternal(); +} + + +// Internal function used to load the .bmp. +ILboolean iLoadBitmapInternal() +{ + BMPHEAD Header; + OS2_HEAD Os2Head; + ILboolean bBitmap; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iGetBmpHead(&Header); + if (!iCheckBmp(&Header)) { + iseek(-(ILint)sizeof(BMPHEAD), IL_SEEK_CUR); + iGetOS2Head(&Os2Head); + if (!iCheckOS2(&Os2Head)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + else { + return iGetOS2Bmp(&Os2Head); + } + } + + // Don't know what to do if it has more than one plane... + if (Header.biPlanes != 1) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + switch (Header.biCompression) + { + case 0: // No compression + case 3: // BITFIELDS compression is handled in 16 bit + // and 32 bit code in ilReadUncompBmp() + bBitmap = ilReadUncompBmp(&Header); + break; + case 1: // RLE 8-bit / pixel (BI_RLE8) + bBitmap = ilReadRLE8Bmp(&Header); + break; + case 2: // RLE 4-bit / pixel (BI_RLE4) + bBitmap = ilReadRLE4Bmp(&Header); + break; + + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ilFixImage()) + return IL_FALSE; + + return bBitmap; +} + + +// Reads an uncompressed .bmp +// One of the absolute ugliest functions I've ever written! +ILboolean ilReadUncompBmp(BMPHEAD * Header) +{ + ILuint i, j, k, c, Read; + ILubyte Bpp, ByteData, PadSize, Padding[4]; + ILuint rMask, gMask, bMask; //required for bitfields packing + ILuint rShiftR, gShiftR, bShiftR; //required for bitfields packing + ILuint rShiftL, gShiftL, bShiftL; //required for bitfields packing + ILushort Read16; //used for 16bit bmp loading + + if (Header->biBitCount < 8) + Bpp = 1; // We can't have an integral number less than one and greater than 0 + else + Bpp = (ILubyte)(Header->biBitCount >> 3); // Convert to bytes per pixel + + if(Bpp == 2 || Bpp == 4) + Bpp = 3; + + // Update the current image with the new dimensions + if (!ilTexImage(Header->biWidth, abs(Header->biHeight), 1, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + switch (Header->biBitCount) + { + case 1: + //iCurImage->Format = IL_LUMINANCE; + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalType = IL_PAL_BGR32; + iCurImage->Pal.PalSize = 2 * 4; + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + break; + + case 4: + case 8: + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalType = IL_PAL_BGR32; + + // if there are 256 colors biClrUsed is 0 + iCurImage->Pal.PalSize = Header->biClrUsed ? + Header->biClrUsed * 4 : 256 * 4; + + if (Header->biBitCount == 4) // biClrUsed is 0 for 4-bit bitmaps + iCurImage->Pal.PalSize = 16 * 4; + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + break; + + case 16: + case 24: + case 32: + iCurImage->Format = IL_BGR; + break; + + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + // A height of 0 is illegal + if (Header->biHeight == 0) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + if (iCurImage->Pal.Palette) + ifree(iCurImage->Pal.Palette); + return IL_FALSE; + } + + // If the image height is negative, then the image is flipped + // (Normal is IL_ORIGIN_LOWER_LEFT) + if (Header->biHeight < 0) { + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + } + else { + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + } + + // Read the palette + iseek(sizeof(BMPHEAD), IL_SEEK_SET); + if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) + return IL_FALSE; + + // Seek to the data from the "beginning" of the file + iseek(Header->bfDataOff, IL_SEEK_SET); + + // We have to handle 1 and 4-bit images separately, because we have to expand them. + switch (Header->biBitCount) + { + case 1: + //changed 2003-09-01 + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->Width / 8 * iCurImage->Height); + + PadSize = ((32 - (iCurImage->Width % 32)) / 8) % 4; // Has to truncate + for (j = 0; j < iCurImage->Height; j++) { + Read = 0; + for (i = 0; i < iCurImage->Width; ) { + if (iread(&ByteData, 1, 1) != 1) { + iUnCache(); + return IL_FALSE; + } + Read++; + k = 128; + for (c = 0; c < 8; c++) { + iCurImage->Data[j * iCurImage->Width + i] = + (!!(ByteData & k) == 1 ? 1 : 0); + k >>= 1; + if (++i >= iCurImage->Width) + break; + } + } + //iseek(PadSize, IL_SEEK_CUR); + iread(Padding, 1, PadSize); + } + + iUnCache(); + break; + + case 4: + //changed 2003-09-01 + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->Width / 2 * iCurImage->Height); + + PadSize = ((8 - (iCurImage->Width % 8)) / 2) % 4; // Has to truncate + for (j = 0; j < iCurImage->Height; j++) { + for (i = 0; i < iCurImage->Width; i++) { + if (iread(&ByteData, 1, 1) != 1) { + iUnCache(); + return IL_FALSE; + } + iCurImage->Data[j * iCurImage->Width + i] = ByteData >> 4; + if (++i == iCurImage->Width) + break; + iCurImage->Data[j * iCurImage->Width + i] = ByteData & 0x0F; + } + iread(Padding, 1, PadSize);//iseek(PadSize, IL_SEEK_CUR); + } + + iUnCache(); + break; + + case 16: + //padding + //2003-09-09: changed iCurImage->Bps to iCurImage->Width*2, + //because iCurImage->Bps refers to the 24 bit devil image + PadSize = (4 - (iCurImage->Width*2 % 4)) % 4; + + //check if bitfield compression is used + rMask = 0x7C00; + gMask = 0x03E0; + bMask = 0x001F; + rShiftR = 10; + gShiftR = 5; + bShiftR = 0; + rShiftL = 3; + gShiftL = 3; + bShiftL = 3; + if (Header->biCompression == 3) //bitfields + { + iseek(Header->bfDataOff - 12, IL_SEEK_SET); //seek to bitfield data + iread(&rMask, 4, 1); + iread(&gMask, 4, 1); + iread(&bMask, 4, 1); + UInt(&rMask); + UInt(&gMask); + UInt(&bMask); + GetShiftFromMask(rMask, &rShiftL, &rShiftR); + GetShiftFromMask(gMask, &gShiftL, &gShiftR); + GetShiftFromMask(bMask, &bShiftL, &bShiftR); + } + + k = 0; + + //changed 2003-09-01 + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->Width * iCurImage->Height); + + //@TODO: This may not be safe for Big Endian. + for (j = 0; j < iCurImage->Height; j++) { + for(i = 0; i < iCurImage->Width; i++, k += 3) { + if (iread(&Read16, 2, 1) != 1) { + iUnCache(); + return IL_FALSE; + } + iCurImage->Data[k] = ((Read16 & bMask) >> bShiftR) << bShiftL; + iCurImage->Data[k + 1] = ((Read16 & gMask) >> gShiftR) << gShiftL; + iCurImage->Data[k + 2] = ((Read16 & rMask) >> rShiftR) << rShiftL; + } + iread(Padding, 1, PadSize); + } + + iUnCache(); + break; + + case 8: + case 24: + // For 8 and 24 bit, Bps is equal to the bmps bps + PadSize = (4 - (iCurImage->Bps % 4)) % 4; + if (PadSize == 0) { + if (iread(iCurImage->Data, 1, iCurImage->SizeOfPlane) != iCurImage->SizeOfPlane) + return IL_FALSE; + } + else { // Microsoft requires lines to be padded if the widths aren't multiples of 4. + //changed 2003-09-01 + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->Width * iCurImage->Height); + + PadSize = (4 - (iCurImage->Bps % 4)); + for (i = 0; i < iCurImage->SizeOfPlane; i += iCurImage->Bps) { + if (iread(iCurImage->Data + i, 1, iCurImage->Bps) != iCurImage->Bps) { + iUnCache(); + return IL_FALSE; + } + //iseek(PadSize, IL_SEEK_CUR); + iread(Padding, 1, PadSize); + } + + iUnCache(); + } + break; + + case 32: + //32bit files are always padded to 4 byte... + //check if bitfield compression is used + rMask = 0xFF0000; + gMask = 0x00FF00; + bMask = 0x0000FF; + rShiftR = 16; + gShiftR = 8; + bShiftR = 0; + rShiftL = 0; + gShiftL = 0; + bShiftL = 0; + if (Header->biCompression == 3) //bitfields + { + iseek(Header->bfDataOff - 12, IL_SEEK_SET); //seek to bitfield data + iread(&rMask, 4, 1); + iread(&gMask, 4, 1); + iread(&bMask, 4, 1); + UInt(&rMask); + UInt(&gMask); + UInt(&bMask); + GetShiftFromMask(rMask, &rShiftL, &rShiftR); + GetShiftFromMask(gMask, &gShiftL, &gShiftR); + GetShiftFromMask(bMask, &bShiftL, &bShiftR); + } + + //TODO: win98 supports per-pixel alpha, so + //load to rgba???? + + //changed 2003-09-01 + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->Width * iCurImage->Height); + + for(i = 0; i < iCurImage->SizeOfData; i += 3) { + if (iread(&Read, 4, 1) != 1) { + iUnCache(); + return IL_FALSE; + } + + iCurImage->Data[i] = ((Read & bMask) >> bShiftR) << bShiftL; + iCurImage->Data[i + 1] = ((Read & gMask) >> gShiftR) << gShiftL; + iCurImage->Data[i + 2] = ((Read & rMask) >> rShiftR) << rShiftL; + } + + iUnCache(); + break; + + default: + return IL_FALSE; //shouldn't happen, we checked that before + } + + return IL_TRUE; +} + + +ILboolean ilReadRLE8Bmp(BMPHEAD *Header) +{ + ILubyte Bytes[2]; + size_t offset = 0, count, endOfLine = Header->biWidth; + + // Update the current image with the new dimensions + if (!ilTexImage(Header->biWidth, abs(Header->biHeight), 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + // A height of 0 is illegal + if (Header->biHeight == 0) + return IL_FALSE; + + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalType = IL_PAL_BGR32; + iCurImage->Pal.PalSize = Header->biClrUsed * 4; // 256 * 4 for most images + if (iCurImage->Pal.PalSize == 0) + iCurImage->Pal.PalSize = 256 * 4; + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) + return IL_FALSE; + + // If the image height is negative, then the image is flipped + // (Normal is IL_ORIGIN_LOWER_LEFT) + iCurImage->Origin = Header->biHeight < 0 ? + IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT; + + // Read the palette + iseek(sizeof(BMPHEAD), IL_SEEK_SET); + if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) + return IL_FALSE; + + // Seek to the data from the "beginning" of the file + iseek(Header->bfDataOff, IL_SEEK_SET); + + while (offset < iCurImage->SizeOfData) { + if (iread(Bytes, sizeof(Bytes), 1) != 1) + return IL_FALSE; + if (Bytes[0] == 0x00) { // Escape sequence + switch (Bytes[1]) + { + case 0x00: // End of line + offset = endOfLine; + endOfLine += iCurImage->Width; + break; + case 0x01: // End of bitmap + offset = iCurImage->SizeOfData; + break; + case 0x2: + if (iread(Bytes, sizeof(Bytes), 1) != 1) + return IL_FALSE; + offset += Bytes[0] + Bytes[1] * iCurImage->Width; + endOfLine += Bytes[1] * iCurImage->Width; + break; + default: + count = IL_MIN(Bytes[1], iCurImage->SizeOfData-offset); + if (iread(iCurImage->Data + offset, (ILuint)count, 1) != 1) + return IL_FALSE; + offset += count; + if ((count & 1) == 1) // Must be on a word boundary + if (iread(Bytes, 1, 1) != 1) + return IL_FALSE; + break; + } + } else { + count = IL_MIN (Bytes[0], iCurImage->SizeOfData-offset); + memset(iCurImage->Data + offset, Bytes[1], count); + offset += count; + } + } + return IL_TRUE; +} + + +//changed 2003-09-01 +//deleted ilReadRLE8Bmp() USE_POINTER version + +ILboolean ilReadRLE4Bmp(BMPHEAD *Header) +{ + ILubyte Bytes[2]; + ILuint i; + size_t offset = 0, count, endOfLine = Header->biWidth; + + // Update the current image with the new dimensions + if (!ilTexImage(Header->biWidth, abs(Header->biHeight), 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + // A height of 0 is illegal + if (Header->biHeight == 0) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalType = IL_PAL_BGR32; + iCurImage->Pal.PalSize = 16 * 4; //Header->biClrUsed * 4; // 16 * 4 for most images + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) + return IL_FALSE; + + // If the image height is negative, then the image is flipped + // (Normal is IL_ORIGIN_LOWER_LEFT) + iCurImage->Origin = Header->biHeight < 0 ? + IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT; + + // Read the palette + iseek(sizeof(BMPHEAD), IL_SEEK_SET); + + if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) + return IL_FALSE; + + // Seek to the data from the "beginning" of the file + iseek(Header->bfDataOff, IL_SEEK_SET); + + while (offset < iCurImage->SizeOfData) { + int align; + if (iread(&Bytes[0], sizeof(Bytes), 1) != 1) + return IL_FALSE; + if (Bytes[0] == 0x0) { // Escape sequence + switch (Bytes[1]) { + case 0x0: // End of line + offset = endOfLine; + endOfLine += iCurImage->Width; + break; + case 0x1: // End of bitmap + offset = iCurImage->SizeOfData; + break; + case 0x2: + if (iread(&Bytes[0], sizeof(Bytes), 1) != 1) + return IL_FALSE; + offset += Bytes[0] + Bytes[1] * iCurImage->Width; + endOfLine += Bytes[1] * iCurImage->Width; + break; + default: // Run of pixels + count = IL_MIN (Bytes[1], iCurImage->SizeOfData-offset); + + for (i = 0; i < count; i++) { + int byte; + + if ((i & 0x01) == 0) { + if (iread(&Bytes[0], sizeof(Bytes[0]), 1) != 1) + return IL_FALSE; + byte = (Bytes[0] >> 4); + } + else + byte = (Bytes[0] & 0x0F); + iCurImage->Data[offset++] = byte; + } + + align = Bytes[1] % 4; + + if (align == 1 || align == 2) // Must be on a word boundary + if (iread(&Bytes[0], sizeof(Bytes[0]), 1) != 1) + return IL_FALSE; + } + } else { + count = IL_MIN (Bytes[0], iCurImage->SizeOfData-offset); + Bytes[0] = (Bytes[1] >> 4); + Bytes[1] &= 0x0F; + for (i = 0; i < count; i++) + iCurImage->Data[offset++] = Bytes [i & 1]; + } + } + + return IL_TRUE; +} + + +//changed 2003-09-01 +//deleted ilReadRLE4Bmp() USE_POINTER version + +ILboolean iGetOS2Bmp(OS2_HEAD *Header) +{ + ILuint PadSize, Read, i, j, k, c; + ILubyte ByteData; + + if (Header->cBitCount == 1) { + if (!ilTexImage(Header->cx, Header->cy, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(2 * 3); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + iCurImage->Pal.PalSize = 2 * 3; + iCurImage->Pal.PalType = IL_PAL_BGR24; + + if (iread(iCurImage->Pal.Palette, 1, 2 * 3) != 6) + return IL_FALSE; + + PadSize = ((32 - (iCurImage->Width % 32)) / 8) % 4; // Has to truncate. + iseek(Header->DataOff, IL_SEEK_SET); + + for (j = 0; j < iCurImage->Height; j++) { + Read = 0; + for (i = 0; i < iCurImage->Width; ) { + if (iread(&ByteData, 1, 1) != 1) + return IL_FALSE; + Read++; + k = 128; + for (c = 0; c < 8; c++) { + iCurImage->Data[j * iCurImage->Width + i] = + (!!(ByteData & k) == 1 ? 1 : 0); + k >>= 1; + if (++i >= iCurImage->Width) + break; + } + } + iseek(PadSize, IL_SEEK_CUR); + } + return IL_TRUE; + } + + if (Header->cBitCount == 4) { + if (!ilTexImage(Header->cx, Header->cy, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + iCurImage->Pal.PalSize = 16 * 3; + iCurImage->Pal.PalType = IL_PAL_BGR24; + + if (iread(iCurImage->Pal.Palette, 1, 16 * 3) != 16*3) + return IL_FALSE; + + PadSize = ((8 - (iCurImage->Width % 8)) / 2) % 4; // Has to truncate + iseek(Header->DataOff, IL_SEEK_SET); + + for (j = 0; j < iCurImage->Height; j++) { + for (i = 0; i < iCurImage->Width; i++) { + if (iread(&ByteData, 1, 1) != 1) + return IL_FALSE; + iCurImage->Data[j * iCurImage->Width + i] = ByteData >> 4; + if (++i == iCurImage->Width) + break; + iCurImage->Data[j * iCurImage->Width + i] = ByteData & 0x0F; + } + iseek(PadSize, IL_SEEK_CUR); + } + + return IL_TRUE; + } + + if (Header->cBitCount == 8) { + //added this line 2003-09-01...strange no-one noticed before... + if (!ilTexImage(Header->cx, Header->cy, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(256 * 3); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + iCurImage->Pal.PalSize = 256 * 3; + iCurImage->Pal.PalType = IL_PAL_BGR24; + + if (iread(iCurImage->Pal.Palette, 1, 256 * 3) != 256*3) + return IL_FALSE; + } + else { //has to be 24 bpp + if (!ilTexImage(Header->cx, Header->cy, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + iseek(Header->DataOff, IL_SEEK_SET); + + PadSize = (4 - (iCurImage->Bps % 4)) % 4; + if (PadSize == 0) { + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) + return IL_FALSE; + } + else { + for (i = 0; i < iCurImage->Height; i++) { + if (iread(iCurImage->Data + i * iCurImage->Bps, 1, iCurImage->Bps) != iCurImage->Bps) + return IL_FALSE; + iseek(PadSize, IL_SEEK_CUR); + } + } + + return IL_TRUE; +} + + +//! Writes a Bmp file +ILboolean ilSaveBmp(const ILstring FileName) +{ + ILHANDLE BitmapFile; + ILuint BitmapSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + BitmapFile = iopenw(FileName); + if (BitmapFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + BitmapSize = ilSaveBmpF(BitmapFile); + iclosew(BitmapFile); + + if (BitmapSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Bmp to an already-opened file +ILuint ilSaveBmpF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveBitmapInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Bmp to a memory "lump" +ILuint ilSaveBmpL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveBitmapInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the .bmp. +ILboolean iSaveBitmapInternal() +{ + //int compress_rle8 = ilGetInteger(IL_BMP_RLE); + int compress_rle8 = IL_FALSE; // disabled BMP RLE compression. broken + ILuint FileSize, i, PadSize, Padding = 0; + ILimage *TempImage = NULL; + ILpal *TempPal; + ILubyte *TempData; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iputc('B'); // Comprises the + iputc('M'); // "signature" + + SaveLittleUInt(0); // Will come back and change later in this function (filesize) + SaveLittleUInt(0); // Reserved + + if (compress_rle8 == IL_TRUE) + { + TempImage = iConvertImage(iCurImage, IL_COLOR_INDEX, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + TempPal = iConvertPal(&TempImage->Pal, IL_PAL_BGR32); + if (TempPal == NULL) + { + ilCloseImage(TempImage); + return IL_FALSE; + } + } + + // If the current image has a palette, take care of it + TempPal = &iCurImage->Pal; + if( iCurImage->Pal.PalSize && iCurImage->Pal.Palette && iCurImage->Pal.PalType != IL_PAL_NONE ) { + // If the palette in .bmp format, write it directly + if (iCurImage->Pal.PalType == IL_PAL_BGR32) { + TempPal = &iCurImage->Pal; + } else { + TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_BGR32); + if (TempPal == NULL) { + return IL_FALSE; + } + } + } + + SaveLittleUInt(54 + TempPal->PalSize); // Offset of the data + + //Changed 20040923: moved this block above writing of + //BITMAPINFOHEADER, so that the written header refers to + //TempImage instead of the original image + + // @TODO LUMINANCE converted to BGR insteaf of beign saved to luminance + if (iCurImage->Format != IL_BGR && iCurImage->Format != IL_BGRA && iCurImage->Format != IL_COLOUR_INDEX) { + if (iCurImage->Format == IL_RGBA) { + TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); + } else { + TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); + } + if (TempImage == NULL) + return IL_FALSE; + } else if (iCurImage->Bpc > 1) { + TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + } else { + TempImage = iCurImage; + } + + if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + ilCloseImage(TempImage); + return IL_FALSE; + } + } else { + TempData = TempImage->Data; + } + + SaveLittleUInt(0x28); // Header size + SaveLittleUInt(iCurImage->Width); + + // Removed because some image viewers don't like the negative height. + // even if it is standard. @TODO should be enabled or disabled + // usually enabled. + /*if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) + SaveLittleInt(-(ILint)iCurImage->Height); + else*/ + SaveLittleInt(TempImage->Height); + + SaveLittleUShort(1); // Number of planes + SaveLittleUShort((ILushort)((ILushort)TempImage->Bpp << 3)); // Bpp + if( compress_rle8 == IL_TRUE ) { + SaveLittleInt(1); // rle8 compression + } else { + SaveLittleInt(0); + } + SaveLittleInt(0); // Size of image (Obsolete) + SaveLittleInt(0); // (Obsolete) + SaveLittleInt(0); // (Obsolete) + + if (TempImage->Pal.PalType != IL_PAL_NONE) { + SaveLittleInt(ilGetInteger(IL_PALETTE_NUM_COLS)); // Num colours used + } else { + SaveLittleInt(0); + } + SaveLittleInt(0); // Important colour (none) + + iwrite(TempPal->Palette, 1, TempPal->PalSize); + + + if( compress_rle8 == IL_TRUE ) { + //@TODO compress and save + ILubyte *Dest = (ILubyte*)ialloc((long)((double)TempImage->SizeOfPlane*130/127)); + FileSize = ilRleCompress(TempImage->Data,TempImage->Width,TempImage->Height, + TempImage->Depth,TempImage->Bpp,Dest,IL_BMPCOMP,NULL); + iwrite(Dest,1,FileSize); + } else { + PadSize = (4 - (TempImage->Bps % 4)) % 4; + // No padding, so write data directly. + if (PadSize == 0) { + iwrite(TempData, 1, TempImage->SizeOfPlane); + } else { // Odd width, so we must pad each line. + for (i = 0; i < TempImage->SizeOfPlane; i += TempImage->Bps) { + iwrite(TempData + i, 1, TempImage->Bps); // Write data + iwrite(&Padding, 1, PadSize); // Write pad byte(s) + } + } + } + + // Write the filesize + FileSize = itellw(); + iseekw(2, IL_SEEK_SET); + SaveLittleUInt(FileSize); + + if (TempPal != &iCurImage->Pal) { + ifree(TempPal->Palette); + ifree(TempPal); + } + if (TempData != TempImage->Data) + ifree(TempData); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + iseekw(FileSize, IL_SEEK_SET); + + return IL_TRUE; +} + + +#endif//IL_NO_BMP diff --git a/DevIL/src-IL/src/il_convbuff.c b/DevIL/src-IL/src/il_convbuff.c deleted file mode 100644 index c9e0d508..00000000 --- a/DevIL/src-IL/src/il_convbuff.c +++ /dev/null @@ -1,2315 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 01/08/2007 -// -// Filename: src-IL/src/il_convbuff.c -// -// Description: Converts between several image formats -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifdef ALTIVEC_GCC -#include "altivec_typeconversion.h" -#endif -#include - - -void* ILAPIENTRY iSwitchTypes(ILuint SizeOfData, ILenum SrcType, ILenum DestType, void *Buffer); - -//ILushort ILAPIENTRY ilFloatToHalf(ILuint i); -//ILuint ILAPIENTRY ilHalfToFloat (ILushort y); -//ILfloat /*ILAPIENTRY*/ ilFloatToHalfOverflow(); - -ILimage *iConvertPalette(ILimage *Image, ILenum DestFormat); - -#define CHECK_ALLOC() if (NewData == NULL) { \ - if (Data != Buffer) \ - ifree(Data); \ - return IL_FALSE; \ - } - -ILAPI void* ILAPIENTRY ilConvertBuffer(ILuint SizeOfData, ILenum SrcFormat, ILenum DestFormat, ILenum SrcType, ILenum DestType, ILpal *SrcPal, void *Buffer) -{ - //static const ILfloat LumFactor[3] = { 0.299f, 0.587f, 0.114f }; // Used for conversion to luminance - //static const ILfloat LumFactor[3] = { 0.3086f, 0.6094f, 0.0820f }; // http://www.sgi.com/grafica/matrix/index.html - static const ILfloat LumFactor[3] = { 0.212671f, 0.715160f, 0.072169f }; // http://www.inforamp.net/~poynton/ and libpng's libpng.txt - - ILubyte *NewData = NULL; - ILuint i, j, c, Size; - ILfloat Resultf; - ILdouble Resultd; - ILuint NumPix; // Really number of pixels * bpp. - ILuint BpcDest; - void *Data = NULL; - ILimage *PalImage = NULL, *TempImage = NULL; - - if (SizeOfData == 0 || Buffer == NULL) { - ilSetError(IL_INVALID_PARAM); - return NULL; - } - - Data = iSwitchTypes(SizeOfData, SrcType, DestType, Buffer); - if (Data == NULL) - return NULL; - - BpcDest = ilGetBpcType(DestType); - NumPix = SizeOfData / ilGetBpcType(SrcType); - - if (DestFormat == SrcFormat) { - NewData = (ILubyte*)ialloc(NumPix * BpcDest); - if (NewData == NULL) { - return IL_FALSE; - } - memcpy(NewData, Data, NumPix * BpcDest); - if (Data != Buffer) - ifree(Data); - - return NewData; - } - - // Colour-indexed images are special here - if (SrcFormat == IL_COLOUR_INDEX) { - // We create a temporary palette image so that we can send it to iConvertPalette. - PalImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0. - if (PalImage == NULL) - return NULL; - // Populate the temporary palette image. - PalImage->Pal.Palette = SrcPal->Palette; - PalImage->Pal.PalSize = SrcPal->PalSize; - PalImage->Pal.PalType = SrcPal->PalType; - PalImage->Width = NumPix; - PalImage->Height = 1; - PalImage->Depth = 1; - PalImage->Format = IL_COLOUR_INDEX; - PalImage->Type = IL_UNSIGNED_BYTE; - PalImage->Data = Buffer; - PalImage->Bpp = 1; - PalImage->SizeOfData = SizeOfData; - - // Convert the paletted image to a different format. - TempImage = iConvertPalette(PalImage, DestFormat); - if (TempImage == NULL) { - // So that we do not delete the original palette or data. - PalImage->Pal.Palette = NULL; - PalImage->Data = NULL; - ilCloseImage(PalImage); - return NULL; - } - - // Set TempImage->Data to NULL so that we can preserve it via NewData, or - // else it would get wiped out by ilCloseImage. - NewData = TempImage->Data; - TempImage->Data = NULL; - // So that we do not delete the original palette or data. - PalImage->Pal.Palette = NULL; - PalImage->Data = NULL; - - // Clean up here. - ilCloseImage(PalImage); - ilCloseImage(TempImage); - return NewData; - } - - switch (SrcFormat) - { - case IL_RGB: - switch (DestFormat) - { - case IL_BGR: - NewData = (ILubyte*)ialloc(NumPix * BpcDest); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - #ifdef ALTIVEC_GCC - abc2cba_byte((ILubyte*)Data,NumPix * BpcDest,NewData); - #else - for (i = 0; i < NumPix; i += 3) { - NewData[i] = ((ILubyte*)(Data))[i+2]; - NewData[i+1] = ((ILubyte*)(Data))[i+1]; - NewData[i+2] = ((ILubyte*)(Data))[i]; - } - #endif - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - #ifdef ALTIVEC_GCC - abc2cba_short((ILushort*)Data,NumPix * BpcDest,(ILushort*)NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; - } - #endif - break; - case IL_UNSIGNED_INT: - case IL_INT: - #ifdef ALTIVEC_GCC - abc2cba_int((ILuint*)Data,NumPix * BpcDest,(ILuint*)NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; - } - #endif - break; - case IL_FLOAT: - #ifdef ALTIVEC_GCC - abc2cba_float(Data,NumPix * BpcDest,NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; - } - #endif - break; - case IL_DOUBLE: - #ifdef ALTIVEC_GCC - abc2cba_double((ILdouble*)Data,NumPix * BpcDest,(ILdouble*)NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; - } - break; - #endif - } - break; - - case IL_RGBA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - NewData[j] = ((ILubyte*)(Data))[i]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i+2]; - NewData[j+3] = UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[j+3] = USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[j+3] = UINT_MAX; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[j+3] = 1.0f; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[j+3] = 1.0; - } - break; - } - break; - - case IL_BGRA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - NewData[j] = ((ILubyte*)(Data))[i+2]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i]; - NewData[j+3] = UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[j+3] = USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[j+3] = UINT_MAX; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[j+3] = 1.0f; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[j+3] = 1.0f; - } - break; - } - break; - - case IL_LUMINANCE: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); - CHECK_ALLOC(); - Size = NumPix / 3; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[c]; - } - NewData[i] = (ILubyte)Resultf; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILushort*)(NewData))[i] = (ILushort)Resultf; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILuint*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILuint*)(NewData))[i] = (ILuint)Resultf; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILfloat*)(NewData))[i] = Resultf; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - Resultd = 0; - for (c = 0; c < 3; c++) { - Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILdouble*)(NewData))[i] = Resultd; - } - break; - } - break; - - case IL_LUMINANCE_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3 * 2); - CHECK_ALLOC(); - Size = NumPix / 3; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[c]; - } - NewData[i*2] = (ILubyte)Resultf; - NewData[i*2+1] = UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILushort*)(NewData))[i*2] = (ILushort)Resultf; - ((ILushort*)(NewData))[i*2+1] = USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILuint*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILuint*)(NewData))[i*2] = (ILuint)Resultf; - ((ILuint*)(NewData))[i*2+1] = UINT_MAX; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILfloat*)(NewData))[i*2] = Resultf; - ((ILfloat*)(NewData))[i*2+1] = 1.0f; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - Resultd = 0; - for (c = 0; c < 3; c++) { - Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILdouble*)(NewData))[i*2] = Resultd; - ((ILdouble*)(NewData))[i*2+1] = 1.0; - } - break; - } - break; - - case IL_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); - CHECK_ALLOC(); - memset(NewData, 0, NumPix * BpcDest); - break; - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - - case IL_RGBA: - switch (DestFormat) - { - case IL_BGRA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - #ifdef ALTIVEC_GCC - abcd2cbad_byte(NewData,iCurImage->SizeOfData,NewData); - #else - for (i = 0; i < NumPix; i += 4) { - NewData[i] = ((ILubyte*)(Data))[i+2]; - NewData[i+1] = ((ILubyte*)(Data))[i+1]; - NewData[i+2] = ((ILubyte*)(Data))[i]; - NewData[i+3] = ((ILubyte*)(Data))[i+3]; - } - #endif - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - #ifdef ALTIVEC_GCC - abcd2cbad_short((ILushort*)Data,iCurImage->SizeOfData,(ILushort*)NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[i+3] = ((ILushort*)(Data))[i+3]; - } - #endif - break; - case IL_UNSIGNED_INT: - case IL_INT: - #ifdef ALTIVEC_GCC - abcd2cbad_int((ILuint*)Data,iCurImage->SizeOfData,(ILuint*)NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[i+3] = ((ILuint*)(Data))[i+3]; - } - #endif - break; - case IL_FLOAT: - #ifdef ALTIVEC_GCC - abcd2cbad_float(Data,iCurImage->SizeOfData,NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[i+3] = ((ILfloat*)(Data))[i+3]; - } - #endif - break; - case IL_DOUBLE: - #ifdef ALTIVEC_GCC - abcd2cbad_double((ILdouble*)Data,iCurImage->SizeOfData,(ILdouble*)NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[i+3] = ((ILdouble*)(Data))[i+3]; - } - #endif - break; - } - break; - - case IL_RGB: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - NewData[j] = ((ILubyte*)(Data))[i]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i+2]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; - } - break; - } - break; - - case IL_BGR: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - NewData[j] = ((ILubyte*)(Data))[i+2]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; - } - break; - } - break; - - case IL_LUMINANCE: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); - CHECK_ALLOC(); - Size = NumPix / 4; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - Resultf = 0.0f; - for (c = 0; c < 3; c++) { - Resultf += ((ILubyte*)(Data))[i * 4 + c] * LumFactor[c]; - } - NewData[i] = (ILubyte)Resultf; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - Resultf = 0.0f; - for (c = 0; c < 3; c++) { - Resultf += ((ILushort*)(Data))[i * 4 + c] * LumFactor[c]; - } - ((ILushort*)(NewData))[i] = (ILushort)Resultf; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILuint*)(Data))[i * 4 + c] * LumFactor[c]; - } - ((ILuint*)(NewData))[i] = (ILuint)Resultd; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILfloat*)(Data))[i * 4 + c] * LumFactor[c]; - } - ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILdouble*)(Data))[i * 4 + c] * LumFactor[c]; - } - ((ILdouble*)(NewData))[i] = Resultd; - } - break; - } - break; - - case IL_LUMINANCE_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4 * 2); - CHECK_ALLOC(); - Size = NumPix / 4 * 2; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i += 2) { - Resultf = 0.0f; - for (c = 0; c < 3; c++) { - Resultf += ((ILubyte*)(Data))[i * 2 + c] * LumFactor[c]; - } - NewData[i] = (ILubyte)Resultf; - NewData[i+1] = ((ILubyte*)(Data))[i * 2 + 3]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i += 2) { - Resultf = 0.0f; - for (c = 0; c < 3; c++) { - Resultf += ((ILushort*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILushort*)(NewData))[i] = (ILushort)Resultf; - ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i * 2 + 3]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i += 2) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILuint*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILuint*)(NewData))[i] = (ILuint)Resultd; - ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i * 2 + 3]; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i += 2) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILfloat*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; - ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i * 2 + 3]; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i += 2) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILdouble*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILdouble*)(NewData))[i] = Resultd; - ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i * 2 + 3]; - } - break; - } - break; - - case IL_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); - CHECK_ALLOC(); - Size = NumPix / 4; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - NewData[i] = ((ILubyte*)(Data))[i * 4 + 3]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i * 4 + 3]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i * 4 + 3]; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i * 4 + 3]; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i * 4 + 3]; - } - break; - } - break; - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - - case IL_BGR: - switch (DestFormat) - { - case IL_RGB: - NewData = (ILubyte*)ialloc(NumPix * BpcDest); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - #ifdef ALTIVEC_GCC - abc2cba_byte(((ILubyte*)Data),NumPix * BpcDest,NewData); - #else - for (i = 0; i < NumPix; i += 3) { - NewData[i] = ((ILubyte*)(Data))[i+2]; - NewData[i+1] = ((ILubyte*)(Data))[i+1]; - NewData[i+2] = ((ILubyte*)(Data))[i]; - } - #endif - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - #ifdef ALTIVEC_GCC - abc2cba_short((ILushort*)Data,NumPix * BpcDest,(ILushort*)NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; - } - #endif - break; - case IL_UNSIGNED_INT: - case IL_INT: - #ifdef ALTIVEC_GCC - abc2cba_int((ILuint*)Data,NumPix * BpcDest,(ILuint*)NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; - } - #endif - break; - case IL_FLOAT: - #ifdef ALTIVEC_GCC - abc2cba_float(Data,NumPix * BpcDest,NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; - } - #endif - break; - case IL_DOUBLE: - #ifdef ALTIVEC_GCC - abc2cba_double((ILdouble*)Data,iCurImage->SizeOfData,(ILdouble*)NewData); - #else - for (i = 0; i < NumPix; i += 3) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; - } - #endif - break; - } - break; - - case IL_BGRA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - NewData[j] = ((ILubyte*)(Data))[i]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i+2]; - NewData[j+3] = UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[j+3] = USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[j+3] = UINT_MAX; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[j+3] = 1.0f; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[j+3] = 1.0; - } - break; - } - break; - - case IL_RGBA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - NewData[j] = ((ILubyte*)(Data))[i+2]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i]; - NewData[j+3] = UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[j+3] = USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[j+3] = UINT_MAX; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[j+3] = 1.0f; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[j+3] = 1.0; - } - break; - } - break; - - case IL_LUMINANCE: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); - CHECK_ALLOC(); - Size = NumPix / 3; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - Resultf = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[j]; - } - NewData[i] = (ILubyte)Resultf; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - Resultf = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[j]; - } - ((ILushort*)(NewData))[i] = (ILushort)Resultf; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - Resultd = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultd += ((ILuint*)(Data))[i * 3 + c] * LumFactor[j]; - } - ((ILuint*)(NewData))[i] = (ILuint)Resultd; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - Resultd = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultd += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[j]; - } - ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - Resultd = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[j]; - } - ((ILdouble*)(NewData))[i] = Resultd; - } - break; - } - break; - - case IL_LUMINANCE_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3 * 2); - CHECK_ALLOC(); - Size = NumPix / 3; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[c]; - } - NewData[i*2] = (ILubyte)Resultf; - NewData[i*2+1] = UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILushort*)(NewData))[i*2] = (ILushort)Resultf; - ((ILushort*)(NewData))[i*2+1] = USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILuint*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILuint*)(NewData))[i*2] = (ILuint)Resultf; - ((ILuint*)(NewData))[i*2+1] = UINT_MAX; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - Resultf = 0; - for (c = 0; c < 3; c++) { - Resultf += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILfloat*)(NewData))[i*2] = Resultf; - ((ILfloat*)(NewData))[i*2+1] = 1.0f; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - Resultd = 0; - for (c = 0; c < 3; c++) { - Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[c]; - } - ((ILdouble*)(NewData))[i*2] = Resultd; - ((ILdouble*)(NewData))[i*2+1] = 1.0; - } - break; - } - break; - - case IL_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); - CHECK_ALLOC(); - memset(NewData, 0, NumPix * BpcDest / 3); - break; - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - - case IL_BGRA: - switch (DestFormat) - { - case IL_RGBA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - #ifdef ALTIVEC_GCC - abcd2cbad_byte(NewData,iCurImage->SizeOfData,NewData); - #else - for (i = 0; i < NumPix; i += 4) { - NewData[i] = ((ILubyte*)(Data))[i+2]; - NewData[i+1] = ((ILubyte*)(Data))[i+1]; - NewData[i+2] = ((ILubyte*)(Data))[i]; - NewData[i+3] = ((ILubyte*)(Data))[i+3]; - } - #endif - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - #ifdef ALTIVEC_GCC - abcd2cbad_short((ILushort*)Data,iCurImage->SizeOfData,(ILushort*)NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[i+3] = ((ILushort*)(Data))[i+3]; - } - #endif - break; - case IL_UNSIGNED_INT: - case IL_INT: - #ifdef ALTIVEC_GCC - abcd2cbad_int((ILuint*)NewData,iCurImage->SizeOfData,(ILuint*)NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[i+3] = ((ILuint*)(Data))[i+3]; - } - #endif - break; - case IL_FLOAT: - #ifdef ALTIVEC_GCC - abcd2cbad_float(NewData,iCurImage->SizeOfData,NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[i+3] = ((ILfloat*)(Data))[i+3]; - } - #endif - break; - case IL_DOUBLE: - #ifdef ALTIVEC_GCC - abcd2cbad_double((ILdouble*)Data,iCurImage->SizeOfData,(ILdouble*)NewData); - #else - for (i = 0; i < NumPix; i += 4) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[i+3] = ((ILdouble*)(Data))[i+3]; - } - #endif - break; - } - break; - - case IL_BGR: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - NewData[j] = ((ILubyte*)(Data))[i]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i+2]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; - } - break; - } - break; - - case IL_RGB: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); - CHECK_ALLOC(); - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - NewData[j] = ((ILubyte*)(Data))[i+2]; - NewData[j+1] = ((ILubyte*)(Data))[i+1]; - NewData[j+2] = ((ILubyte*)(Data))[i]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; - ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; - ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; - ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; - ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; - ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; - ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; - ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; - ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; - } - break; - } - break; - - case IL_LUMINANCE: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); - CHECK_ALLOC(); - Size = NumPix / 4; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - Resultf = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultf += ((ILubyte*)(Data))[i * 4 + c] * LumFactor[j]; - } - NewData[i] = (ILubyte)Resultf; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - Resultf = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultf += ((ILushort*)(Data))[i * 4 + c] * LumFactor[j]; - } - ((ILushort*)(NewData))[i] = (ILushort)Resultf; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - Resultd = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultd += ((ILuint*)(Data))[i * 4 + c] * LumFactor[j]; - } - ((ILuint*)(NewData))[i] = (ILuint)Resultd; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - Resultd = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultd += ((ILfloat*)(Data))[i * 4 + c] * LumFactor[j]; - } - ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - Resultd = 0.0f; j = 2; - for (c = 0; c < 3; c++, j--) { - Resultd += ((ILdouble*)(Data))[i * 4 + c] * LumFactor[j]; - } - ((ILdouble*)(NewData))[i] = Resultd; - } - break; - } - break; - - case IL_LUMINANCE_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4 * 2); - CHECK_ALLOC(); - Size = NumPix / 4 * 2; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i += 2) { - Resultf = 0.0f; - for (c = 0; c < 3; c++) { - Resultf += ((ILubyte*)(Data))[i * 2 + c] * LumFactor[c]; - } - NewData[i] = (ILubyte)Resultf; - NewData[i+1] = ((ILubyte*)(Data))[i * 2 + 3]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i += 2) { - Resultf = 0.0f; - for (c = 0; c < 3; c++) { - Resultf += ((ILushort*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILushort*)(NewData))[i] = (ILushort)Resultf; - ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i * 2 + 3]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i += 2) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILuint*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILuint*)(NewData))[i] = (ILuint)Resultd; - ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i * 2 + 3]; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i += 2) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILfloat*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; - ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i * 2 + 3]; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i += 2) { - Resultd = 0.0; - for (c = 0; c < 3; c++) { - Resultd += ((ILdouble*)(Data))[i * 2 + c] * LumFactor[c]; - } - ((ILdouble*)(NewData))[i] = Resultd; - ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i * 2 + 3]; - } - break; - } - break; - - case IL_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); - CHECK_ALLOC(); - Size = NumPix / 4; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - NewData[i] = ((ILubyte*)(Data))[i * 4 + 3]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i * 4 + 3]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i * 4 + 3]; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i * 4 + 3]; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i * 4 + 3]; - } - break; - } - break; - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - - - case IL_LUMINANCE: - switch (DestFormat) - { - case IL_RGB: - case IL_BGR: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i++, j += 3) { - for (c = 0; c < 3; c++) { - NewData[j + c] = ((ILubyte*)(Data))[i]; - } - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i++, j += 3) { - for (c = 0; c < 3; c++) { - ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; - } - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i++, j += 3) { - for (c = 0; c < 3; c++) { - ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; - } - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i++, j += 3) { - for (c = 0; c < 3; c++) { - ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; - } - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i++, j += 3) { - for (c = 0; c < 3; c++) { - ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; - } - } - break; - } - break; - - case IL_RGBA: - case IL_BGRA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - NewData[j + c] = ((ILubyte*)(Data))[i]; - } - NewData[j + 3] = UCHAR_MAX; // Full opacity - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; - } - ((ILushort*)(NewData))[j + 3] = USHRT_MAX; // Full opacity - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; - } - ((ILuint*)(NewData))[j + 3] = UINT_MAX; // Full opacity - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; - } - ((ILfloat*)(NewData))[j + 3] = 1.0f; // Full opacity - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; - } - ((ILdouble*)(NewData))[j + 3] = 1.0; // Full opacity - } - break; - } - break; - - case IL_LUMINANCE_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 2); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < NumPix; i++) { - NewData[i * 2] = ((ILubyte*)(Data))[i]; - NewData[i * 2 + 1] = UCHAR_MAX; // Full opacity - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < NumPix; i++) { - ((ILushort*)(NewData))[i * 2] = ((ILushort*)(Data))[i]; - ((ILushort*)(NewData))[i * 2 + 1] = USHRT_MAX; // Full opacity - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < NumPix; i++) { - ((ILuint*)(NewData))[i * 2] = ((ILuint*)(Data))[i]; - ((ILuint*)(NewData))[i * 2 + 1] = UINT_MAX; // Full opacity - } - break; - case IL_FLOAT: - for (i = 0; i < NumPix; i++) { - ((ILfloat*)(NewData))[i * 2] = ((ILfloat*)(Data))[i]; - ((ILfloat*)(NewData))[i * 2 + 1] = 1.0f; // Full opacity - } - break; - case IL_DOUBLE: - for (i = 0; i < NumPix; i++) { - ((ILdouble*)(NewData))[i * 2] = ((ILdouble*)(Data))[i]; - ((ILdouble*)(NewData))[i * 2 + 1] = 1.0; // Full opacity - } - break; - } - break; - - case IL_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest); - CHECK_ALLOC(); - memset(NewData, 0, NumPix * BpcDest); - break; - - /*case IL_COLOUR_INDEX: - NewData = (ILubyte*)ialloc(iCurImage->SizeOfData); - NewImage->Pal.Palette = (ILubyte*)ialloc(768); - if (NewData == NULL || NewImage->Pal.Palette) { - ifree(NewImage); - return IL_FALSE; - } - - // Fill the palette - for (i = 0; i < 256; i++) { - for (c = 0; c < 3; c++) { - NewImage->Pal.Palette[i * 3 + c] = (ILubyte)i; - } - } - // Copy the data - for (i = 0; i < iCurImage->SizeOfData; i++) { - NewData[i] = iCurImage->Data[i]; - } - break;*/ - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - - - case IL_LUMINANCE_ALPHA: - switch (DestFormat) - { - case IL_RGB: - case IL_BGR: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2 * 3); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { - for (c = 0; c < 3; c++) { - NewData[j + c] = ((ILubyte*)(Data))[i]; - } - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { - for (c = 0; c < 3; c++) { - ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; - } - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { - for (c = 0; c < 3; c++) { - ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; - } - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { - for (c = 0; c < 3; c++) { - ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; - } - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { - for (c = 0; c < 3; c++) { - ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; - } - } - break; - } - break; - - case IL_RGBA: - case IL_BGRA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2 * 4); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { - for (c = 0; c < 3; c++) { - NewData[j + c] = ((ILubyte*)(Data))[i]; - } - NewData[j + 3] = ((ILubyte*)(Data))[i+1]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { - for (c = 0; c < 3; c++) { - ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; - } - ((ILushort*)(NewData))[j + 3] = ((ILushort*)(Data))[i+1]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { - for (c = 0; c < 3; c++) { - ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; - } - ((ILuint*)(NewData))[j + 3] = ((ILuint*)(Data))[i+1]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { - for (c = 0; c < 3; c++) { - ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; - } - ((ILfloat*)(NewData))[j + 3] = ((ILfloat*)(Data))[i+1]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { - for (c = 0; c < 3; c++) { - ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; - } - ((ILdouble*)(NewData))[j + 3] = ((ILdouble*)(Data))[i+1]; - } - break; - } - break; - - case IL_LUMINANCE: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i += 2, j++) { - NewData[j] = ((ILubyte*)(Data))[i]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i += 2, j++) { - ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i += 2, j++) { - ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i += 2, j++) { - ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i += 2, j++) { - ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; - } - break; - } - break; - - case IL_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2); - CHECK_ALLOC(); - Size = NumPix / 2; - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - NewData[i] = ((ILubyte*)(Data))[i * 2 + 3]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < Size; i++) { - ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i * 2 + 3]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i * 2 + 3]; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i * 2 + 3]; - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i * 2 + 3]; - } - break; - } - break; - - /*case IL_COLOUR_INDEX: - NewData = (ILubyte*)ialloc(iCurImage->SizeOfData); - NewImage->Pal.Palette = (ILubyte*)ialloc(768); - if (NewData == NULL || NewImage->Pal.Palette) { - ifree(NewImage); - return IL_FALSE; - } - - // Fill the palette - for (i = 0; i < 256; i++) { - for (c = 0; c < 3; c++) { - NewImage->Pal.Palette[i * 3 + c] = (ILubyte)i; - } - } - // Copy the data - for (i = 0; i < iCurImage->SizeOfData; i++) { - NewData[i] = iCurImage->Data[i]; - } - break;*/ - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - - - case IL_ALPHA: - switch (DestFormat) - { - case IL_RGB: - case IL_BGR: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - case IL_UNSIGNED_INT: - case IL_INT: - case IL_FLOAT: - case IL_DOUBLE: - memset(NewData, 0, NumPix * BpcDest * 3); // Easy enough - break; - //@TODO: Do we need to a check for default: (error)? - } - break; - - case IL_RGBA: - case IL_BGRA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - NewData[j + c] = 0; - } - NewData[j + 3] = ((ILubyte*)(Data))[i]; // Only value that matters - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILushort*)(NewData))[j + c] = 0; - } - ((ILushort*)(NewData))[j + 3] = ((ILushort*)(Data))[i]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILuint*)(NewData))[j + c] = 0; - } - ((ILuint*)(NewData))[j + 3] = ((ILuint*)(Data))[i]; - } - break; - case IL_FLOAT: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILfloat*)(NewData))[j + c] = 0; - } - ((ILfloat*)(NewData))[j + 3] = ((ILfloat*)(Data))[i]; - } - break; - case IL_DOUBLE: - for (i = 0, j = 0; i < NumPix; i++, j += 4) { - for (c = 0; c < 3; c++) { - ((ILdouble*)(NewData))[j + c] = 0; - } - ((ILdouble*)(NewData))[j + 3] = ((ILdouble*)(Data))[i]; - } - break; - } - break; - - case IL_LUMINANCE_ALPHA: - NewData = (ILubyte*)ialloc(NumPix * BpcDest * 2); - CHECK_ALLOC(); - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < NumPix; i++) { - NewData[i * 2] = 0; - NewData[i * 2 + 1] = ((ILubyte*)(Data))[i]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - case IL_HALF: - for (i = 0; i < NumPix; i++) { - ((ILushort*)(NewData))[i * 2] = 0; - ((ILushort*)(NewData))[i * 2 + 1] = ((ILushort*)(Data))[i]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < NumPix; i++) { - ((ILuint*)(NewData))[i * 2] = 0; - ((ILuint*)(NewData))[i * 2 + 1] = ((ILuint*)(Data))[i]; - } - break; - case IL_FLOAT: - for (i = 0; i < NumPix; i++) { - ((ILfloat*)(NewData))[i * 2] = 0; - ((ILfloat*)(NewData))[i * 2 + 1] = ((ILfloat*)(Data))[i]; - } - break; - case IL_DOUBLE: - for (i = 0; i < NumPix; i++) { - ((ILdouble*)(NewData))[i * 2] = 0; - ((ILdouble*)(NewData))[i * 2 + 1] = ((ILdouble*)(Data))[i]; - } - break; - } - break; - - - /*case IL_COLOUR_INDEX: - NewData = (ILubyte*)ialloc(iCurImage->SizeOfData); - NewImage->Pal.Palette = (ILubyte*)ialloc(768); - if (NewData == NULL || NewImage->Pal.Palette) { - ifree(NewImage); - return IL_FALSE; - } - - // Fill the palette - for (i = 0; i < 256; i++) { - for (c = 0; c < 3; c++) { - NewImage->Pal.Palette[i * 3 + c] = (ILubyte)i; - } - } - // Copy the data - for (i = 0; i < iCurImage->SizeOfData; i++) { - NewData[i] = iCurImage->Data[i]; - } - break;*/ - - default: - ilSetError(IL_INVALID_CONVERSION); - if (Data != Buffer) - ifree(Data); - return NULL; - } - break; - } - - if (Data != Buffer) - ifree(Data); - - return NewData; -} - - -// Really shouldn't have to check for default, as in above ilConvertBuffer(). -// This now converts better from lower bpp to higher bpp. For example, when -// converting from 8 bpp to 16 bpp, if the value is 0xEC, the new value is 0xECEC -// instead of 0xEC00. -void* ILAPIENTRY iSwitchTypes(ILuint SizeOfData, ILenum SrcType, ILenum DestType, void *Buffer) -{ - ILuint BpcSrc, BpcDest, Size, i; - ILubyte *NewData, *BytePtr; - ILushort *ShortPtr; - ILuint *IntPtr; - ILfloat *FloatPtr, tempFloat; - ILdouble *DblPtr, tempDouble; - ILushort *HalfPtr; - - BpcSrc = ilGetBpcType(SrcType); - BpcDest = ilGetBpcType(DestType); - - if (BpcSrc == 0 || BpcDest == 0) { - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - Size = SizeOfData / BpcSrc; - - //if (BpcSrc == BpcDest) { - if (SrcType == DestType) { - return Buffer; - } - - NewData = (ILubyte*)ialloc(Size * BpcDest); - if (NewData == NULL) { - return IL_FALSE; - } - - switch (DestType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - BytePtr = (ILubyte*)NewData; - switch (SrcType) - { - case IL_UNSIGNED_SHORT: - case IL_SHORT: - for (i = 0; i < Size; i++) { - BytePtr[i] = ((ILushort*)Buffer)[i] >> 8; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - BytePtr[i] = ((ILuint*)Buffer)[i] >> 24; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - #if CLAMP_FLOATS - tempFloat = IL_CLAMP(((ILfloat*)Buffer)[i]); - BytePtr[i] = (ILubyte)(tempFloat * UCHAR_MAX); - #else - BytePtr[i] = (ILubyte)(((ILfloat*)Buffer)[i] * UCHAR_MAX); - #endif - } - break; - case IL_HALF: - for (i = 0; i < Size; i++) { - #if CLAMP_HALF - *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); - tempFloat = IL_CLAMP(tempFloat); - BytePtr[i] = (ILubyte)(tempFloat * UCHAR_MAX); - #else - *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); - BytePtr[i] = (ILubyte)(tempFloat * UCHAR_MAX); - #endif - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - #if CLAMP_DOUBLES - tempDouble = IL_CLAMP(((ILdouble*)Buffer)[i]); - BytePtr[i] = (ILubyte)(tempDouble * UCHAR_MAX); - #else - BytePtr[i] = (ILubyte)( ((ILdouble*)Buffer)[i] * UCHAR_MAX); - #endif - } - break; - } - break; - - case IL_UNSIGNED_SHORT: - case IL_SHORT: - ShortPtr = (ILushort*)NewData; - switch (SrcType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - ShortPtr[i] = (((ILubyte*)Buffer)[i] << 8) | ((ILubyte*)Buffer)[i]; - } - break; - case IL_UNSIGNED_INT: - case IL_INT: - for (i = 0; i < Size; i++) { - ShortPtr[i] = ((ILuint*)Buffer)[i] >> 16; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - #if CLAMP_FLOATS - tempFloat = IL_CLAMP(((ILfloat*)Buffer)[i]); - ShortPtr[i] = (ILushort)(tempFloat * USHRT_MAX); - #else - ShortPtr[i] = (ILushort)( ((ILfloat*)Buffer)[i] * USHRT_MAX); - #endif - } - break; - case IL_HALF: - for (i = 0; i < Size; i++) { - #if CLAMP_FLOATS - *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); - tempFloat = IL_CLAMP(tempFloat); - ShortPtr[i] = (ILushort)(tempFloat * USHRT_MAX); - #else - *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); - ShortPtr[i] = (ILushort)(tempFloat * USHRT_MAX); - #endif - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - #if CLAMP_DOUBLES - tempDouble = IL_CLAMP(((ILdouble*)Buffer)[i]); - ShortPtr[i] = (ILushort)(tempDouble * USHRT_MAX); - #else - ShortPtr[i] = (ILushort)( ((ILdouble*)Buffer)[i] * USHRT_MAX); - #endif - } - break; - } - break; - - case IL_UNSIGNED_INT: - case IL_INT: - IntPtr = (ILuint*)NewData; - switch (SrcType) - { - case IL_UNSIGNED_BYTE: - case IL_BYTE: - for (i = 0; i < Size; i++) { - IntPtr[i] = (((ILubyte*)Buffer)[i] << 24) | (((ILubyte*)Buffer)[i] << 16) | - (((ILubyte*)Buffer)[i] << 8) | ((ILubyte*)Buffer)[i]; - } - break; - case IL_UNSIGNED_SHORT: - case IL_SHORT: - for (i = 0; i < Size; i++) { - IntPtr[i] = (((ILushort*)Buffer)[i] << 16) | ((ILushort*)Buffer)[i]; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - #if CLAMP_FLOATS - tempFloat = IL_CLAMP(((ILfloat*)Buffer)[i]); - IntPtr[i] = (ILuint)(tempFloat * UINT_MAX); - #else - IntPtr[i] = (ILuint)( ((ILfloat*)Buffer)[i] * UINT_MAX); - #endif - } - break; - case IL_HALF: - for (i = 0; i < Size; i++) { - #if CLAMP_FLOATS - *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); - tempFloat = IL_CLAMP(tempFloat); - IntPtr[i] = (ILuint)(tempFloat * UINT_MAX); - #else - *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); - IntPtr[i] = (ILuint)(tempFloat * UINT_MAX); - #endif - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - #if CLAMP_DOUBLES - tempDouble = IL_CLAMP(((ILdouble*)Buffer)[i]); - IntPtr[i] = (ILuint)(tempDouble * UINT_MAX); - #else - IntPtr[i] = (ILuint)( ((ILdouble*)Buffer)[i] * UINT_MAX); - #endif - } - break; - } - break; - - // @TODO: Handle signed better. - case IL_FLOAT: - FloatPtr = (ILfloat*)NewData; - switch (SrcType) - { - case IL_UNSIGNED_BYTE: - for (i = 0; i < Size; i++) { - FloatPtr[i] = ((ILubyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; - } - break; - case IL_BYTE: - for (i = 0; i < Size; i++) { - FloatPtr[i] = ((ILbyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - for (i = 0; i < Size; i++) { - FloatPtr[i] = ((ILushort*)Buffer)[i] / (ILfloat)USHRT_MAX; - } - break; - case IL_SHORT: - for (i = 0; i < Size; i++) { - FloatPtr[i] = ((ILshort*)Buffer)[i] / (ILfloat)USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - for (i = 0; i < Size; i++) { - FloatPtr[i] = (ILfloat)((ILuint*)Buffer)[i] / (ILfloat)UINT_MAX; - } - break; - case IL_INT: - for (i = 0; i < Size; i++) { - FloatPtr[i] = (ILfloat)((ILint*)Buffer)[i] / (ILfloat)UINT_MAX; - } - break; - case IL_HALF: - for (i = 0; i < Size; i++) { - *((ILuint*)&FloatPtr[i]) = ilHalfToFloat(((ILushort*)Buffer)[i]); - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - FloatPtr[i] = (ILfloat)((ILdouble*)Buffer)[i]; - } - break; - } - break; - - case IL_DOUBLE: - DblPtr = (ILdouble*)NewData; - switch (SrcType) - { - case IL_UNSIGNED_BYTE: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILubyte*)Buffer)[i] / (ILdouble)UCHAR_MAX; - } - break; - case IL_BYTE: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILbyte*)Buffer)[i] / (ILdouble)UCHAR_MAX; - } - break; - case IL_UNSIGNED_SHORT: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILushort*)Buffer)[i] / (ILdouble)USHRT_MAX; - } - break; - case IL_SHORT: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILshort*)Buffer)[i] / (ILdouble)USHRT_MAX; - } - break; - case IL_UNSIGNED_INT: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILuint*)Buffer)[i] / (ILdouble)UINT_MAX; - } - break; - case IL_INT: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILint*)Buffer)[i] / (ILdouble)UINT_MAX; - } - break; - case IL_HALF: - for (i = 0; i < Size; i++) { - *(ILuint*)&tempFloat = ilHalfToFloat(((ILushort*)Buffer)[i]); - DblPtr[i] = tempFloat; - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - DblPtr[i] = ((ILfloat*)Buffer)[i]; - } - break; - } - break; - - case IL_HALF: - HalfPtr = (ILushort*)NewData; - switch (SrcType) - { - case IL_UNSIGNED_BYTE: - for (i = 0; i < Size; i++) { - tempFloat = ((ILubyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_BYTE: - for (i = 0; i < Size; i++) { - tempFloat = ((ILbyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_UNSIGNED_SHORT: - for (i = 0; i < Size; i++) { - tempFloat = ((ILushort*)Buffer)[i] / (ILfloat)USHRT_MAX; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_SHORT: - for (i = 0; i < Size; i++) { - tempFloat = ((ILshort*)Buffer)[i] / (ILfloat)USHRT_MAX; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_UNSIGNED_INT: - for (i = 0; i < Size; i++) { - tempFloat = ((ILuint*)Buffer)[i] / (ILfloat)UINT_MAX; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_INT: - for (i = 0; i < Size; i++) { - tempFloat = ((ILint*)Buffer)[i] / (ILfloat)UINT_MAX; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_DOUBLE: - for (i = 0; i < Size; i++) { - tempFloat = (ILfloat)((ILdouble*)Buffer)[i]; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - case IL_FLOAT: - for (i = 0; i < Size; i++) { - tempFloat = ((ILfloat*)Buffer)[i]; - *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); - } - break; - } - break; - } - - - return NewData; -} - - - - diff --git a/DevIL/src-IL/src/il_convbuff.cpp b/DevIL/src-IL/src/il_convbuff.cpp new file mode 100644 index 00000000..c9e0d508 --- /dev/null +++ b/DevIL/src-IL/src/il_convbuff.cpp @@ -0,0 +1,2315 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 01/08/2007 +// +// Filename: src-IL/src/il_convbuff.c +// +// Description: Converts between several image formats +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifdef ALTIVEC_GCC +#include "altivec_typeconversion.h" +#endif +#include + + +void* ILAPIENTRY iSwitchTypes(ILuint SizeOfData, ILenum SrcType, ILenum DestType, void *Buffer); + +//ILushort ILAPIENTRY ilFloatToHalf(ILuint i); +//ILuint ILAPIENTRY ilHalfToFloat (ILushort y); +//ILfloat /*ILAPIENTRY*/ ilFloatToHalfOverflow(); + +ILimage *iConvertPalette(ILimage *Image, ILenum DestFormat); + +#define CHECK_ALLOC() if (NewData == NULL) { \ + if (Data != Buffer) \ + ifree(Data); \ + return IL_FALSE; \ + } + +ILAPI void* ILAPIENTRY ilConvertBuffer(ILuint SizeOfData, ILenum SrcFormat, ILenum DestFormat, ILenum SrcType, ILenum DestType, ILpal *SrcPal, void *Buffer) +{ + //static const ILfloat LumFactor[3] = { 0.299f, 0.587f, 0.114f }; // Used for conversion to luminance + //static const ILfloat LumFactor[3] = { 0.3086f, 0.6094f, 0.0820f }; // http://www.sgi.com/grafica/matrix/index.html + static const ILfloat LumFactor[3] = { 0.212671f, 0.715160f, 0.072169f }; // http://www.inforamp.net/~poynton/ and libpng's libpng.txt + + ILubyte *NewData = NULL; + ILuint i, j, c, Size; + ILfloat Resultf; + ILdouble Resultd; + ILuint NumPix; // Really number of pixels * bpp. + ILuint BpcDest; + void *Data = NULL; + ILimage *PalImage = NULL, *TempImage = NULL; + + if (SizeOfData == 0 || Buffer == NULL) { + ilSetError(IL_INVALID_PARAM); + return NULL; + } + + Data = iSwitchTypes(SizeOfData, SrcType, DestType, Buffer); + if (Data == NULL) + return NULL; + + BpcDest = ilGetBpcType(DestType); + NumPix = SizeOfData / ilGetBpcType(SrcType); + + if (DestFormat == SrcFormat) { + NewData = (ILubyte*)ialloc(NumPix * BpcDest); + if (NewData == NULL) { + return IL_FALSE; + } + memcpy(NewData, Data, NumPix * BpcDest); + if (Data != Buffer) + ifree(Data); + + return NewData; + } + + // Colour-indexed images are special here + if (SrcFormat == IL_COLOUR_INDEX) { + // We create a temporary palette image so that we can send it to iConvertPalette. + PalImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0. + if (PalImage == NULL) + return NULL; + // Populate the temporary palette image. + PalImage->Pal.Palette = SrcPal->Palette; + PalImage->Pal.PalSize = SrcPal->PalSize; + PalImage->Pal.PalType = SrcPal->PalType; + PalImage->Width = NumPix; + PalImage->Height = 1; + PalImage->Depth = 1; + PalImage->Format = IL_COLOUR_INDEX; + PalImage->Type = IL_UNSIGNED_BYTE; + PalImage->Data = Buffer; + PalImage->Bpp = 1; + PalImage->SizeOfData = SizeOfData; + + // Convert the paletted image to a different format. + TempImage = iConvertPalette(PalImage, DestFormat); + if (TempImage == NULL) { + // So that we do not delete the original palette or data. + PalImage->Pal.Palette = NULL; + PalImage->Data = NULL; + ilCloseImage(PalImage); + return NULL; + } + + // Set TempImage->Data to NULL so that we can preserve it via NewData, or + // else it would get wiped out by ilCloseImage. + NewData = TempImage->Data; + TempImage->Data = NULL; + // So that we do not delete the original palette or data. + PalImage->Pal.Palette = NULL; + PalImage->Data = NULL; + + // Clean up here. + ilCloseImage(PalImage); + ilCloseImage(TempImage); + return NewData; + } + + switch (SrcFormat) + { + case IL_RGB: + switch (DestFormat) + { + case IL_BGR: + NewData = (ILubyte*)ialloc(NumPix * BpcDest); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + #ifdef ALTIVEC_GCC + abc2cba_byte((ILubyte*)Data,NumPix * BpcDest,NewData); + #else + for (i = 0; i < NumPix; i += 3) { + NewData[i] = ((ILubyte*)(Data))[i+2]; + NewData[i+1] = ((ILubyte*)(Data))[i+1]; + NewData[i+2] = ((ILubyte*)(Data))[i]; + } + #endif + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + #ifdef ALTIVEC_GCC + abc2cba_short((ILushort*)Data,NumPix * BpcDest,(ILushort*)NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; + } + #endif + break; + case IL_UNSIGNED_INT: + case IL_INT: + #ifdef ALTIVEC_GCC + abc2cba_int((ILuint*)Data,NumPix * BpcDest,(ILuint*)NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; + } + #endif + break; + case IL_FLOAT: + #ifdef ALTIVEC_GCC + abc2cba_float(Data,NumPix * BpcDest,NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; + } + #endif + break; + case IL_DOUBLE: + #ifdef ALTIVEC_GCC + abc2cba_double((ILdouble*)Data,NumPix * BpcDest,(ILdouble*)NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; + } + break; + #endif + } + break; + + case IL_RGBA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + NewData[j] = ((ILubyte*)(Data))[i]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i+2]; + NewData[j+3] = UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[j+3] = USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[j+3] = UINT_MAX; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[j+3] = 1.0f; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[j+3] = 1.0; + } + break; + } + break; + + case IL_BGRA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + NewData[j] = ((ILubyte*)(Data))[i+2]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i]; + NewData[j+3] = UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[j+3] = USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[j+3] = UINT_MAX; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[j+3] = 1.0f; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[j+3] = 1.0f; + } + break; + } + break; + + case IL_LUMINANCE: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); + CHECK_ALLOC(); + Size = NumPix / 3; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[c]; + } + NewData[i] = (ILubyte)Resultf; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILushort*)(NewData))[i] = (ILushort)Resultf; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILuint*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILuint*)(NewData))[i] = (ILuint)Resultf; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILfloat*)(NewData))[i] = Resultf; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + Resultd = 0; + for (c = 0; c < 3; c++) { + Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILdouble*)(NewData))[i] = Resultd; + } + break; + } + break; + + case IL_LUMINANCE_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3 * 2); + CHECK_ALLOC(); + Size = NumPix / 3; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[c]; + } + NewData[i*2] = (ILubyte)Resultf; + NewData[i*2+1] = UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILushort*)(NewData))[i*2] = (ILushort)Resultf; + ((ILushort*)(NewData))[i*2+1] = USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILuint*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILuint*)(NewData))[i*2] = (ILuint)Resultf; + ((ILuint*)(NewData))[i*2+1] = UINT_MAX; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILfloat*)(NewData))[i*2] = Resultf; + ((ILfloat*)(NewData))[i*2+1] = 1.0f; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + Resultd = 0; + for (c = 0; c < 3; c++) { + Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILdouble*)(NewData))[i*2] = Resultd; + ((ILdouble*)(NewData))[i*2+1] = 1.0; + } + break; + } + break; + + case IL_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); + CHECK_ALLOC(); + memset(NewData, 0, NumPix * BpcDest); + break; + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + + case IL_RGBA: + switch (DestFormat) + { + case IL_BGRA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + #ifdef ALTIVEC_GCC + abcd2cbad_byte(NewData,iCurImage->SizeOfData,NewData); + #else + for (i = 0; i < NumPix; i += 4) { + NewData[i] = ((ILubyte*)(Data))[i+2]; + NewData[i+1] = ((ILubyte*)(Data))[i+1]; + NewData[i+2] = ((ILubyte*)(Data))[i]; + NewData[i+3] = ((ILubyte*)(Data))[i+3]; + } + #endif + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + #ifdef ALTIVEC_GCC + abcd2cbad_short((ILushort*)Data,iCurImage->SizeOfData,(ILushort*)NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[i+3] = ((ILushort*)(Data))[i+3]; + } + #endif + break; + case IL_UNSIGNED_INT: + case IL_INT: + #ifdef ALTIVEC_GCC + abcd2cbad_int((ILuint*)Data,iCurImage->SizeOfData,(ILuint*)NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[i+3] = ((ILuint*)(Data))[i+3]; + } + #endif + break; + case IL_FLOAT: + #ifdef ALTIVEC_GCC + abcd2cbad_float(Data,iCurImage->SizeOfData,NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[i+3] = ((ILfloat*)(Data))[i+3]; + } + #endif + break; + case IL_DOUBLE: + #ifdef ALTIVEC_GCC + abcd2cbad_double((ILdouble*)Data,iCurImage->SizeOfData,(ILdouble*)NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[i+3] = ((ILdouble*)(Data))[i+3]; + } + #endif + break; + } + break; + + case IL_RGB: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + NewData[j] = ((ILubyte*)(Data))[i]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i+2]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; + } + break; + } + break; + + case IL_BGR: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + NewData[j] = ((ILubyte*)(Data))[i+2]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; + } + break; + } + break; + + case IL_LUMINANCE: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); + CHECK_ALLOC(); + Size = NumPix / 4; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + Resultf = 0.0f; + for (c = 0; c < 3; c++) { + Resultf += ((ILubyte*)(Data))[i * 4 + c] * LumFactor[c]; + } + NewData[i] = (ILubyte)Resultf; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + Resultf = 0.0f; + for (c = 0; c < 3; c++) { + Resultf += ((ILushort*)(Data))[i * 4 + c] * LumFactor[c]; + } + ((ILushort*)(NewData))[i] = (ILushort)Resultf; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILuint*)(Data))[i * 4 + c] * LumFactor[c]; + } + ((ILuint*)(NewData))[i] = (ILuint)Resultd; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILfloat*)(Data))[i * 4 + c] * LumFactor[c]; + } + ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILdouble*)(Data))[i * 4 + c] * LumFactor[c]; + } + ((ILdouble*)(NewData))[i] = Resultd; + } + break; + } + break; + + case IL_LUMINANCE_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4 * 2); + CHECK_ALLOC(); + Size = NumPix / 4 * 2; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i += 2) { + Resultf = 0.0f; + for (c = 0; c < 3; c++) { + Resultf += ((ILubyte*)(Data))[i * 2 + c] * LumFactor[c]; + } + NewData[i] = (ILubyte)Resultf; + NewData[i+1] = ((ILubyte*)(Data))[i * 2 + 3]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i += 2) { + Resultf = 0.0f; + for (c = 0; c < 3; c++) { + Resultf += ((ILushort*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILushort*)(NewData))[i] = (ILushort)Resultf; + ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i * 2 + 3]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i += 2) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILuint*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILuint*)(NewData))[i] = (ILuint)Resultd; + ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i * 2 + 3]; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i += 2) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILfloat*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; + ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i * 2 + 3]; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i += 2) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILdouble*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILdouble*)(NewData))[i] = Resultd; + ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i * 2 + 3]; + } + break; + } + break; + + case IL_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); + CHECK_ALLOC(); + Size = NumPix / 4; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + NewData[i] = ((ILubyte*)(Data))[i * 4 + 3]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i * 4 + 3]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i * 4 + 3]; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i * 4 + 3]; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i * 4 + 3]; + } + break; + } + break; + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + + case IL_BGR: + switch (DestFormat) + { + case IL_RGB: + NewData = (ILubyte*)ialloc(NumPix * BpcDest); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + #ifdef ALTIVEC_GCC + abc2cba_byte(((ILubyte*)Data),NumPix * BpcDest,NewData); + #else + for (i = 0; i < NumPix; i += 3) { + NewData[i] = ((ILubyte*)(Data))[i+2]; + NewData[i+1] = ((ILubyte*)(Data))[i+1]; + NewData[i+2] = ((ILubyte*)(Data))[i]; + } + #endif + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + #ifdef ALTIVEC_GCC + abc2cba_short((ILushort*)Data,NumPix * BpcDest,(ILushort*)NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; + } + #endif + break; + case IL_UNSIGNED_INT: + case IL_INT: + #ifdef ALTIVEC_GCC + abc2cba_int((ILuint*)Data,NumPix * BpcDest,(ILuint*)NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; + } + #endif + break; + case IL_FLOAT: + #ifdef ALTIVEC_GCC + abc2cba_float(Data,NumPix * BpcDest,NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; + } + #endif + break; + case IL_DOUBLE: + #ifdef ALTIVEC_GCC + abc2cba_double((ILdouble*)Data,iCurImage->SizeOfData,(ILdouble*)NewData); + #else + for (i = 0; i < NumPix; i += 3) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; + } + #endif + break; + } + break; + + case IL_BGRA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + NewData[j] = ((ILubyte*)(Data))[i]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i+2]; + NewData[j+3] = UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[j+3] = USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[j+3] = UINT_MAX; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[j+3] = 1.0f; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[j+3] = 1.0; + } + break; + } + break; + + case IL_RGBA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4 / 3); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + NewData[j] = ((ILubyte*)(Data))[i+2]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i]; + NewData[j+3] = UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[j+3] = USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[j+3] = UINT_MAX; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[j+3] = 1.0f; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 3, j += 4) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[j+3] = 1.0; + } + break; + } + break; + + case IL_LUMINANCE: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); + CHECK_ALLOC(); + Size = NumPix / 3; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + Resultf = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[j]; + } + NewData[i] = (ILubyte)Resultf; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + Resultf = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[j]; + } + ((ILushort*)(NewData))[i] = (ILushort)Resultf; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + Resultd = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultd += ((ILuint*)(Data))[i * 3 + c] * LumFactor[j]; + } + ((ILuint*)(NewData))[i] = (ILuint)Resultd; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + Resultd = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultd += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[j]; + } + ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + Resultd = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[j]; + } + ((ILdouble*)(NewData))[i] = Resultd; + } + break; + } + break; + + case IL_LUMINANCE_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3 * 2); + CHECK_ALLOC(); + Size = NumPix / 3; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILubyte*)(Data))[i * 3 + c] * LumFactor[c]; + } + NewData[i*2] = (ILubyte)Resultf; + NewData[i*2+1] = UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILushort*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILushort*)(NewData))[i*2] = (ILushort)Resultf; + ((ILushort*)(NewData))[i*2+1] = USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILuint*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILuint*)(NewData))[i*2] = (ILuint)Resultf; + ((ILuint*)(NewData))[i*2+1] = UINT_MAX; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + Resultf = 0; + for (c = 0; c < 3; c++) { + Resultf += ((ILfloat*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILfloat*)(NewData))[i*2] = Resultf; + ((ILfloat*)(NewData))[i*2+1] = 1.0f; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + Resultd = 0; + for (c = 0; c < 3; c++) { + Resultd += ((ILdouble*)(Data))[i * 3 + c] * LumFactor[c]; + } + ((ILdouble*)(NewData))[i*2] = Resultd; + ((ILdouble*)(NewData))[i*2+1] = 1.0; + } + break; + } + break; + + case IL_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 3); + CHECK_ALLOC(); + memset(NewData, 0, NumPix * BpcDest / 3); + break; + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + + case IL_BGRA: + switch (DestFormat) + { + case IL_RGBA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + #ifdef ALTIVEC_GCC + abcd2cbad_byte(NewData,iCurImage->SizeOfData,NewData); + #else + for (i = 0; i < NumPix; i += 4) { + NewData[i] = ((ILubyte*)(Data))[i+2]; + NewData[i+1] = ((ILubyte*)(Data))[i+1]; + NewData[i+2] = ((ILubyte*)(Data))[i]; + NewData[i+3] = ((ILubyte*)(Data))[i+3]; + } + #endif + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + #ifdef ALTIVEC_GCC + abcd2cbad_short((ILushort*)Data,iCurImage->SizeOfData,(ILushort*)NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[i+2] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[i+3] = ((ILushort*)(Data))[i+3]; + } + #endif + break; + case IL_UNSIGNED_INT: + case IL_INT: + #ifdef ALTIVEC_GCC + abcd2cbad_int((ILuint*)NewData,iCurImage->SizeOfData,(ILuint*)NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[i+2] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[i+3] = ((ILuint*)(Data))[i+3]; + } + #endif + break; + case IL_FLOAT: + #ifdef ALTIVEC_GCC + abcd2cbad_float(NewData,iCurImage->SizeOfData,NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[i+2] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[i+3] = ((ILfloat*)(Data))[i+3]; + } + #endif + break; + case IL_DOUBLE: + #ifdef ALTIVEC_GCC + abcd2cbad_double((ILdouble*)Data,iCurImage->SizeOfData,(ILdouble*)NewData); + #else + for (i = 0; i < NumPix; i += 4) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[i+2] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[i+3] = ((ILdouble*)(Data))[i+3]; + } + #endif + break; + } + break; + + case IL_BGR: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + NewData[j] = ((ILubyte*)(Data))[i]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i+2]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i+2]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i+2]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i+2]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i+2]; + } + break; + } + break; + + case IL_RGB: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3 / 4); + CHECK_ALLOC(); + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + NewData[j] = ((ILubyte*)(Data))[i+2]; + NewData[j+1] = ((ILubyte*)(Data))[i+1]; + NewData[j+2] = ((ILubyte*)(Data))[i]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i+2]; + ((ILushort*)(NewData))[j+1] = ((ILushort*)(Data))[i+1]; + ((ILushort*)(NewData))[j+2] = ((ILushort*)(Data))[i]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i+2]; + ((ILuint*)(NewData))[j+1] = ((ILuint*)(Data))[i+1]; + ((ILuint*)(NewData))[j+2] = ((ILuint*)(Data))[i]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i+2]; + ((ILfloat*)(NewData))[j+1] = ((ILfloat*)(Data))[i+1]; + ((ILfloat*)(NewData))[j+2] = ((ILfloat*)(Data))[i]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 4, j += 3) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i+2]; + ((ILdouble*)(NewData))[j+1] = ((ILdouble*)(Data))[i+1]; + ((ILdouble*)(NewData))[j+2] = ((ILdouble*)(Data))[i]; + } + break; + } + break; + + case IL_LUMINANCE: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); + CHECK_ALLOC(); + Size = NumPix / 4; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + Resultf = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultf += ((ILubyte*)(Data))[i * 4 + c] * LumFactor[j]; + } + NewData[i] = (ILubyte)Resultf; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + Resultf = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultf += ((ILushort*)(Data))[i * 4 + c] * LumFactor[j]; + } + ((ILushort*)(NewData))[i] = (ILushort)Resultf; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + Resultd = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultd += ((ILuint*)(Data))[i * 4 + c] * LumFactor[j]; + } + ((ILuint*)(NewData))[i] = (ILuint)Resultd; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + Resultd = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultd += ((ILfloat*)(Data))[i * 4 + c] * LumFactor[j]; + } + ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + Resultd = 0.0f; j = 2; + for (c = 0; c < 3; c++, j--) { + Resultd += ((ILdouble*)(Data))[i * 4 + c] * LumFactor[j]; + } + ((ILdouble*)(NewData))[i] = Resultd; + } + break; + } + break; + + case IL_LUMINANCE_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4 * 2); + CHECK_ALLOC(); + Size = NumPix / 4 * 2; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i += 2) { + Resultf = 0.0f; + for (c = 0; c < 3; c++) { + Resultf += ((ILubyte*)(Data))[i * 2 + c] * LumFactor[c]; + } + NewData[i] = (ILubyte)Resultf; + NewData[i+1] = ((ILubyte*)(Data))[i * 2 + 3]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i += 2) { + Resultf = 0.0f; + for (c = 0; c < 3; c++) { + Resultf += ((ILushort*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILushort*)(NewData))[i] = (ILushort)Resultf; + ((ILushort*)(NewData))[i+1] = ((ILushort*)(Data))[i * 2 + 3]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i += 2) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILuint*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILuint*)(NewData))[i] = (ILuint)Resultd; + ((ILuint*)(NewData))[i+1] = ((ILuint*)(Data))[i * 2 + 3]; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i += 2) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILfloat*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILfloat*)(NewData))[i] = (ILfloat)Resultd; + ((ILfloat*)(NewData))[i+1] = ((ILfloat*)(Data))[i * 2 + 3]; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i += 2) { + Resultd = 0.0; + for (c = 0; c < 3; c++) { + Resultd += ((ILdouble*)(Data))[i * 2 + c] * LumFactor[c]; + } + ((ILdouble*)(NewData))[i] = Resultd; + ((ILdouble*)(NewData))[i+1] = ((ILdouble*)(Data))[i * 2 + 3]; + } + break; + } + break; + + case IL_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 4); + CHECK_ALLOC(); + Size = NumPix / 4; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + NewData[i] = ((ILubyte*)(Data))[i * 4 + 3]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i * 4 + 3]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i * 4 + 3]; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i * 4 + 3]; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i * 4 + 3]; + } + break; + } + break; + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + + + case IL_LUMINANCE: + switch (DestFormat) + { + case IL_RGB: + case IL_BGR: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i++, j += 3) { + for (c = 0; c < 3; c++) { + NewData[j + c] = ((ILubyte*)(Data))[i]; + } + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i++, j += 3) { + for (c = 0; c < 3; c++) { + ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; + } + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i++, j += 3) { + for (c = 0; c < 3; c++) { + ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; + } + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i++, j += 3) { + for (c = 0; c < 3; c++) { + ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; + } + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i++, j += 3) { + for (c = 0; c < 3; c++) { + ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; + } + } + break; + } + break; + + case IL_RGBA: + case IL_BGRA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + NewData[j + c] = ((ILubyte*)(Data))[i]; + } + NewData[j + 3] = UCHAR_MAX; // Full opacity + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; + } + ((ILushort*)(NewData))[j + 3] = USHRT_MAX; // Full opacity + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; + } + ((ILuint*)(NewData))[j + 3] = UINT_MAX; // Full opacity + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; + } + ((ILfloat*)(NewData))[j + 3] = 1.0f; // Full opacity + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; + } + ((ILdouble*)(NewData))[j + 3] = 1.0; // Full opacity + } + break; + } + break; + + case IL_LUMINANCE_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 2); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < NumPix; i++) { + NewData[i * 2] = ((ILubyte*)(Data))[i]; + NewData[i * 2 + 1] = UCHAR_MAX; // Full opacity + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < NumPix; i++) { + ((ILushort*)(NewData))[i * 2] = ((ILushort*)(Data))[i]; + ((ILushort*)(NewData))[i * 2 + 1] = USHRT_MAX; // Full opacity + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < NumPix; i++) { + ((ILuint*)(NewData))[i * 2] = ((ILuint*)(Data))[i]; + ((ILuint*)(NewData))[i * 2 + 1] = UINT_MAX; // Full opacity + } + break; + case IL_FLOAT: + for (i = 0; i < NumPix; i++) { + ((ILfloat*)(NewData))[i * 2] = ((ILfloat*)(Data))[i]; + ((ILfloat*)(NewData))[i * 2 + 1] = 1.0f; // Full opacity + } + break; + case IL_DOUBLE: + for (i = 0; i < NumPix; i++) { + ((ILdouble*)(NewData))[i * 2] = ((ILdouble*)(Data))[i]; + ((ILdouble*)(NewData))[i * 2 + 1] = 1.0; // Full opacity + } + break; + } + break; + + case IL_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest); + CHECK_ALLOC(); + memset(NewData, 0, NumPix * BpcDest); + break; + + /*case IL_COLOUR_INDEX: + NewData = (ILubyte*)ialloc(iCurImage->SizeOfData); + NewImage->Pal.Palette = (ILubyte*)ialloc(768); + if (NewData == NULL || NewImage->Pal.Palette) { + ifree(NewImage); + return IL_FALSE; + } + + // Fill the palette + for (i = 0; i < 256; i++) { + for (c = 0; c < 3; c++) { + NewImage->Pal.Palette[i * 3 + c] = (ILubyte)i; + } + } + // Copy the data + for (i = 0; i < iCurImage->SizeOfData; i++) { + NewData[i] = iCurImage->Data[i]; + } + break;*/ + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + + + case IL_LUMINANCE_ALPHA: + switch (DestFormat) + { + case IL_RGB: + case IL_BGR: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2 * 3); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { + for (c = 0; c < 3; c++) { + NewData[j + c] = ((ILubyte*)(Data))[i]; + } + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { + for (c = 0; c < 3; c++) { + ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; + } + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { + for (c = 0; c < 3; c++) { + ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; + } + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { + for (c = 0; c < 3; c++) { + ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; + } + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 2, j += 3) { + for (c = 0; c < 3; c++) { + ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; + } + } + break; + } + break; + + case IL_RGBA: + case IL_BGRA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2 * 4); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { + for (c = 0; c < 3; c++) { + NewData[j + c] = ((ILubyte*)(Data))[i]; + } + NewData[j + 3] = ((ILubyte*)(Data))[i+1]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { + for (c = 0; c < 3; c++) { + ((ILushort*)(NewData))[j + c] = ((ILushort*)(Data))[i]; + } + ((ILushort*)(NewData))[j + 3] = ((ILushort*)(Data))[i+1]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { + for (c = 0; c < 3; c++) { + ((ILuint*)(NewData))[j + c] = ((ILuint*)(Data))[i]; + } + ((ILuint*)(NewData))[j + 3] = ((ILuint*)(Data))[i+1]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { + for (c = 0; c < 3; c++) { + ((ILfloat*)(NewData))[j + c] = ((ILfloat*)(Data))[i]; + } + ((ILfloat*)(NewData))[j + 3] = ((ILfloat*)(Data))[i+1]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 2, j += 4) { + for (c = 0; c < 3; c++) { + ((ILdouble*)(NewData))[j + c] = ((ILdouble*)(Data))[i]; + } + ((ILdouble*)(NewData))[j + 3] = ((ILdouble*)(Data))[i+1]; + } + break; + } + break; + + case IL_LUMINANCE: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i += 2, j++) { + NewData[j] = ((ILubyte*)(Data))[i]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i += 2, j++) { + ((ILushort*)(NewData))[j] = ((ILushort*)(Data))[i]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i += 2, j++) { + ((ILuint*)(NewData))[j] = ((ILuint*)(Data))[i]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i += 2, j++) { + ((ILfloat*)(NewData))[j] = ((ILfloat*)(Data))[i]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i += 2, j++) { + ((ILdouble*)(NewData))[j] = ((ILdouble*)(Data))[i]; + } + break; + } + break; + + case IL_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest / 2); + CHECK_ALLOC(); + Size = NumPix / 2; + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + NewData[i] = ((ILubyte*)(Data))[i * 2 + 3]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < Size; i++) { + ((ILushort*)(NewData))[i] = ((ILushort*)(Data))[i * 2 + 3]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + ((ILuint*)(NewData))[i] = ((ILuint*)(Data))[i * 2 + 3]; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + ((ILfloat*)(NewData))[i] = ((ILfloat*)(Data))[i * 2 + 3]; + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + ((ILdouble*)(NewData))[i] = ((ILdouble*)(Data))[i * 2 + 3]; + } + break; + } + break; + + /*case IL_COLOUR_INDEX: + NewData = (ILubyte*)ialloc(iCurImage->SizeOfData); + NewImage->Pal.Palette = (ILubyte*)ialloc(768); + if (NewData == NULL || NewImage->Pal.Palette) { + ifree(NewImage); + return IL_FALSE; + } + + // Fill the palette + for (i = 0; i < 256; i++) { + for (c = 0; c < 3; c++) { + NewImage->Pal.Palette[i * 3 + c] = (ILubyte)i; + } + } + // Copy the data + for (i = 0; i < iCurImage->SizeOfData; i++) { + NewData[i] = iCurImage->Data[i]; + } + break;*/ + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + + + case IL_ALPHA: + switch (DestFormat) + { + case IL_RGB: + case IL_BGR: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 3); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + case IL_UNSIGNED_INT: + case IL_INT: + case IL_FLOAT: + case IL_DOUBLE: + memset(NewData, 0, NumPix * BpcDest * 3); // Easy enough + break; + //@TODO: Do we need to a check for default: (error)? + } + break; + + case IL_RGBA: + case IL_BGRA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 4); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + NewData[j + c] = 0; + } + NewData[j + 3] = ((ILubyte*)(Data))[i]; // Only value that matters + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILushort*)(NewData))[j + c] = 0; + } + ((ILushort*)(NewData))[j + 3] = ((ILushort*)(Data))[i]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILuint*)(NewData))[j + c] = 0; + } + ((ILuint*)(NewData))[j + 3] = ((ILuint*)(Data))[i]; + } + break; + case IL_FLOAT: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILfloat*)(NewData))[j + c] = 0; + } + ((ILfloat*)(NewData))[j + 3] = ((ILfloat*)(Data))[i]; + } + break; + case IL_DOUBLE: + for (i = 0, j = 0; i < NumPix; i++, j += 4) { + for (c = 0; c < 3; c++) { + ((ILdouble*)(NewData))[j + c] = 0; + } + ((ILdouble*)(NewData))[j + 3] = ((ILdouble*)(Data))[i]; + } + break; + } + break; + + case IL_LUMINANCE_ALPHA: + NewData = (ILubyte*)ialloc(NumPix * BpcDest * 2); + CHECK_ALLOC(); + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < NumPix; i++) { + NewData[i * 2] = 0; + NewData[i * 2 + 1] = ((ILubyte*)(Data))[i]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + case IL_HALF: + for (i = 0; i < NumPix; i++) { + ((ILushort*)(NewData))[i * 2] = 0; + ((ILushort*)(NewData))[i * 2 + 1] = ((ILushort*)(Data))[i]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < NumPix; i++) { + ((ILuint*)(NewData))[i * 2] = 0; + ((ILuint*)(NewData))[i * 2 + 1] = ((ILuint*)(Data))[i]; + } + break; + case IL_FLOAT: + for (i = 0; i < NumPix; i++) { + ((ILfloat*)(NewData))[i * 2] = 0; + ((ILfloat*)(NewData))[i * 2 + 1] = ((ILfloat*)(Data))[i]; + } + break; + case IL_DOUBLE: + for (i = 0; i < NumPix; i++) { + ((ILdouble*)(NewData))[i * 2] = 0; + ((ILdouble*)(NewData))[i * 2 + 1] = ((ILdouble*)(Data))[i]; + } + break; + } + break; + + + /*case IL_COLOUR_INDEX: + NewData = (ILubyte*)ialloc(iCurImage->SizeOfData); + NewImage->Pal.Palette = (ILubyte*)ialloc(768); + if (NewData == NULL || NewImage->Pal.Palette) { + ifree(NewImage); + return IL_FALSE; + } + + // Fill the palette + for (i = 0; i < 256; i++) { + for (c = 0; c < 3; c++) { + NewImage->Pal.Palette[i * 3 + c] = (ILubyte)i; + } + } + // Copy the data + for (i = 0; i < iCurImage->SizeOfData; i++) { + NewData[i] = iCurImage->Data[i]; + } + break;*/ + + default: + ilSetError(IL_INVALID_CONVERSION); + if (Data != Buffer) + ifree(Data); + return NULL; + } + break; + } + + if (Data != Buffer) + ifree(Data); + + return NewData; +} + + +// Really shouldn't have to check for default, as in above ilConvertBuffer(). +// This now converts better from lower bpp to higher bpp. For example, when +// converting from 8 bpp to 16 bpp, if the value is 0xEC, the new value is 0xECEC +// instead of 0xEC00. +void* ILAPIENTRY iSwitchTypes(ILuint SizeOfData, ILenum SrcType, ILenum DestType, void *Buffer) +{ + ILuint BpcSrc, BpcDest, Size, i; + ILubyte *NewData, *BytePtr; + ILushort *ShortPtr; + ILuint *IntPtr; + ILfloat *FloatPtr, tempFloat; + ILdouble *DblPtr, tempDouble; + ILushort *HalfPtr; + + BpcSrc = ilGetBpcType(SrcType); + BpcDest = ilGetBpcType(DestType); + + if (BpcSrc == 0 || BpcDest == 0) { + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + Size = SizeOfData / BpcSrc; + + //if (BpcSrc == BpcDest) { + if (SrcType == DestType) { + return Buffer; + } + + NewData = (ILubyte*)ialloc(Size * BpcDest); + if (NewData == NULL) { + return IL_FALSE; + } + + switch (DestType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + BytePtr = (ILubyte*)NewData; + switch (SrcType) + { + case IL_UNSIGNED_SHORT: + case IL_SHORT: + for (i = 0; i < Size; i++) { + BytePtr[i] = ((ILushort*)Buffer)[i] >> 8; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + BytePtr[i] = ((ILuint*)Buffer)[i] >> 24; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + #if CLAMP_FLOATS + tempFloat = IL_CLAMP(((ILfloat*)Buffer)[i]); + BytePtr[i] = (ILubyte)(tempFloat * UCHAR_MAX); + #else + BytePtr[i] = (ILubyte)(((ILfloat*)Buffer)[i] * UCHAR_MAX); + #endif + } + break; + case IL_HALF: + for (i = 0; i < Size; i++) { + #if CLAMP_HALF + *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); + tempFloat = IL_CLAMP(tempFloat); + BytePtr[i] = (ILubyte)(tempFloat * UCHAR_MAX); + #else + *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); + BytePtr[i] = (ILubyte)(tempFloat * UCHAR_MAX); + #endif + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + #if CLAMP_DOUBLES + tempDouble = IL_CLAMP(((ILdouble*)Buffer)[i]); + BytePtr[i] = (ILubyte)(tempDouble * UCHAR_MAX); + #else + BytePtr[i] = (ILubyte)( ((ILdouble*)Buffer)[i] * UCHAR_MAX); + #endif + } + break; + } + break; + + case IL_UNSIGNED_SHORT: + case IL_SHORT: + ShortPtr = (ILushort*)NewData; + switch (SrcType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + ShortPtr[i] = (((ILubyte*)Buffer)[i] << 8) | ((ILubyte*)Buffer)[i]; + } + break; + case IL_UNSIGNED_INT: + case IL_INT: + for (i = 0; i < Size; i++) { + ShortPtr[i] = ((ILuint*)Buffer)[i] >> 16; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + #if CLAMP_FLOATS + tempFloat = IL_CLAMP(((ILfloat*)Buffer)[i]); + ShortPtr[i] = (ILushort)(tempFloat * USHRT_MAX); + #else + ShortPtr[i] = (ILushort)( ((ILfloat*)Buffer)[i] * USHRT_MAX); + #endif + } + break; + case IL_HALF: + for (i = 0; i < Size; i++) { + #if CLAMP_FLOATS + *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); + tempFloat = IL_CLAMP(tempFloat); + ShortPtr[i] = (ILushort)(tempFloat * USHRT_MAX); + #else + *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); + ShortPtr[i] = (ILushort)(tempFloat * USHRT_MAX); + #endif + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + #if CLAMP_DOUBLES + tempDouble = IL_CLAMP(((ILdouble*)Buffer)[i]); + ShortPtr[i] = (ILushort)(tempDouble * USHRT_MAX); + #else + ShortPtr[i] = (ILushort)( ((ILdouble*)Buffer)[i] * USHRT_MAX); + #endif + } + break; + } + break; + + case IL_UNSIGNED_INT: + case IL_INT: + IntPtr = (ILuint*)NewData; + switch (SrcType) + { + case IL_UNSIGNED_BYTE: + case IL_BYTE: + for (i = 0; i < Size; i++) { + IntPtr[i] = (((ILubyte*)Buffer)[i] << 24) | (((ILubyte*)Buffer)[i] << 16) | + (((ILubyte*)Buffer)[i] << 8) | ((ILubyte*)Buffer)[i]; + } + break; + case IL_UNSIGNED_SHORT: + case IL_SHORT: + for (i = 0; i < Size; i++) { + IntPtr[i] = (((ILushort*)Buffer)[i] << 16) | ((ILushort*)Buffer)[i]; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + #if CLAMP_FLOATS + tempFloat = IL_CLAMP(((ILfloat*)Buffer)[i]); + IntPtr[i] = (ILuint)(tempFloat * UINT_MAX); + #else + IntPtr[i] = (ILuint)( ((ILfloat*)Buffer)[i] * UINT_MAX); + #endif + } + break; + case IL_HALF: + for (i = 0; i < Size; i++) { + #if CLAMP_FLOATS + *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); + tempFloat = IL_CLAMP(tempFloat); + IntPtr[i] = (ILuint)(tempFloat * UINT_MAX); + #else + *((ILuint*)&tempFloat) = ilHalfToFloat(((ILushort*)Buffer)[i]); + IntPtr[i] = (ILuint)(tempFloat * UINT_MAX); + #endif + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + #if CLAMP_DOUBLES + tempDouble = IL_CLAMP(((ILdouble*)Buffer)[i]); + IntPtr[i] = (ILuint)(tempDouble * UINT_MAX); + #else + IntPtr[i] = (ILuint)( ((ILdouble*)Buffer)[i] * UINT_MAX); + #endif + } + break; + } + break; + + // @TODO: Handle signed better. + case IL_FLOAT: + FloatPtr = (ILfloat*)NewData; + switch (SrcType) + { + case IL_UNSIGNED_BYTE: + for (i = 0; i < Size; i++) { + FloatPtr[i] = ((ILubyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; + } + break; + case IL_BYTE: + for (i = 0; i < Size; i++) { + FloatPtr[i] = ((ILbyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + for (i = 0; i < Size; i++) { + FloatPtr[i] = ((ILushort*)Buffer)[i] / (ILfloat)USHRT_MAX; + } + break; + case IL_SHORT: + for (i = 0; i < Size; i++) { + FloatPtr[i] = ((ILshort*)Buffer)[i] / (ILfloat)USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + for (i = 0; i < Size; i++) { + FloatPtr[i] = (ILfloat)((ILuint*)Buffer)[i] / (ILfloat)UINT_MAX; + } + break; + case IL_INT: + for (i = 0; i < Size; i++) { + FloatPtr[i] = (ILfloat)((ILint*)Buffer)[i] / (ILfloat)UINT_MAX; + } + break; + case IL_HALF: + for (i = 0; i < Size; i++) { + *((ILuint*)&FloatPtr[i]) = ilHalfToFloat(((ILushort*)Buffer)[i]); + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + FloatPtr[i] = (ILfloat)((ILdouble*)Buffer)[i]; + } + break; + } + break; + + case IL_DOUBLE: + DblPtr = (ILdouble*)NewData; + switch (SrcType) + { + case IL_UNSIGNED_BYTE: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILubyte*)Buffer)[i] / (ILdouble)UCHAR_MAX; + } + break; + case IL_BYTE: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILbyte*)Buffer)[i] / (ILdouble)UCHAR_MAX; + } + break; + case IL_UNSIGNED_SHORT: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILushort*)Buffer)[i] / (ILdouble)USHRT_MAX; + } + break; + case IL_SHORT: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILshort*)Buffer)[i] / (ILdouble)USHRT_MAX; + } + break; + case IL_UNSIGNED_INT: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILuint*)Buffer)[i] / (ILdouble)UINT_MAX; + } + break; + case IL_INT: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILint*)Buffer)[i] / (ILdouble)UINT_MAX; + } + break; + case IL_HALF: + for (i = 0; i < Size; i++) { + *(ILuint*)&tempFloat = ilHalfToFloat(((ILushort*)Buffer)[i]); + DblPtr[i] = tempFloat; + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + DblPtr[i] = ((ILfloat*)Buffer)[i]; + } + break; + } + break; + + case IL_HALF: + HalfPtr = (ILushort*)NewData; + switch (SrcType) + { + case IL_UNSIGNED_BYTE: + for (i = 0; i < Size; i++) { + tempFloat = ((ILubyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_BYTE: + for (i = 0; i < Size; i++) { + tempFloat = ((ILbyte*)Buffer)[i] / (ILfloat)UCHAR_MAX; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_UNSIGNED_SHORT: + for (i = 0; i < Size; i++) { + tempFloat = ((ILushort*)Buffer)[i] / (ILfloat)USHRT_MAX; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_SHORT: + for (i = 0; i < Size; i++) { + tempFloat = ((ILshort*)Buffer)[i] / (ILfloat)USHRT_MAX; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_UNSIGNED_INT: + for (i = 0; i < Size; i++) { + tempFloat = ((ILuint*)Buffer)[i] / (ILfloat)UINT_MAX; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_INT: + for (i = 0; i < Size; i++) { + tempFloat = ((ILint*)Buffer)[i] / (ILfloat)UINT_MAX; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_DOUBLE: + for (i = 0; i < Size; i++) { + tempFloat = (ILfloat)((ILdouble*)Buffer)[i]; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + case IL_FLOAT: + for (i = 0; i < Size; i++) { + tempFloat = ((ILfloat*)Buffer)[i]; + *((ILushort*)&HalfPtr[i]) = ilFloatToHalf(*(ILuint*)&tempFloat); + } + break; + } + break; + } + + + return NewData; +} + + + + diff --git a/DevIL/src-IL/src/il_convert.c b/DevIL/src-IL/src/il_convert.c deleted file mode 100644 index 1f72f4f6..00000000 --- a/DevIL/src-IL/src/il_convert.c +++ /dev/null @@ -1,1125 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_convert.c -// -// Description: Converts between several image formats -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include - - -ILimage *iConvertPalette(ILimage *Image, ILenum DestFormat) -{ - static const ILfloat LumFactor[3] = { 0.212671f, 0.715160f, 0.072169f }; // http://www.inforamp.net/~poynton/ and libpng's libpng.txt - Used for conversion to luminance. - ILimage *NewImage = NULL, *CurImage = NULL; - ILuint i, j, k, c, Size, LumBpp = 1; - ILfloat Resultf; - ILubyte *Temp = NULL; - ILboolean Converted; - ILboolean HasAlpha; - - NewImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0. - if (NewImage == NULL) { - return IL_FALSE; - } - - ilCopyImageAttr(NewImage, Image); - - if (!Image->Pal.Palette || !Image->Pal.PalSize || Image->Pal.PalType == IL_PAL_NONE || Image->Bpp != 1) { - ilCloseImage(NewImage); - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - - if (DestFormat == IL_LUMINANCE || DestFormat == IL_LUMINANCE_ALPHA) { - if (NewImage->Pal.Palette) - ifree(NewImage->Pal.Palette); - if (DestFormat == IL_LUMINANCE_ALPHA) - LumBpp = 2; - - switch (iCurImage->Pal.PalType) - { - case IL_PAL_RGB24: - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - Temp = (ILubyte*)ialloc(LumBpp * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType)); - if (Temp == NULL) - goto alloc_error; - - Size = ilGetBppPal(Image->Pal.PalType); - for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += LumBpp) { - Resultf = 0.0f; - for (c = 0; c < Size; c++) { - Resultf += Image->Pal.Palette[i + c] * LumFactor[c]; - } - Temp[k] = (ILubyte)Resultf; - if (LumBpp == 2) { - if (iCurImage->Pal.PalType == IL_PAL_RGBA32) - Temp[k+1] = Image->Pal.Palette[i + 3]; - else - Temp[k+1] = 0xff; - } - } - - break; - - case IL_PAL_BGR24: - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - Temp = (ILubyte*)ialloc(LumBpp * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType)); - if (Temp == NULL) - goto alloc_error; - - Size = ilGetBppPal(Image->Pal.PalType); - for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += LumBpp) { - Resultf = 0.0f; j = 2; - for (c = 0; c < Size; c++, j--) { - Resultf += Image->Pal.Palette[i + c] * LumFactor[j]; - } - Temp[k] = (ILubyte)Resultf; - if (LumBpp == 2) { - if (iCurImage->Pal.PalType == IL_PAL_RGBA32) - Temp[k+1] = Image->Pal.Palette[i + 3]; - else - Temp[k+1] = 0xff; - } - } - - break; - } - - NewImage->Pal.Palette = NULL; - NewImage->Pal.PalSize = 0; - NewImage->Pal.PalType = IL_PAL_NONE; - NewImage->Format = DestFormat; - NewImage->Bpp = LumBpp; - NewImage->Bps = NewImage->Width * LumBpp; - NewImage->SizeOfData = NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; - NewImage->Data = (ILubyte*)ialloc(NewImage->SizeOfData); - if (NewImage->Data == NULL) - goto alloc_error; - - if (LumBpp == 2) { - for (i = 0; i < Image->SizeOfData; i++) { - NewImage->Data[i*2] = Temp[Image->Data[i] * 2]; - NewImage->Data[i*2+1] = Temp[Image->Data[i] * 2 + 1]; - } - } - else { - for (i = 0; i < Image->SizeOfData; i++) { - NewImage->Data[i] = Temp[Image->Data[i]]; - } - } - - ifree(Temp); - - return NewImage; - } - else if (DestFormat == IL_ALPHA) { - if (NewImage->Pal.Palette) - ifree(NewImage->Pal.Palette); - - switch (iCurImage->Pal.PalType) - { - // Opaque, so all the values are 0xFF. - case IL_PAL_RGB24: - case IL_PAL_RGB32: - case IL_PAL_BGR24: - case IL_PAL_BGR32: - HasAlpha = IL_FALSE; - break; - - case IL_PAL_BGRA32: - case IL_PAL_RGBA32: - HasAlpha = IL_TRUE; - Temp = (ILubyte*)ialloc(1 * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType)); - if (Temp == NULL) - goto alloc_error; - - Size = ilGetBppPal(Image->Pal.PalType); - for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += 1) { - Temp[k] = Image->Pal.Palette[i + 3]; - } - - break; - } - - NewImage->Pal.Palette = NULL; - NewImage->Pal.PalSize = 0; - NewImage->Pal.PalType = IL_PAL_NONE; - NewImage->Format = DestFormat; - NewImage->Bpp = LumBpp; - NewImage->Bps = NewImage->Width * 1; // Alpha is only one byte. - NewImage->SizeOfData = NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; - NewImage->Data = (ILubyte*)ialloc(NewImage->SizeOfData); - if (NewImage->Data == NULL) - goto alloc_error; - - if (HasAlpha) { - for (i = 0; i < Image->SizeOfData; i++) { - NewImage->Data[i*2] = Temp[Image->Data[i] * 2]; - NewImage->Data[i*2+1] = Temp[Image->Data[i] * 2 + 1]; - } - } - else { // No alpha, opaque. - for (i = 0; i < Image->SizeOfData; i++) { - NewImage->Data[i] = 0xFF; - } - } - - ifree(Temp); - - return NewImage; - } - - //NewImage->Format = ilGetPalBaseType(iCurImage->Pal.PalType); - NewImage->Format = DestFormat; - - if (ilGetBppFormat(NewImage->Format) == 0) { - ilCloseImage(NewImage); - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - - CurImage = iCurImage; - ilSetCurImage(NewImage); - - switch (DestFormat) - { - case IL_RGB: - Converted = ilConvertPal(IL_PAL_RGB24); - break; - - case IL_BGR: - Converted = ilConvertPal(IL_PAL_BGR24); - break; - - case IL_RGBA: - Converted = ilConvertPal(IL_PAL_RGB32); - break; - - case IL_BGRA: - Converted = ilConvertPal(IL_PAL_BGR32); - break; - - case IL_COLOUR_INDEX: - // Just copy the original image over. - NewImage->Data = (ILubyte*)ialloc(CurImage->SizeOfData); - if (NewImage->Data == NULL) - goto alloc_error; - NewImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (NewImage->Pal.Palette == NULL) - goto alloc_error; - memcpy(NewImage->Data, CurImage->Data, CurImage->SizeOfData); - memcpy(NewImage->Pal.Palette, Image->Pal.Palette, Image->Pal.PalSize); - NewImage->Pal.PalSize = Image->Pal.PalSize; - NewImage->Pal.PalType = Image->Pal.PalType; - ilSetCurImage(CurImage); - return NewImage; - - default: - ilCloseImage(NewImage); - ilSetError(IL_INVALID_CONVERSION); - return NULL; - } - - // Resize to new bpp - ilResizeImage(NewImage, NewImage->Width, NewImage->Height, NewImage->Depth, ilGetBppFormat(DestFormat), /*ilGetBpcType(DestType)*/1); - - // ilConvertPal already sets the error message - no need to confuse the user. - if (!Converted) { - ilSetCurImage(CurImage); - ilCloseImage(NewImage); - return NULL; - } - - Size = ilGetBppPal(NewImage->Pal.PalType); - for (i = 0; i < Image->SizeOfData; i++) { - for (c = 0; c < NewImage->Bpp; c++) { - NewImage->Data[i * NewImage->Bpp + c] = NewImage->Pal.Palette[Image->Data[i] * Size + c]; - } - } - - ifree(NewImage->Pal.Palette); - - NewImage->Pal.Palette = NULL; - NewImage->Pal.PalSize = 0; - NewImage->Pal.PalType = IL_PAL_NONE; - ilSetCurImage(CurImage); - - return NewImage; - -alloc_error: - ifree(Temp); - if (NewImage) - ilCloseImage(NewImage); - if (CurImage != iCurImage) - ilSetCurImage(CurImage); - return NULL; -} - - -// In il_quantizer.c -ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols); -// In il_neuquant.c -ILimage *iNeuQuant(ILimage *Image, ILuint NumCols); - -// Converts an image from one format to another -ILAPI ILimage* ILAPIENTRY iConvertImage(ILimage *Image, ILenum DestFormat, ILenum DestType) -{ - ILimage *NewImage, *CurImage; - ILuint i; - ILubyte *NewData; - - CurImage = Image; - if (Image == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - // We don't support 16-bit color indices (or higher). - if (DestFormat == IL_COLOUR_INDEX && DestType >= IL_SHORT) { - ilSetError(IL_INVALID_CONVERSION); - return NULL; - } - - if (Image->Format == IL_COLOUR_INDEX) { - NewImage = iConvertPalette(Image, DestFormat); - - //added test 2003-09-01 - if (NewImage == NULL) - return NULL; - - if (DestType == NewImage->Type) - return NewImage; - - NewData = (ILubyte*)ilConvertBuffer(NewImage->SizeOfData, NewImage->Format, DestFormat, NewImage->Type, DestType, NULL, NewImage->Data); - if (NewData == NULL) { - ifree(NewImage); // ilCloseImage not needed. - return NULL; - } - ifree(NewImage->Data); - NewImage->Data = NewData; - - ilCopyImageAttr(NewImage, Image); - NewImage->Format = DestFormat; - NewImage->Type = DestType; - NewImage->Bpc = ilGetBpcType(DestType); - NewImage->Bpp = ilGetBppFormat(DestFormat); - NewImage->Bps = NewImage->Bpp * NewImage->Bpc * NewImage->Width; - NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; - NewImage->SizeOfData = NewImage->SizeOfPlane * NewImage->Depth; - } - else if (DestFormat == IL_COLOUR_INDEX && Image->Format != IL_LUMINANCE) { - if (iGetInt(IL_QUANTIZATION_MODE) == IL_NEU_QUANT) - return iNeuQuant(Image, iGetInt(IL_MAX_QUANT_INDICES)); - else // Assume IL_WU_QUANT otherwise. - return iQuantizeImage(Image, iGetInt(IL_MAX_QUANT_INDICES)); - } - else { - NewImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0. - if (NewImage == NULL) { - return NULL; - } - - if (ilGetBppFormat(DestFormat) == 0) { - ilSetError(IL_INVALID_PARAM); - ifree(NewImage); - return NULL; - } - - ilCopyImageAttr(NewImage, Image); - NewImage->Format = DestFormat; - NewImage->Type = DestType; - NewImage->Bpc = ilGetBpcType(DestType); - NewImage->Bpp = ilGetBppFormat(DestFormat); - NewImage->Bps = NewImage->Bpp * NewImage->Bpc * NewImage->Width; - NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; - NewImage->SizeOfData = NewImage->SizeOfPlane * NewImage->Depth; - - if (DestFormat == IL_COLOUR_INDEX && Image->Format == IL_LUMINANCE) { - NewImage->Pal.PalSize = 768; - NewImage->Pal.PalType = IL_PAL_RGB24; - NewImage->Pal.Palette = (ILubyte*)ialloc(768); - for (i = 0; i < 256; i++) { - NewImage->Pal.Palette[i * 3] = i; - NewImage->Pal.Palette[i * 3 + 1] = i; - NewImage->Pal.Palette[i * 3 + 2] = i; - } - NewImage->Data = (ILubyte*)ialloc(Image->SizeOfData); - if (NewImage->Data == NULL) { - ilCloseImage(NewImage); - return NULL; - } - memcpy(NewImage->Data, Image->Data, Image->SizeOfData); - } - else { - NewImage->Data = (ILubyte*)ilConvertBuffer(Image->SizeOfData, Image->Format, DestFormat, Image->Type, DestType, NULL, Image->Data); - if (NewImage->Data == NULL) { - ifree(NewImage); // ilCloseImage not needed. - return NULL; - } - } - } - - return NewImage; -} - - -//! Converts the current image to the DestFormat format. -/*! \param DestFormat An enum of the desired output format. Any format values are accepted. - \param DestType An enum of the desired output type. Any type values are accepted. - \exception IL_ILLEGAL_OPERATION No currently bound image - \exception IL_INVALID_CONVERSION DestFormat or DestType was an invalid identifier. - \exception IL_OUT_OF_MEMORY Could not allocate enough memory. - \return Boolean value of failure or success*/ -ILboolean ILAPIENTRY ilConvertImage(ILenum DestFormat, ILenum DestType) -{ - ILimage *Image, *pCurImage; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (DestFormat == iCurImage->Format && DestType == iCurImage->Type) - return IL_TRUE; // No conversion needed. - - if (DestType == iCurImage->Type) { - if (iFastConvert(DestFormat)) { - iCurImage->Format = DestFormat; - return IL_TRUE; - } - } - - if (ilIsEnabled(IL_USE_KEY_COLOUR)) { - ilAddAlphaKey(iCurImage); - } - - pCurImage = iCurImage; - while (pCurImage != NULL) - { - Image = iConvertImage(pCurImage, DestFormat, DestType); - if (Image == NULL) - return IL_FALSE; - - //ilCopyImageAttr(pCurImage, Image); // Destroys subimages. - - // We don't copy the colour profile here, since it stays the same. - // Same with the DXTC data. - pCurImage->Format = DestFormat; - pCurImage->Type = DestType; - pCurImage->Bpc = ilGetBpcType(DestType); - pCurImage->Bpp = ilGetBppFormat(DestFormat); - pCurImage->Bps = pCurImage->Width * pCurImage->Bpc * pCurImage->Bpp; - pCurImage->SizeOfPlane = pCurImage->Bps * pCurImage->Height; - pCurImage->SizeOfData = pCurImage->Depth * pCurImage->SizeOfPlane; - if (pCurImage->Pal.Palette && pCurImage->Pal.PalSize && pCurImage->Pal.PalType != IL_PAL_NONE) - ifree(pCurImage->Pal.Palette); - pCurImage->Pal.Palette = Image->Pal.Palette; - pCurImage->Pal.PalSize = Image->Pal.PalSize; - pCurImage->Pal.PalType = Image->Pal.PalType; - Image->Pal.Palette = NULL; - ifree(pCurImage->Data); - pCurImage->Data = Image->Data; - Image->Data = NULL; - ilCloseImage(Image); - - pCurImage = pCurImage->Next; - } - - return IL_TRUE; -} - - -// Swaps the colour order of the current image (rgb(a)->bgr(a) or vice-versa). -// Must be either an 8, 24 or 32-bit (coloured) image (or palette). -ILboolean ilSwapColours() -{ - ILuint i = 0, Size = iCurImage->Bpp * iCurImage->Width * iCurImage->Height; - ILbyte PalBpp = ilGetBppPal(iCurImage->Pal.PalType); - ILushort *ShortPtr; - ILuint *IntPtr, Temp; - ILdouble *DoublePtr, DoubleTemp; - - if ((iCurImage->Bpp != 1 && iCurImage->Bpp != 3 && iCurImage->Bpp != 4)) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - // Just check before we change the format. - if (iCurImage->Format == IL_COLOUR_INDEX) { - if (PalBpp == 0 || iCurImage->Format != IL_COLOUR_INDEX) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - } - - switch (iCurImage->Format) - { - case IL_RGB: - iCurImage->Format = IL_BGR; - break; - case IL_RGBA: - iCurImage->Format = IL_BGRA; - break; - case IL_BGR: - iCurImage->Format = IL_RGB; - break; - case IL_BGRA: - iCurImage->Format = IL_RGBA; - break; - case IL_ALPHA: - case IL_LUMINANCE: - case IL_LUMINANCE_ALPHA: - return IL_TRUE; // No need to do anything to luminance or alpha images. - case IL_COLOUR_INDEX: - switch (iCurImage->Pal.PalType) - { - case IL_PAL_RGB24: - iCurImage->Pal.PalType = IL_PAL_BGR24; - break; - case IL_PAL_RGB32: - iCurImage->Pal.PalType = IL_PAL_BGR32; - break; - case IL_PAL_RGBA32: - iCurImage->Pal.PalType = IL_PAL_BGRA32; - break; - case IL_PAL_BGR24: - iCurImage->Pal.PalType = IL_PAL_RGB24; - break; - case IL_PAL_BGR32: - iCurImage->Pal.PalType = IL_PAL_RGB32; - break; - case IL_PAL_BGRA32: - iCurImage->Pal.PalType = IL_PAL_RGBA32; - break; - default: - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - break; - default: - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (iCurImage->Format == IL_COLOUR_INDEX) { - for (; i < iCurImage->Pal.PalSize; i += PalBpp) { - Temp = iCurImage->Pal.Palette[i]; - iCurImage->Pal.Palette[i] = iCurImage->Pal.Palette[i+2]; - iCurImage->Pal.Palette[i+2] = Temp; - } - } - else { - ShortPtr = (ILushort*)iCurImage->Data; - IntPtr = (ILuint*)iCurImage->Data; - DoublePtr = (ILdouble*)iCurImage->Data; - switch (iCurImage->Bpc) - { - case 1: - for (; i < Size; i += iCurImage->Bpp) { - Temp = iCurImage->Data[i]; - iCurImage->Data[i] = iCurImage->Data[i+2]; - iCurImage->Data[i+2] = Temp; - } - break; - case 2: - for (; i < Size; i += iCurImage->Bpp) { - Temp = ShortPtr[i]; - ShortPtr[i] = ShortPtr[i+2]; - ShortPtr[i+2] = Temp; - } - break; - case 4: // Works fine with ILint, ILuint and ILfloat. - for (; i < Size; i += iCurImage->Bpp) { - Temp = IntPtr[i]; - IntPtr[i] = IntPtr[i+2]; - IntPtr[i+2] = Temp; - } - break; - case 8: - for (; i < Size; i += iCurImage->Bpp) { - DoubleTemp = DoublePtr[i]; - DoublePtr[i] = DoublePtr[i+2]; - DoublePtr[i+2] = DoubleTemp; - } - break; - } - } - - return IL_TRUE; -} - - -// Adds an opaque alpha channel to a 24-bit image -ILboolean ilAddAlpha() -{ - ILubyte *NewData, NewBpp; - ILuint i = 0, j = 0, Size; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (iCurImage->Bpp != 3) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - Size = iCurImage->Bps * iCurImage->Height / iCurImage->Bpc; - NewBpp = (ILubyte)(iCurImage->Bpp + 1); - - NewData = (ILubyte*)ialloc(NewBpp * iCurImage->Bpc * iCurImage->Width * iCurImage->Height); - if (NewData == NULL) { - return IL_FALSE; - } - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - NewData[j] = iCurImage->Data[i]; - NewData[j+1] = iCurImage->Data[i+1]; - NewData[j+2] = iCurImage->Data[i+2]; - NewData[j+3] = UCHAR_MAX; // Max opaqueness - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILushort*)NewData)[j] = ((ILushort*)iCurImage->Data)[i]; - ((ILushort*)NewData)[j+1] = ((ILushort*)iCurImage->Data)[i+1]; - ((ILushort*)NewData)[j+2] = ((ILushort*)iCurImage->Data)[i+2]; - ((ILushort*)NewData)[j+3] = USHRT_MAX; - } - break; - - case IL_INT: - case IL_UNSIGNED_INT: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILuint*)NewData)[j] = ((ILuint*)iCurImage->Data)[i]; - ((ILuint*)NewData)[j+1] = ((ILuint*)iCurImage->Data)[i+1]; - ((ILuint*)NewData)[j+2] = ((ILuint*)iCurImage->Data)[i+2]; - ((ILuint*)NewData)[j+3] = UINT_MAX; - } - break; - - case IL_FLOAT: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILfloat*)NewData)[j] = ((ILfloat*)iCurImage->Data)[i]; - ((ILfloat*)NewData)[j+1] = ((ILfloat*)iCurImage->Data)[i+1]; - ((ILfloat*)NewData)[j+2] = ((ILfloat*)iCurImage->Data)[i+2]; - ((ILfloat*)NewData)[j+3] = 1.0f; - } - break; - - case IL_DOUBLE: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILdouble*)NewData)[j] = ((ILdouble*)iCurImage->Data)[i]; - ((ILdouble*)NewData)[j+1] = ((ILdouble*)iCurImage->Data)[i+1]; - ((ILdouble*)NewData)[j+2] = ((ILdouble*)iCurImage->Data)[i+2]; - ((ILdouble*)NewData)[j+3] = 1.0; - } - break; - - default: - ifree(NewData); - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - - iCurImage->Bpp = NewBpp; - iCurImage->Bps = iCurImage->Width * iCurImage->Bpc * NewBpp; - iCurImage->SizeOfPlane = iCurImage->Bps * iCurImage->Height; - iCurImage->SizeOfData = iCurImage->SizeOfPlane * iCurImage->Depth; - ifree(iCurImage->Data); - iCurImage->Data = NewData; - - switch (iCurImage->Format) - { - case IL_RGB: - iCurImage->Format = IL_RGBA; - break; - case IL_BGR: - iCurImage->Format = IL_BGRA; - break; - } - - return IL_TRUE; -} - - -//ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0; - -void ILAPIENTRY ilKeyColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha) -{ - ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0; - KeyRed = Red; - KeyGreen = Green; - KeyBlue = Blue; - KeyAlpha = Alpha; - return; -} - - -// Adds an alpha channel to an 8 or 24-bit image, -// making the image transparent where Key is equal to the pixel. -ILboolean ilAddAlphaKey(ILimage *Image) -{ - ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0; - ILubyte *NewData, NewBpp; - ILfloat KeyColour[3]; - ILuint i = 0, j = 0, c, Size; - ILboolean Same; - - if (Image == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (Image->Format != IL_COLOUR_INDEX) { - if (Image->Bpp != 3) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - if (Image->Format == IL_BGR || Image->Format == IL_BGRA) { - KeyColour[0] = KeyBlue; - KeyColour[1] = KeyGreen; - KeyColour[2] = KeyRed; - } - else { - KeyColour[0] = KeyRed; - KeyColour[1] = KeyGreen; - KeyColour[2] = KeyBlue; - } - - Size = Image->Bps * Image->Height / Image->Bpc; - - NewBpp = (ILubyte)(Image->Bpp + 1); - - NewData = (ILubyte*)ialloc(NewBpp * Image->Bpc * Image->Width * Image->Height); - if (NewData == NULL) { - return IL_FALSE; - } - - switch (Image->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - for (; i < Size; i += Image->Bpp, j += NewBpp) { - NewData[j] = Image->Data[i]; - NewData[j+1] = Image->Data[i+1]; - NewData[j+2] = Image->Data[i+2]; - Same = IL_TRUE; - for (c = 0; c < Image->Bpp; c++) { - if (Image->Data[i+c] != KeyColour[c] * UCHAR_MAX) - Same = IL_FALSE; - } - - if (Same) - NewData[j+3] = 0; // Transparent - matches key colour - else - NewData[j+3] = UCHAR_MAX; - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - for (; i < Size; i += Image->Bpp, j += NewBpp) { - ((ILushort*)NewData)[j] = ((ILushort*)Image->Data)[i]; - ((ILushort*)NewData)[j+1] = ((ILushort*)Image->Data)[i+1]; - ((ILushort*)NewData)[j+2] = ((ILushort*)Image->Data)[i+2]; - Same = IL_TRUE; - for (c = 0; c < Image->Bpp; c++) { - if (((ILushort*)Image->Data)[i+c] != KeyColour[c] * USHRT_MAX) - Same = IL_FALSE; - } - - if (Same) - ((ILushort*)NewData)[j+3] = 0; - else - ((ILushort*)NewData)[j+3] = USHRT_MAX; - } - break; - - case IL_INT: - case IL_UNSIGNED_INT: - for (; i < Size; i += Image->Bpp, j += NewBpp) { - ((ILuint*)NewData)[j] = ((ILuint*)Image->Data)[i]; - ((ILuint*)NewData)[j+1] = ((ILuint*)Image->Data)[i+1]; - ((ILuint*)NewData)[j+2] = ((ILuint*)Image->Data)[i+2]; - Same = IL_TRUE; - for (c = 0; c < Image->Bpp; c++) { - if (((ILuint*)Image->Data)[i+c] != KeyColour[c] * UINT_MAX) - Same = IL_FALSE; - } - - if (Same) - ((ILuint*)NewData)[j+3] = 0; - else - ((ILuint*)NewData)[j+3] = UINT_MAX; - } - break; - - case IL_FLOAT: - for (; i < Size; i += Image->Bpp, j += NewBpp) { - ((ILfloat*)NewData)[j] = ((ILfloat*)Image->Data)[i]; - ((ILfloat*)NewData)[j+1] = ((ILfloat*)Image->Data)[i+1]; - ((ILfloat*)NewData)[j+2] = ((ILfloat*)Image->Data)[i+2]; - Same = IL_TRUE; - for (c = 0; c < Image->Bpp; c++) { - if (((ILfloat*)Image->Data)[i+c] != KeyColour[c]) - Same = IL_FALSE; - } - - if (Same) - ((ILfloat*)NewData)[j+3] = 0.0f; - else - ((ILfloat*)NewData)[j+3] = 1.0f; - } - break; - - case IL_DOUBLE: - for (; i < Size; i += Image->Bpp, j += NewBpp) { - ((ILdouble*)NewData)[j] = ((ILdouble*)Image->Data)[i]; - ((ILdouble*)NewData)[j+1] = ((ILdouble*)Image->Data)[i+1]; - ((ILdouble*)NewData)[j+2] = ((ILdouble*)Image->Data)[i+2]; - Same = IL_TRUE; - for (c = 0; c < Image->Bpp; c++) { - if (((ILdouble*)Image->Data)[i+c] != KeyColour[c]) - Same = IL_FALSE; - } - - if (Same) - ((ILdouble*)NewData)[j+3] = 0.0; - else - ((ILdouble*)NewData)[j+3] = 1.0; - } - break; - - default: - ifree(NewData); - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - - Image->Bpp = NewBpp; - Image->Bps = Image->Width * Image->Bpc * NewBpp; - Image->SizeOfPlane = Image->Bps * Image->Height; - Image->SizeOfData = Image->SizeOfPlane * Image->Depth; - ifree(Image->Data); - Image->Data = NewData; - - switch (Image->Format) - { - case IL_RGB: - Image->Format = IL_RGBA; - break; - case IL_BGR: - Image->Format = IL_BGRA; - break; - } - } - else { // IL_COLOUR_INDEX - if (Image->Bpp != 1) { - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - Size = ilGetInteger(IL_PALETTE_NUM_COLS); - if (Size == 0) { - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - if ((ILuint)(KeyAlpha * UCHAR_MAX) > Size) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - switch (Image->Pal.PalType) - { - case IL_PAL_RGB24: - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - if (!ilConvertPal(IL_PAL_RGBA32)) - return IL_FALSE; - break; - case IL_PAL_BGR24: - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - if (!ilConvertPal(IL_PAL_BGRA32)) - return IL_FALSE; - break; - default: - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - // Set the colour index to be transparent. - Image->Pal.Palette[(ILuint)(KeyAlpha * UCHAR_MAX) * 4 + 3] = 0; - - // @TODO: Check if this is the required behaviour. - - if (Image->Pal.PalType == IL_PAL_RGBA32) - ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE); - else - ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE); - } - - return IL_TRUE; -} - - -// Removes alpha from a 32-bit image -// Should we maybe add an option that changes the image based on the alpha? -ILboolean ilRemoveAlpha() -{ - ILubyte *NewData, NewBpp; - ILuint i = 0, j = 0, Size; - - if (iCurImage == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (iCurImage->Bpp != 4) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - Size = iCurImage->Bps * iCurImage->Height; - NewBpp = (ILubyte)(iCurImage->Bpp - 1); - - NewData = (ILubyte*)ialloc(NewBpp * iCurImage->Bpc * iCurImage->Width * iCurImage->Height); - if (NewData == NULL) { - return IL_FALSE; - } - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - NewData[j] = iCurImage->Data[i]; - NewData[j+1] = iCurImage->Data[i+1]; - NewData[j+2] = iCurImage->Data[i+2]; - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILushort*)NewData)[j] = ((ILushort*)iCurImage->Data)[i]; - ((ILushort*)NewData)[j+1] = ((ILushort*)iCurImage->Data)[i+1]; - ((ILushort*)NewData)[j+2] = ((ILushort*)iCurImage->Data)[i+2]; - } - break; - - case IL_INT: - case IL_UNSIGNED_INT: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILuint*)NewData)[j] = ((ILuint*)iCurImage->Data)[i]; - ((ILuint*)NewData)[j+1] = ((ILuint*)iCurImage->Data)[i+1]; - ((ILuint*)NewData)[j+2] = ((ILuint*)iCurImage->Data)[i+2]; - } - break; - - case IL_FLOAT: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILfloat*)NewData)[j] = ((ILfloat*)iCurImage->Data)[i]; - ((ILfloat*)NewData)[j+1] = ((ILfloat*)iCurImage->Data)[i+1]; - ((ILfloat*)NewData)[j+2] = ((ILfloat*)iCurImage->Data)[i+2]; - } - break; - - case IL_DOUBLE: - for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { - ((ILdouble*)NewData)[j] = ((ILdouble*)iCurImage->Data)[i]; - ((ILdouble*)NewData)[j+1] = ((ILdouble*)iCurImage->Data)[i+1]; - ((ILdouble*)NewData)[j+2] = ((ILdouble*)iCurImage->Data)[i+2]; - } - break; - - default: - ifree(NewData); - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - - iCurImage->Bpp = NewBpp; - iCurImage->Bps = iCurImage->Width * iCurImage->Bpc * NewBpp; - iCurImage->SizeOfPlane = iCurImage->Bps * iCurImage->Height; - iCurImage->SizeOfData = iCurImage->SizeOfPlane * iCurImage->Depth; - ifree(iCurImage->Data); - iCurImage->Data = NewData; - - switch (iCurImage->Format) - { - case IL_RGBA: - iCurImage->Format = IL_RGB; - break; - case IL_BGRA: - iCurImage->Format = IL_BGR; - break; - } - - return IL_TRUE; -} - - -ILboolean ilFixCur() -{ - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - if (!ilFlipImage()) { - return IL_FALSE; - } - } - } - - if (ilIsEnabled(IL_TYPE_SET)) { - if ((ILenum)ilGetInteger(IL_TYPE_MODE) != iCurImage->Type) { - if (!ilConvertImage(iCurImage->Format, ilGetInteger(IL_TYPE_MODE))) { - return IL_FALSE; - } - } - } - if (ilIsEnabled(IL_FORMAT_SET)) { - if ((ILenum)ilGetInteger(IL_FORMAT_MODE) != iCurImage->Format) { - if (!ilConvertImage(ilGetInteger(IL_FORMAT_MODE), iCurImage->Type)) { - return IL_FALSE; - } - } - } - - if (iCurImage->Format == IL_COLOUR_INDEX) { - if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { - if (!ilConvertImage(IL_BGR, IL_UNSIGNED_BYTE)) { - return IL_FALSE; - } - } - } -/* Swap Colors on Big Endian !!!!! -#ifdef __BIG_ENDIAN__ - // Swap endian - EndianSwapData(iCurImage); -#endif -*/ - return IL_TRUE; -} - -/* -ILboolean ilFixImage() -{ - ILuint NumImages, i; - - NumImages = ilGetInteger(IL_NUM_IMAGES); - for (i = 0; i < NumImages; i++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveImage(i+1)) - return IL_FALSE; - if (!ilFixCur()) - return IL_FALSE; - } - - NumImages = ilGetInteger(IL_NUM_MIPMAPS); - for (i = 0; i < NumImages; i++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveMipmap(i+1)) - return IL_FALSE; - if (!ilFixCur()) - return IL_FALSE; - } - - NumImages = ilGetInteger(IL_NUM_LAYERS); - for (i = 0; i < NumImages; i++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveLayer(i+1)) - return IL_FALSE; - if (!ilFixCur()) - return IL_FALSE; - } - - ilBindImage(ilGetCurName()); - ilFixCur(); - - return IL_TRUE; -} -*/ - -/* -This function was replaced 20050304, because the previous version -didn't fix the mipmaps of the subimages etc. This version is not -completely correct either, because the subimages of the subimages -etc. are not fixed, but at the moment no images of this type can -be loaded anyway. Thanks to Chris Lux for pointing this out. -*/ - -ILboolean ilFixImage() -{ - ILuint NumFaces, f; - ILuint NumImages, i; - ILuint NumMipmaps,j; - ILuint NumLayers, k; - - NumImages = ilGetInteger(IL_NUM_IMAGES); - for (i = 0; i <= NumImages; i++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveImage(i)) - return IL_FALSE; - - NumFaces = ilGetInteger(IL_NUM_FACES); - for (f = 0; f <= NumFaces; f++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveImage(i)) - return IL_FALSE; - if (!ilActiveFace(f)) - return IL_FALSE; - - NumLayers = ilGetInteger(IL_NUM_LAYERS); - for (k = 0; k <= NumLayers; k++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveImage(i)) - return IL_FALSE; - if (!ilActiveFace(f)) - return IL_FALSE; - if (!ilActiveLayer(k)) - return IL_FALSE; - - NumMipmaps = ilGetInteger(IL_NUM_MIPMAPS); - for (j = 0; j <= NumMipmaps; j++) { - ilBindImage(ilGetCurName()); // Set to parent image first. - if (!ilActiveImage(i)) - return IL_FALSE; - if (!ilActiveFace(f)) - return IL_FALSE; - if (!ilActiveLayer(k)) - return IL_FALSE; - if (!ilActiveMipmap(j)) - return IL_FALSE; - if (!ilFixCur()) - return IL_FALSE; - } - } - } - } - ilBindImage(ilGetCurName()); - - return IL_TRUE; -} diff --git a/DevIL/src-IL/src/il_convert.cpp b/DevIL/src-IL/src/il_convert.cpp new file mode 100644 index 00000000..1f72f4f6 --- /dev/null +++ b/DevIL/src-IL/src/il_convert.cpp @@ -0,0 +1,1125 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_convert.c +// +// Description: Converts between several image formats +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include + + +ILimage *iConvertPalette(ILimage *Image, ILenum DestFormat) +{ + static const ILfloat LumFactor[3] = { 0.212671f, 0.715160f, 0.072169f }; // http://www.inforamp.net/~poynton/ and libpng's libpng.txt - Used for conversion to luminance. + ILimage *NewImage = NULL, *CurImage = NULL; + ILuint i, j, k, c, Size, LumBpp = 1; + ILfloat Resultf; + ILubyte *Temp = NULL; + ILboolean Converted; + ILboolean HasAlpha; + + NewImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0. + if (NewImage == NULL) { + return IL_FALSE; + } + + ilCopyImageAttr(NewImage, Image); + + if (!Image->Pal.Palette || !Image->Pal.PalSize || Image->Pal.PalType == IL_PAL_NONE || Image->Bpp != 1) { + ilCloseImage(NewImage); + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + + if (DestFormat == IL_LUMINANCE || DestFormat == IL_LUMINANCE_ALPHA) { + if (NewImage->Pal.Palette) + ifree(NewImage->Pal.Palette); + if (DestFormat == IL_LUMINANCE_ALPHA) + LumBpp = 2; + + switch (iCurImage->Pal.PalType) + { + case IL_PAL_RGB24: + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + Temp = (ILubyte*)ialloc(LumBpp * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType)); + if (Temp == NULL) + goto alloc_error; + + Size = ilGetBppPal(Image->Pal.PalType); + for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += LumBpp) { + Resultf = 0.0f; + for (c = 0; c < Size; c++) { + Resultf += Image->Pal.Palette[i + c] * LumFactor[c]; + } + Temp[k] = (ILubyte)Resultf; + if (LumBpp == 2) { + if (iCurImage->Pal.PalType == IL_PAL_RGBA32) + Temp[k+1] = Image->Pal.Palette[i + 3]; + else + Temp[k+1] = 0xff; + } + } + + break; + + case IL_PAL_BGR24: + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + Temp = (ILubyte*)ialloc(LumBpp * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType)); + if (Temp == NULL) + goto alloc_error; + + Size = ilGetBppPal(Image->Pal.PalType); + for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += LumBpp) { + Resultf = 0.0f; j = 2; + for (c = 0; c < Size; c++, j--) { + Resultf += Image->Pal.Palette[i + c] * LumFactor[j]; + } + Temp[k] = (ILubyte)Resultf; + if (LumBpp == 2) { + if (iCurImage->Pal.PalType == IL_PAL_RGBA32) + Temp[k+1] = Image->Pal.Palette[i + 3]; + else + Temp[k+1] = 0xff; + } + } + + break; + } + + NewImage->Pal.Palette = NULL; + NewImage->Pal.PalSize = 0; + NewImage->Pal.PalType = IL_PAL_NONE; + NewImage->Format = DestFormat; + NewImage->Bpp = LumBpp; + NewImage->Bps = NewImage->Width * LumBpp; + NewImage->SizeOfData = NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; + NewImage->Data = (ILubyte*)ialloc(NewImage->SizeOfData); + if (NewImage->Data == NULL) + goto alloc_error; + + if (LumBpp == 2) { + for (i = 0; i < Image->SizeOfData; i++) { + NewImage->Data[i*2] = Temp[Image->Data[i] * 2]; + NewImage->Data[i*2+1] = Temp[Image->Data[i] * 2 + 1]; + } + } + else { + for (i = 0; i < Image->SizeOfData; i++) { + NewImage->Data[i] = Temp[Image->Data[i]]; + } + } + + ifree(Temp); + + return NewImage; + } + else if (DestFormat == IL_ALPHA) { + if (NewImage->Pal.Palette) + ifree(NewImage->Pal.Palette); + + switch (iCurImage->Pal.PalType) + { + // Opaque, so all the values are 0xFF. + case IL_PAL_RGB24: + case IL_PAL_RGB32: + case IL_PAL_BGR24: + case IL_PAL_BGR32: + HasAlpha = IL_FALSE; + break; + + case IL_PAL_BGRA32: + case IL_PAL_RGBA32: + HasAlpha = IL_TRUE; + Temp = (ILubyte*)ialloc(1 * Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType)); + if (Temp == NULL) + goto alloc_error; + + Size = ilGetBppPal(Image->Pal.PalType); + for (i = 0, k = 0; i < Image->Pal.PalSize; i += Size, k += 1) { + Temp[k] = Image->Pal.Palette[i + 3]; + } + + break; + } + + NewImage->Pal.Palette = NULL; + NewImage->Pal.PalSize = 0; + NewImage->Pal.PalType = IL_PAL_NONE; + NewImage->Format = DestFormat; + NewImage->Bpp = LumBpp; + NewImage->Bps = NewImage->Width * 1; // Alpha is only one byte. + NewImage->SizeOfData = NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; + NewImage->Data = (ILubyte*)ialloc(NewImage->SizeOfData); + if (NewImage->Data == NULL) + goto alloc_error; + + if (HasAlpha) { + for (i = 0; i < Image->SizeOfData; i++) { + NewImage->Data[i*2] = Temp[Image->Data[i] * 2]; + NewImage->Data[i*2+1] = Temp[Image->Data[i] * 2 + 1]; + } + } + else { // No alpha, opaque. + for (i = 0; i < Image->SizeOfData; i++) { + NewImage->Data[i] = 0xFF; + } + } + + ifree(Temp); + + return NewImage; + } + + //NewImage->Format = ilGetPalBaseType(iCurImage->Pal.PalType); + NewImage->Format = DestFormat; + + if (ilGetBppFormat(NewImage->Format) == 0) { + ilCloseImage(NewImage); + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + + CurImage = iCurImage; + ilSetCurImage(NewImage); + + switch (DestFormat) + { + case IL_RGB: + Converted = ilConvertPal(IL_PAL_RGB24); + break; + + case IL_BGR: + Converted = ilConvertPal(IL_PAL_BGR24); + break; + + case IL_RGBA: + Converted = ilConvertPal(IL_PAL_RGB32); + break; + + case IL_BGRA: + Converted = ilConvertPal(IL_PAL_BGR32); + break; + + case IL_COLOUR_INDEX: + // Just copy the original image over. + NewImage->Data = (ILubyte*)ialloc(CurImage->SizeOfData); + if (NewImage->Data == NULL) + goto alloc_error; + NewImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (NewImage->Pal.Palette == NULL) + goto alloc_error; + memcpy(NewImage->Data, CurImage->Data, CurImage->SizeOfData); + memcpy(NewImage->Pal.Palette, Image->Pal.Palette, Image->Pal.PalSize); + NewImage->Pal.PalSize = Image->Pal.PalSize; + NewImage->Pal.PalType = Image->Pal.PalType; + ilSetCurImage(CurImage); + return NewImage; + + default: + ilCloseImage(NewImage); + ilSetError(IL_INVALID_CONVERSION); + return NULL; + } + + // Resize to new bpp + ilResizeImage(NewImage, NewImage->Width, NewImage->Height, NewImage->Depth, ilGetBppFormat(DestFormat), /*ilGetBpcType(DestType)*/1); + + // ilConvertPal already sets the error message - no need to confuse the user. + if (!Converted) { + ilSetCurImage(CurImage); + ilCloseImage(NewImage); + return NULL; + } + + Size = ilGetBppPal(NewImage->Pal.PalType); + for (i = 0; i < Image->SizeOfData; i++) { + for (c = 0; c < NewImage->Bpp; c++) { + NewImage->Data[i * NewImage->Bpp + c] = NewImage->Pal.Palette[Image->Data[i] * Size + c]; + } + } + + ifree(NewImage->Pal.Palette); + + NewImage->Pal.Palette = NULL; + NewImage->Pal.PalSize = 0; + NewImage->Pal.PalType = IL_PAL_NONE; + ilSetCurImage(CurImage); + + return NewImage; + +alloc_error: + ifree(Temp); + if (NewImage) + ilCloseImage(NewImage); + if (CurImage != iCurImage) + ilSetCurImage(CurImage); + return NULL; +} + + +// In il_quantizer.c +ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols); +// In il_neuquant.c +ILimage *iNeuQuant(ILimage *Image, ILuint NumCols); + +// Converts an image from one format to another +ILAPI ILimage* ILAPIENTRY iConvertImage(ILimage *Image, ILenum DestFormat, ILenum DestType) +{ + ILimage *NewImage, *CurImage; + ILuint i; + ILubyte *NewData; + + CurImage = Image; + if (Image == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + // We don't support 16-bit color indices (or higher). + if (DestFormat == IL_COLOUR_INDEX && DestType >= IL_SHORT) { + ilSetError(IL_INVALID_CONVERSION); + return NULL; + } + + if (Image->Format == IL_COLOUR_INDEX) { + NewImage = iConvertPalette(Image, DestFormat); + + //added test 2003-09-01 + if (NewImage == NULL) + return NULL; + + if (DestType == NewImage->Type) + return NewImage; + + NewData = (ILubyte*)ilConvertBuffer(NewImage->SizeOfData, NewImage->Format, DestFormat, NewImage->Type, DestType, NULL, NewImage->Data); + if (NewData == NULL) { + ifree(NewImage); // ilCloseImage not needed. + return NULL; + } + ifree(NewImage->Data); + NewImage->Data = NewData; + + ilCopyImageAttr(NewImage, Image); + NewImage->Format = DestFormat; + NewImage->Type = DestType; + NewImage->Bpc = ilGetBpcType(DestType); + NewImage->Bpp = ilGetBppFormat(DestFormat); + NewImage->Bps = NewImage->Bpp * NewImage->Bpc * NewImage->Width; + NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; + NewImage->SizeOfData = NewImage->SizeOfPlane * NewImage->Depth; + } + else if (DestFormat == IL_COLOUR_INDEX && Image->Format != IL_LUMINANCE) { + if (iGetInt(IL_QUANTIZATION_MODE) == IL_NEU_QUANT) + return iNeuQuant(Image, iGetInt(IL_MAX_QUANT_INDICES)); + else // Assume IL_WU_QUANT otherwise. + return iQuantizeImage(Image, iGetInt(IL_MAX_QUANT_INDICES)); + } + else { + NewImage = (ILimage*)icalloc(1, sizeof(ILimage)); // Much better to have it all set to 0. + if (NewImage == NULL) { + return NULL; + } + + if (ilGetBppFormat(DestFormat) == 0) { + ilSetError(IL_INVALID_PARAM); + ifree(NewImage); + return NULL; + } + + ilCopyImageAttr(NewImage, Image); + NewImage->Format = DestFormat; + NewImage->Type = DestType; + NewImage->Bpc = ilGetBpcType(DestType); + NewImage->Bpp = ilGetBppFormat(DestFormat); + NewImage->Bps = NewImage->Bpp * NewImage->Bpc * NewImage->Width; + NewImage->SizeOfPlane = NewImage->Bps * NewImage->Height; + NewImage->SizeOfData = NewImage->SizeOfPlane * NewImage->Depth; + + if (DestFormat == IL_COLOUR_INDEX && Image->Format == IL_LUMINANCE) { + NewImage->Pal.PalSize = 768; + NewImage->Pal.PalType = IL_PAL_RGB24; + NewImage->Pal.Palette = (ILubyte*)ialloc(768); + for (i = 0; i < 256; i++) { + NewImage->Pal.Palette[i * 3] = i; + NewImage->Pal.Palette[i * 3 + 1] = i; + NewImage->Pal.Palette[i * 3 + 2] = i; + } + NewImage->Data = (ILubyte*)ialloc(Image->SizeOfData); + if (NewImage->Data == NULL) { + ilCloseImage(NewImage); + return NULL; + } + memcpy(NewImage->Data, Image->Data, Image->SizeOfData); + } + else { + NewImage->Data = (ILubyte*)ilConvertBuffer(Image->SizeOfData, Image->Format, DestFormat, Image->Type, DestType, NULL, Image->Data); + if (NewImage->Data == NULL) { + ifree(NewImage); // ilCloseImage not needed. + return NULL; + } + } + } + + return NewImage; +} + + +//! Converts the current image to the DestFormat format. +/*! \param DestFormat An enum of the desired output format. Any format values are accepted. + \param DestType An enum of the desired output type. Any type values are accepted. + \exception IL_ILLEGAL_OPERATION No currently bound image + \exception IL_INVALID_CONVERSION DestFormat or DestType was an invalid identifier. + \exception IL_OUT_OF_MEMORY Could not allocate enough memory. + \return Boolean value of failure or success*/ +ILboolean ILAPIENTRY ilConvertImage(ILenum DestFormat, ILenum DestType) +{ + ILimage *Image, *pCurImage; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (DestFormat == iCurImage->Format && DestType == iCurImage->Type) + return IL_TRUE; // No conversion needed. + + if (DestType == iCurImage->Type) { + if (iFastConvert(DestFormat)) { + iCurImage->Format = DestFormat; + return IL_TRUE; + } + } + + if (ilIsEnabled(IL_USE_KEY_COLOUR)) { + ilAddAlphaKey(iCurImage); + } + + pCurImage = iCurImage; + while (pCurImage != NULL) + { + Image = iConvertImage(pCurImage, DestFormat, DestType); + if (Image == NULL) + return IL_FALSE; + + //ilCopyImageAttr(pCurImage, Image); // Destroys subimages. + + // We don't copy the colour profile here, since it stays the same. + // Same with the DXTC data. + pCurImage->Format = DestFormat; + pCurImage->Type = DestType; + pCurImage->Bpc = ilGetBpcType(DestType); + pCurImage->Bpp = ilGetBppFormat(DestFormat); + pCurImage->Bps = pCurImage->Width * pCurImage->Bpc * pCurImage->Bpp; + pCurImage->SizeOfPlane = pCurImage->Bps * pCurImage->Height; + pCurImage->SizeOfData = pCurImage->Depth * pCurImage->SizeOfPlane; + if (pCurImage->Pal.Palette && pCurImage->Pal.PalSize && pCurImage->Pal.PalType != IL_PAL_NONE) + ifree(pCurImage->Pal.Palette); + pCurImage->Pal.Palette = Image->Pal.Palette; + pCurImage->Pal.PalSize = Image->Pal.PalSize; + pCurImage->Pal.PalType = Image->Pal.PalType; + Image->Pal.Palette = NULL; + ifree(pCurImage->Data); + pCurImage->Data = Image->Data; + Image->Data = NULL; + ilCloseImage(Image); + + pCurImage = pCurImage->Next; + } + + return IL_TRUE; +} + + +// Swaps the colour order of the current image (rgb(a)->bgr(a) or vice-versa). +// Must be either an 8, 24 or 32-bit (coloured) image (or palette). +ILboolean ilSwapColours() +{ + ILuint i = 0, Size = iCurImage->Bpp * iCurImage->Width * iCurImage->Height; + ILbyte PalBpp = ilGetBppPal(iCurImage->Pal.PalType); + ILushort *ShortPtr; + ILuint *IntPtr, Temp; + ILdouble *DoublePtr, DoubleTemp; + + if ((iCurImage->Bpp != 1 && iCurImage->Bpp != 3 && iCurImage->Bpp != 4)) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + // Just check before we change the format. + if (iCurImage->Format == IL_COLOUR_INDEX) { + if (PalBpp == 0 || iCurImage->Format != IL_COLOUR_INDEX) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + } + + switch (iCurImage->Format) + { + case IL_RGB: + iCurImage->Format = IL_BGR; + break; + case IL_RGBA: + iCurImage->Format = IL_BGRA; + break; + case IL_BGR: + iCurImage->Format = IL_RGB; + break; + case IL_BGRA: + iCurImage->Format = IL_RGBA; + break; + case IL_ALPHA: + case IL_LUMINANCE: + case IL_LUMINANCE_ALPHA: + return IL_TRUE; // No need to do anything to luminance or alpha images. + case IL_COLOUR_INDEX: + switch (iCurImage->Pal.PalType) + { + case IL_PAL_RGB24: + iCurImage->Pal.PalType = IL_PAL_BGR24; + break; + case IL_PAL_RGB32: + iCurImage->Pal.PalType = IL_PAL_BGR32; + break; + case IL_PAL_RGBA32: + iCurImage->Pal.PalType = IL_PAL_BGRA32; + break; + case IL_PAL_BGR24: + iCurImage->Pal.PalType = IL_PAL_RGB24; + break; + case IL_PAL_BGR32: + iCurImage->Pal.PalType = IL_PAL_RGB32; + break; + case IL_PAL_BGRA32: + iCurImage->Pal.PalType = IL_PAL_RGBA32; + break; + default: + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + break; + default: + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (iCurImage->Format == IL_COLOUR_INDEX) { + for (; i < iCurImage->Pal.PalSize; i += PalBpp) { + Temp = iCurImage->Pal.Palette[i]; + iCurImage->Pal.Palette[i] = iCurImage->Pal.Palette[i+2]; + iCurImage->Pal.Palette[i+2] = Temp; + } + } + else { + ShortPtr = (ILushort*)iCurImage->Data; + IntPtr = (ILuint*)iCurImage->Data; + DoublePtr = (ILdouble*)iCurImage->Data; + switch (iCurImage->Bpc) + { + case 1: + for (; i < Size; i += iCurImage->Bpp) { + Temp = iCurImage->Data[i]; + iCurImage->Data[i] = iCurImage->Data[i+2]; + iCurImage->Data[i+2] = Temp; + } + break; + case 2: + for (; i < Size; i += iCurImage->Bpp) { + Temp = ShortPtr[i]; + ShortPtr[i] = ShortPtr[i+2]; + ShortPtr[i+2] = Temp; + } + break; + case 4: // Works fine with ILint, ILuint and ILfloat. + for (; i < Size; i += iCurImage->Bpp) { + Temp = IntPtr[i]; + IntPtr[i] = IntPtr[i+2]; + IntPtr[i+2] = Temp; + } + break; + case 8: + for (; i < Size; i += iCurImage->Bpp) { + DoubleTemp = DoublePtr[i]; + DoublePtr[i] = DoublePtr[i+2]; + DoublePtr[i+2] = DoubleTemp; + } + break; + } + } + + return IL_TRUE; +} + + +// Adds an opaque alpha channel to a 24-bit image +ILboolean ilAddAlpha() +{ + ILubyte *NewData, NewBpp; + ILuint i = 0, j = 0, Size; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (iCurImage->Bpp != 3) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + Size = iCurImage->Bps * iCurImage->Height / iCurImage->Bpc; + NewBpp = (ILubyte)(iCurImage->Bpp + 1); + + NewData = (ILubyte*)ialloc(NewBpp * iCurImage->Bpc * iCurImage->Width * iCurImage->Height); + if (NewData == NULL) { + return IL_FALSE; + } + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + NewData[j] = iCurImage->Data[i]; + NewData[j+1] = iCurImage->Data[i+1]; + NewData[j+2] = iCurImage->Data[i+2]; + NewData[j+3] = UCHAR_MAX; // Max opaqueness + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILushort*)NewData)[j] = ((ILushort*)iCurImage->Data)[i]; + ((ILushort*)NewData)[j+1] = ((ILushort*)iCurImage->Data)[i+1]; + ((ILushort*)NewData)[j+2] = ((ILushort*)iCurImage->Data)[i+2]; + ((ILushort*)NewData)[j+3] = USHRT_MAX; + } + break; + + case IL_INT: + case IL_UNSIGNED_INT: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILuint*)NewData)[j] = ((ILuint*)iCurImage->Data)[i]; + ((ILuint*)NewData)[j+1] = ((ILuint*)iCurImage->Data)[i+1]; + ((ILuint*)NewData)[j+2] = ((ILuint*)iCurImage->Data)[i+2]; + ((ILuint*)NewData)[j+3] = UINT_MAX; + } + break; + + case IL_FLOAT: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILfloat*)NewData)[j] = ((ILfloat*)iCurImage->Data)[i]; + ((ILfloat*)NewData)[j+1] = ((ILfloat*)iCurImage->Data)[i+1]; + ((ILfloat*)NewData)[j+2] = ((ILfloat*)iCurImage->Data)[i+2]; + ((ILfloat*)NewData)[j+3] = 1.0f; + } + break; + + case IL_DOUBLE: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILdouble*)NewData)[j] = ((ILdouble*)iCurImage->Data)[i]; + ((ILdouble*)NewData)[j+1] = ((ILdouble*)iCurImage->Data)[i+1]; + ((ILdouble*)NewData)[j+2] = ((ILdouble*)iCurImage->Data)[i+2]; + ((ILdouble*)NewData)[j+3] = 1.0; + } + break; + + default: + ifree(NewData); + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + + iCurImage->Bpp = NewBpp; + iCurImage->Bps = iCurImage->Width * iCurImage->Bpc * NewBpp; + iCurImage->SizeOfPlane = iCurImage->Bps * iCurImage->Height; + iCurImage->SizeOfData = iCurImage->SizeOfPlane * iCurImage->Depth; + ifree(iCurImage->Data); + iCurImage->Data = NewData; + + switch (iCurImage->Format) + { + case IL_RGB: + iCurImage->Format = IL_RGBA; + break; + case IL_BGR: + iCurImage->Format = IL_BGRA; + break; + } + + return IL_TRUE; +} + + +//ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0; + +void ILAPIENTRY ilKeyColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha) +{ + ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0; + KeyRed = Red; + KeyGreen = Green; + KeyBlue = Blue; + KeyAlpha = Alpha; + return; +} + + +// Adds an alpha channel to an 8 or 24-bit image, +// making the image transparent where Key is equal to the pixel. +ILboolean ilAddAlphaKey(ILimage *Image) +{ + ILfloat KeyRed = 0, KeyGreen = 0, KeyBlue = 0, KeyAlpha = 0; + ILubyte *NewData, NewBpp; + ILfloat KeyColour[3]; + ILuint i = 0, j = 0, c, Size; + ILboolean Same; + + if (Image == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (Image->Format != IL_COLOUR_INDEX) { + if (Image->Bpp != 3) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + if (Image->Format == IL_BGR || Image->Format == IL_BGRA) { + KeyColour[0] = KeyBlue; + KeyColour[1] = KeyGreen; + KeyColour[2] = KeyRed; + } + else { + KeyColour[0] = KeyRed; + KeyColour[1] = KeyGreen; + KeyColour[2] = KeyBlue; + } + + Size = Image->Bps * Image->Height / Image->Bpc; + + NewBpp = (ILubyte)(Image->Bpp + 1); + + NewData = (ILubyte*)ialloc(NewBpp * Image->Bpc * Image->Width * Image->Height); + if (NewData == NULL) { + return IL_FALSE; + } + + switch (Image->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + for (; i < Size; i += Image->Bpp, j += NewBpp) { + NewData[j] = Image->Data[i]; + NewData[j+1] = Image->Data[i+1]; + NewData[j+2] = Image->Data[i+2]; + Same = IL_TRUE; + for (c = 0; c < Image->Bpp; c++) { + if (Image->Data[i+c] != KeyColour[c] * UCHAR_MAX) + Same = IL_FALSE; + } + + if (Same) + NewData[j+3] = 0; // Transparent - matches key colour + else + NewData[j+3] = UCHAR_MAX; + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + for (; i < Size; i += Image->Bpp, j += NewBpp) { + ((ILushort*)NewData)[j] = ((ILushort*)Image->Data)[i]; + ((ILushort*)NewData)[j+1] = ((ILushort*)Image->Data)[i+1]; + ((ILushort*)NewData)[j+2] = ((ILushort*)Image->Data)[i+2]; + Same = IL_TRUE; + for (c = 0; c < Image->Bpp; c++) { + if (((ILushort*)Image->Data)[i+c] != KeyColour[c] * USHRT_MAX) + Same = IL_FALSE; + } + + if (Same) + ((ILushort*)NewData)[j+3] = 0; + else + ((ILushort*)NewData)[j+3] = USHRT_MAX; + } + break; + + case IL_INT: + case IL_UNSIGNED_INT: + for (; i < Size; i += Image->Bpp, j += NewBpp) { + ((ILuint*)NewData)[j] = ((ILuint*)Image->Data)[i]; + ((ILuint*)NewData)[j+1] = ((ILuint*)Image->Data)[i+1]; + ((ILuint*)NewData)[j+2] = ((ILuint*)Image->Data)[i+2]; + Same = IL_TRUE; + for (c = 0; c < Image->Bpp; c++) { + if (((ILuint*)Image->Data)[i+c] != KeyColour[c] * UINT_MAX) + Same = IL_FALSE; + } + + if (Same) + ((ILuint*)NewData)[j+3] = 0; + else + ((ILuint*)NewData)[j+3] = UINT_MAX; + } + break; + + case IL_FLOAT: + for (; i < Size; i += Image->Bpp, j += NewBpp) { + ((ILfloat*)NewData)[j] = ((ILfloat*)Image->Data)[i]; + ((ILfloat*)NewData)[j+1] = ((ILfloat*)Image->Data)[i+1]; + ((ILfloat*)NewData)[j+2] = ((ILfloat*)Image->Data)[i+2]; + Same = IL_TRUE; + for (c = 0; c < Image->Bpp; c++) { + if (((ILfloat*)Image->Data)[i+c] != KeyColour[c]) + Same = IL_FALSE; + } + + if (Same) + ((ILfloat*)NewData)[j+3] = 0.0f; + else + ((ILfloat*)NewData)[j+3] = 1.0f; + } + break; + + case IL_DOUBLE: + for (; i < Size; i += Image->Bpp, j += NewBpp) { + ((ILdouble*)NewData)[j] = ((ILdouble*)Image->Data)[i]; + ((ILdouble*)NewData)[j+1] = ((ILdouble*)Image->Data)[i+1]; + ((ILdouble*)NewData)[j+2] = ((ILdouble*)Image->Data)[i+2]; + Same = IL_TRUE; + for (c = 0; c < Image->Bpp; c++) { + if (((ILdouble*)Image->Data)[i+c] != KeyColour[c]) + Same = IL_FALSE; + } + + if (Same) + ((ILdouble*)NewData)[j+3] = 0.0; + else + ((ILdouble*)NewData)[j+3] = 1.0; + } + break; + + default: + ifree(NewData); + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + + Image->Bpp = NewBpp; + Image->Bps = Image->Width * Image->Bpc * NewBpp; + Image->SizeOfPlane = Image->Bps * Image->Height; + Image->SizeOfData = Image->SizeOfPlane * Image->Depth; + ifree(Image->Data); + Image->Data = NewData; + + switch (Image->Format) + { + case IL_RGB: + Image->Format = IL_RGBA; + break; + case IL_BGR: + Image->Format = IL_BGRA; + break; + } + } + else { // IL_COLOUR_INDEX + if (Image->Bpp != 1) { + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + Size = ilGetInteger(IL_PALETTE_NUM_COLS); + if (Size == 0) { + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + if ((ILuint)(KeyAlpha * UCHAR_MAX) > Size) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + switch (Image->Pal.PalType) + { + case IL_PAL_RGB24: + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + if (!ilConvertPal(IL_PAL_RGBA32)) + return IL_FALSE; + break; + case IL_PAL_BGR24: + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + if (!ilConvertPal(IL_PAL_BGRA32)) + return IL_FALSE; + break; + default: + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + // Set the colour index to be transparent. + Image->Pal.Palette[(ILuint)(KeyAlpha * UCHAR_MAX) * 4 + 3] = 0; + + // @TODO: Check if this is the required behaviour. + + if (Image->Pal.PalType == IL_PAL_RGBA32) + ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE); + else + ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE); + } + + return IL_TRUE; +} + + +// Removes alpha from a 32-bit image +// Should we maybe add an option that changes the image based on the alpha? +ILboolean ilRemoveAlpha() +{ + ILubyte *NewData, NewBpp; + ILuint i = 0, j = 0, Size; + + if (iCurImage == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (iCurImage->Bpp != 4) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + Size = iCurImage->Bps * iCurImage->Height; + NewBpp = (ILubyte)(iCurImage->Bpp - 1); + + NewData = (ILubyte*)ialloc(NewBpp * iCurImage->Bpc * iCurImage->Width * iCurImage->Height); + if (NewData == NULL) { + return IL_FALSE; + } + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + NewData[j] = iCurImage->Data[i]; + NewData[j+1] = iCurImage->Data[i+1]; + NewData[j+2] = iCurImage->Data[i+2]; + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILushort*)NewData)[j] = ((ILushort*)iCurImage->Data)[i]; + ((ILushort*)NewData)[j+1] = ((ILushort*)iCurImage->Data)[i+1]; + ((ILushort*)NewData)[j+2] = ((ILushort*)iCurImage->Data)[i+2]; + } + break; + + case IL_INT: + case IL_UNSIGNED_INT: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILuint*)NewData)[j] = ((ILuint*)iCurImage->Data)[i]; + ((ILuint*)NewData)[j+1] = ((ILuint*)iCurImage->Data)[i+1]; + ((ILuint*)NewData)[j+2] = ((ILuint*)iCurImage->Data)[i+2]; + } + break; + + case IL_FLOAT: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILfloat*)NewData)[j] = ((ILfloat*)iCurImage->Data)[i]; + ((ILfloat*)NewData)[j+1] = ((ILfloat*)iCurImage->Data)[i+1]; + ((ILfloat*)NewData)[j+2] = ((ILfloat*)iCurImage->Data)[i+2]; + } + break; + + case IL_DOUBLE: + for (; i < Size; i += iCurImage->Bpp, j += NewBpp) { + ((ILdouble*)NewData)[j] = ((ILdouble*)iCurImage->Data)[i]; + ((ILdouble*)NewData)[j+1] = ((ILdouble*)iCurImage->Data)[i+1]; + ((ILdouble*)NewData)[j+2] = ((ILdouble*)iCurImage->Data)[i+2]; + } + break; + + default: + ifree(NewData); + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + + iCurImage->Bpp = NewBpp; + iCurImage->Bps = iCurImage->Width * iCurImage->Bpc * NewBpp; + iCurImage->SizeOfPlane = iCurImage->Bps * iCurImage->Height; + iCurImage->SizeOfData = iCurImage->SizeOfPlane * iCurImage->Depth; + ifree(iCurImage->Data); + iCurImage->Data = NewData; + + switch (iCurImage->Format) + { + case IL_RGBA: + iCurImage->Format = IL_RGB; + break; + case IL_BGRA: + iCurImage->Format = IL_BGR; + break; + } + + return IL_TRUE; +} + + +ILboolean ilFixCur() +{ + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + if (!ilFlipImage()) { + return IL_FALSE; + } + } + } + + if (ilIsEnabled(IL_TYPE_SET)) { + if ((ILenum)ilGetInteger(IL_TYPE_MODE) != iCurImage->Type) { + if (!ilConvertImage(iCurImage->Format, ilGetInteger(IL_TYPE_MODE))) { + return IL_FALSE; + } + } + } + if (ilIsEnabled(IL_FORMAT_SET)) { + if ((ILenum)ilGetInteger(IL_FORMAT_MODE) != iCurImage->Format) { + if (!ilConvertImage(ilGetInteger(IL_FORMAT_MODE), iCurImage->Type)) { + return IL_FALSE; + } + } + } + + if (iCurImage->Format == IL_COLOUR_INDEX) { + if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { + if (!ilConvertImage(IL_BGR, IL_UNSIGNED_BYTE)) { + return IL_FALSE; + } + } + } +/* Swap Colors on Big Endian !!!!! +#ifdef __BIG_ENDIAN__ + // Swap endian + EndianSwapData(iCurImage); +#endif +*/ + return IL_TRUE; +} + +/* +ILboolean ilFixImage() +{ + ILuint NumImages, i; + + NumImages = ilGetInteger(IL_NUM_IMAGES); + for (i = 0; i < NumImages; i++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveImage(i+1)) + return IL_FALSE; + if (!ilFixCur()) + return IL_FALSE; + } + + NumImages = ilGetInteger(IL_NUM_MIPMAPS); + for (i = 0; i < NumImages; i++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveMipmap(i+1)) + return IL_FALSE; + if (!ilFixCur()) + return IL_FALSE; + } + + NumImages = ilGetInteger(IL_NUM_LAYERS); + for (i = 0; i < NumImages; i++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveLayer(i+1)) + return IL_FALSE; + if (!ilFixCur()) + return IL_FALSE; + } + + ilBindImage(ilGetCurName()); + ilFixCur(); + + return IL_TRUE; +} +*/ + +/* +This function was replaced 20050304, because the previous version +didn't fix the mipmaps of the subimages etc. This version is not +completely correct either, because the subimages of the subimages +etc. are not fixed, but at the moment no images of this type can +be loaded anyway. Thanks to Chris Lux for pointing this out. +*/ + +ILboolean ilFixImage() +{ + ILuint NumFaces, f; + ILuint NumImages, i; + ILuint NumMipmaps,j; + ILuint NumLayers, k; + + NumImages = ilGetInteger(IL_NUM_IMAGES); + for (i = 0; i <= NumImages; i++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveImage(i)) + return IL_FALSE; + + NumFaces = ilGetInteger(IL_NUM_FACES); + for (f = 0; f <= NumFaces; f++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveImage(i)) + return IL_FALSE; + if (!ilActiveFace(f)) + return IL_FALSE; + + NumLayers = ilGetInteger(IL_NUM_LAYERS); + for (k = 0; k <= NumLayers; k++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveImage(i)) + return IL_FALSE; + if (!ilActiveFace(f)) + return IL_FALSE; + if (!ilActiveLayer(k)) + return IL_FALSE; + + NumMipmaps = ilGetInteger(IL_NUM_MIPMAPS); + for (j = 0; j <= NumMipmaps; j++) { + ilBindImage(ilGetCurName()); // Set to parent image first. + if (!ilActiveImage(i)) + return IL_FALSE; + if (!ilActiveFace(f)) + return IL_FALSE; + if (!ilActiveLayer(k)) + return IL_FALSE; + if (!ilActiveMipmap(j)) + return IL_FALSE; + if (!ilFixCur()) + return IL_FALSE; + } + } + } + } + ilBindImage(ilGetCurName()); + + return IL_TRUE; +} diff --git a/DevIL/src-IL/src/il_cut.c b/DevIL/src-IL/src/il_cut.c deleted file mode 100644 index 100d15ed..00000000 --- a/DevIL/src-IL/src/il_cut.c +++ /dev/null @@ -1,147 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 10/10/2006 -// -// Filename: src-IL/src/il_cut.c -// -// Description: Reads a Dr. Halo .cut file -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_CUT -#include "il_pal.h" -#include "il_bits.h" - - -// Wrap it just in case... -#ifdef _MSC_VER -#pragma pack(push, packed_struct, 1) -#endif -typedef struct CUT_HEAD -{ - ILushort Width; - ILushort Height; - ILint Dummy; -} IL_PACKSTRUCT CUT_HEAD; -#ifdef _MSC_VER -#pragma pack(pop, packed_struct) -#endif - -ILboolean iLoadCutInternal(); - -//! Reads a .cut file -ILboolean ilLoadCut(ILconst_string FileName) -{ - ILHANDLE CutFile; - ILboolean bCut = IL_FALSE; - - CutFile = iopenr(FileName); - if (CutFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bCut; - } - - bCut = ilLoadCutF(CutFile); - icloser(CutFile); - - return bCut; -} - - -//! Reads an already-opened .cut file -ILboolean ilLoadCutF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadCutInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .cut -ILboolean ilLoadCutL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadCutInternal(); -} - - -// Note: .Cut support has not been tested yet! -// A .cut can only have 1 bpp. -// We need to add support for the .pal's PSP outputs with these... -ILboolean iLoadCutInternal() -{ - CUT_HEAD Header; - ILuint Size, i = 0, j; - ILubyte Count, Run; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Header.Width = GetLittleShort(); - Header.Height = GetLittleShort(); - Header.Dummy = GetLittleInt(); - - if (Header.Width == 0 || Header.Height == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { // always 1 bpp - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - Size = Header.Width * Header.Height; - - while (i < Size) { - Count = igetc(); - if (Count == 0) { // end of row - igetc(); // Not supposed to be here, but - igetc(); // PSP is putting these two bytes here...WHY?! - continue; - } - if (Count & BIT_7) { // rle-compressed - ClearBits(Count, BIT_7); - Run = igetc(); - for (j = 0; j < Count; j++) { - iCurImage->Data[i++] = Run; - } - } - else { // run of pixels - for (j = 0; j < Count; j++) { - iCurImage->Data[i++] = igetc(); - } - } - } - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Not sure - - /*iCurImage->Pal.Palette = SharedPal.Palette; - iCurImage->Pal.PalSize = SharedPal.PalSize; - iCurImage->Pal.PalType = SharedPal.PalType;*/ - - return ilFixImage(); -} - -/* ????????? -void ilPopToast() { - ILstring flipCode = IL_TEXT("#flipCode and www.flipCode.com rule you all."); - flipCode[0] = flipCode[0]; -} -*/ - - - -#endif//IL_NO_CUT diff --git a/DevIL/src-IL/src/il_cut.cpp b/DevIL/src-IL/src/il_cut.cpp new file mode 100644 index 00000000..100d15ed --- /dev/null +++ b/DevIL/src-IL/src/il_cut.cpp @@ -0,0 +1,147 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 10/10/2006 +// +// Filename: src-IL/src/il_cut.c +// +// Description: Reads a Dr. Halo .cut file +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_CUT +#include "il_pal.h" +#include "il_bits.h" + + +// Wrap it just in case... +#ifdef _MSC_VER +#pragma pack(push, packed_struct, 1) +#endif +typedef struct CUT_HEAD +{ + ILushort Width; + ILushort Height; + ILint Dummy; +} IL_PACKSTRUCT CUT_HEAD; +#ifdef _MSC_VER +#pragma pack(pop, packed_struct) +#endif + +ILboolean iLoadCutInternal(); + +//! Reads a .cut file +ILboolean ilLoadCut(ILconst_string FileName) +{ + ILHANDLE CutFile; + ILboolean bCut = IL_FALSE; + + CutFile = iopenr(FileName); + if (CutFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bCut; + } + + bCut = ilLoadCutF(CutFile); + icloser(CutFile); + + return bCut; +} + + +//! Reads an already-opened .cut file +ILboolean ilLoadCutF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadCutInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .cut +ILboolean ilLoadCutL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadCutInternal(); +} + + +// Note: .Cut support has not been tested yet! +// A .cut can only have 1 bpp. +// We need to add support for the .pal's PSP outputs with these... +ILboolean iLoadCutInternal() +{ + CUT_HEAD Header; + ILuint Size, i = 0, j; + ILubyte Count, Run; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Header.Width = GetLittleShort(); + Header.Height = GetLittleShort(); + Header.Dummy = GetLittleInt(); + + if (Header.Width == 0 || Header.Height == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { // always 1 bpp + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + Size = Header.Width * Header.Height; + + while (i < Size) { + Count = igetc(); + if (Count == 0) { // end of row + igetc(); // Not supposed to be here, but + igetc(); // PSP is putting these two bytes here...WHY?! + continue; + } + if (Count & BIT_7) { // rle-compressed + ClearBits(Count, BIT_7); + Run = igetc(); + for (j = 0; j < Count; j++) { + iCurImage->Data[i++] = Run; + } + } + else { // run of pixels + for (j = 0; j < Count; j++) { + iCurImage->Data[i++] = igetc(); + } + } + } + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Not sure + + /*iCurImage->Pal.Palette = SharedPal.Palette; + iCurImage->Pal.PalSize = SharedPal.PalSize; + iCurImage->Pal.PalType = SharedPal.PalType;*/ + + return ilFixImage(); +} + +/* ????????? +void ilPopToast() { + ILstring flipCode = IL_TEXT("#flipCode and www.flipCode.com rule you all."); + flipCode[0] = flipCode[0]; +} +*/ + + + +#endif//IL_NO_CUT diff --git a/DevIL/src-IL/src/il_dcx.c b/DevIL/src-IL/src/il_dcx.c deleted file mode 100644 index ec07e3ff..00000000 --- a/DevIL/src-IL/src/il_dcx.c +++ /dev/null @@ -1,485 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_dcx.c -// -// Description: Reads from a .dcx file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_DCX -#include "il_dcx.h" - - -//! Checks if the file specified in FileName is a valid .dcx file. -ILboolean ilIsValidDcx(ILconst_string FileName) -{ - ILHANDLE DcxFile; - ILboolean bDcx = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("dcx"))) { - ilSetError(IL_INVALID_EXTENSION); - return bDcx; - } - - DcxFile = iopenr(FileName); - if (DcxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDcx; - } - - bDcx = ilIsValidDcxF(DcxFile); - icloser(DcxFile); - - return bDcx; -} - - -//! Checks if the ILHANDLE contains a valid .dcx file at the current position. -ILboolean ilIsValidDcxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidDcx(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .dcx lump. -ILboolean ilIsValidDcxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidDcx(); -} - - -// Internal function obtain the .dcx header from the current file. -ILboolean iGetDcxHead(DCXHEAD *Head) -{ - Head->Xmin = GetLittleUShort(); - Head->Ymin = GetLittleUShort(); - Head->Xmax = GetLittleUShort(); - Head->Ymax = GetLittleUShort(); - Head->HDpi = GetLittleUShort(); - Head->VDpi = GetLittleUShort(); - Head->Bps = GetLittleUShort(); - Head->PaletteInfo = GetLittleUShort(); - Head->HScreenSize = GetLittleUShort(); - Head->VScreenSize = GetLittleUShort(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidDcx() -{ - ILuint Signature; - - if (iread(&Signature, 1, 4) != 4) - return IL_FALSE; - iseek(-4, IL_SEEK_CUR); - - return (Signature == 987654321); -} - - -// Internal function used to check if the HEADER is a valid .dcx header. -// Should we also do a check on Header->Bpp? -ILboolean iCheckDcx(DCXHEAD *Header) -{ - ILuint Test, i; - - // There are other versions, but I am not supporting them as of yet. - // Got rid of the Reserved check, because I've seen some .dcx files with invalid values in it. - if (Header->Manufacturer != 10 || Header->Version != 5 || Header->Encoding != 1/* || Header->Reserved != 0*/) - return IL_FALSE; - - // See if the padding size is correct - Test = Header->Xmax - Header->Xmin + 1; - /*if (Header->Bpp >= 8) { - if (Test & 1) { - if (Header->Bps != Test + 1) - return IL_FALSE; - } - else { - if (Header->Bps != Test) // No padding - return IL_FALSE; - } - }*/ - - for (i = 0; i < 54; i++) { - if (Header->Filler[i] != 0) - return IL_FALSE; - } - - return IL_TRUE; -} - - -//! Reads a .dcx file -ILboolean ilLoadDcx(ILconst_string FileName) -{ - ILHANDLE DcxFile; - ILboolean bDcx = IL_FALSE; - - DcxFile = iopenr(FileName); - if (DcxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDcx; - } - - bDcx = ilLoadDcxF(DcxFile); - icloser(DcxFile); - - return bDcx; -} - - -//! Reads an already-opened .dcx file -ILboolean ilLoadDcxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDcxInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .dcx -ILboolean ilLoadDcxL(const void *Lump, ILuint Size) { - iSetInputLump(Lump, Size); - return iLoadDcxInternal(); -} - - -// Internal function used to load the .dcx. -ILboolean iLoadDcxInternal() -{ - DCXHEAD Header; - ILuint Signature, i, Entries[1024], Num = 0; - ILimage *Image, *Base; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iIsValidDcx()) - return IL_FALSE; - iread(&Signature, 1, 4); - - do { - if (iread(&Entries[Num], 1, 4) != 4) - return IL_FALSE; - Num++; - } while (Entries[Num-1] != 0); - - for (i = 0; i < Num; i++) { - iseek(Entries[i], IL_SEEK_SET); - iGetDcxHead(&Header); - /*if (!iCheckDcx(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - }*/ - - Image = iUncompressDcx(&Header); - if (Image == NULL) - return IL_FALSE; - - if (i == 0) { - ilTexImage(Image->Width, Image->Height, 1, Image->Bpp, Image->Format, Image->Type, Image->Data); - Base = iCurImage; - Base->Origin = IL_ORIGIN_UPPER_LEFT; - ilCloseImage(Image); - } - else { - iCurImage->Next = Image; - iCurImage = iCurImage->Next; - } - } - - return ilFixImage(); -} - - -// Internal function to uncompress the .dcx (all .dcx files are rle compressed) -ILimage *iUncompressDcx(DCXHEAD *Header) -{ - ILubyte ByteHead, Colour, *ScanLine = NULL /* Only one plane */; - ILuint c, i, x, y;//, Read = 0; - ILimage *Image = NULL; - - if (Header->Bpp < 8) { - /*ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE;*/ - return iUncompressDcxSmall(Header); - } - - Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1); - if (Image == NULL) - return NULL; - /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - }*/ - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - ScanLine = (ILubyte*)ialloc(Header->Bps); - if (ScanLine == NULL) - goto dcx_error; - - switch (Image->Bpp) - { - case 1: - Image->Format = IL_COLOUR_INDEX; - Image->Pal.PalType = IL_PAL_RGB24; - Image->Pal.PalSize = 256 * 3; // Need to find out for sure... - Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); - if (Image->Pal.Palette == NULL) - goto dcx_error; - break; - //case 2: // No 16-bit images in the dcx format! - case 3: - Image->Format = IL_RGB; - Image->Pal.Palette = NULL; - Image->Pal.PalSize = 0; - Image->Pal.PalType = IL_PAL_NONE; - break; - case 4: - Image->Format = IL_RGBA; - Image->Pal.Palette = NULL; - Image->Pal.PalSize = 0; - Image->Pal.PalType = IL_PAL_NONE; - break; - - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - goto dcx_error; - } - - - /*StartPos = itell(); - Compressed = (ILubyte*)ialloc(Image->SizeOfData * 4 / 3); - iread(Compressed, 1, Image->SizeOfData * 4 / 3); - - for (y = 0; y < Image->Height; y++) { - for (c = 0; c < Image->Bpp; c++) { - x = 0; - while (x < Header->Bps) { - ByteHead = Compressed[Read++]; - if ((ByteHead & 0xC0) == 0xC0) { - ByteHead &= 0x3F; - Colour = Compressed[Read++]; - for (i = 0; i < ByteHead; i++) { - ScanLine[x++] = Colour; - } - } - else { - ScanLine[x++] = ByteHead; - } - } - - for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) - Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; - } - } - } - - ifree(Compressed); - iseek(StartPos + Read, IL_SEEK_SET);*/ - - //changed 2003-09-01 - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->SizeOfData); - - //TODO: because the .pcx-code was broken this - //code is probably broken, too - for (y = 0; y < Image->Height; y++) { - for (c = 0; c < Image->Bpp; c++) { - x = 0; - while (x < Header->Bps) { - if (iread(&ByteHead, 1, 1) != 1) { - iUnCache(); - goto dcx_error; - } - if ((ByteHead & 0xC0) == 0xC0) { - ByteHead &= 0x3F; - if (iread(&Colour, 1, 1) != 1) { - iUnCache(); - goto dcx_error; - } - for (i = 0; i < ByteHead; i++) { - ScanLine[x++] = Colour; - } - } - else { - ScanLine[x++] = ByteHead; - } - } - - for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) - Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; - } - } - } - - iUnCache(); - - - ifree(ScanLine); - - // Read in the palette - if (Image->Bpp == 1) { - ByteHead = igetc(); // the value 12, because it signals there's a palette for some reason... - // We should do a check to make certain it's 12... - if (ByteHead != 12) - iseek(-1, IL_SEEK_CUR); - if (iread(Image->Pal.Palette, 1, Image->Pal.PalSize) != Image->Pal.PalSize) { - ilCloseImage(Image); - return NULL; - } - } - - return Image; - -dcx_error: - ifree(ScanLine); - ilCloseImage(Image); - return NULL; -} - - -ILimage *iUncompressDcxSmall(DCXHEAD *Header) -{ - ILuint i = 0, j, k, c, d, x, y, Bps; - ILubyte HeadByte, Colour, Data = 0, *ScanLine = NULL; - ILimage *Image; - - Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1); - if (Image == NULL) - return NULL; - - /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - }*/ - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - switch (Header->NumPlanes) - { - case 1: - Image->Format = IL_LUMINANCE; - break; - case 4: - Image->Format = IL_COLOUR_INDEX; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - ilCloseImage(Image); - return NULL; - } - - if (Header->NumPlanes == 1) { - for (j = 0; j < Image->Height; j++) { - i = 0; - while (i < Image->Width) { - if (iread(&HeadByte, 1, 1) != 1) - goto file_read_error; - if (HeadByte >= 192) { - HeadByte -= 192; - if (iread(&Data, 1, 1) != 1) - goto file_read_error; - - for (c = 0; c < HeadByte; c++) { - k = 128; - for (d = 0; d < 8 && i < Image->Width; d++) { - Image->Data[j * Image->Width + i++] = (!!(Data & k) == 1 ? 255 : 0); - k >>= 1; - } - } - } - else { - k = 128; - for (c = 0; c < 8 && i < Image->Width; c++) { - Image->Data[j * Image->Width + i++] = (!!(HeadByte & k) == 1 ? 255 : 0); - k >>= 1; - } - } - } - if (Data != 0) - igetc(); // Skip pad byte if last byte not a 0 - } - } - else { // 4-bit images - Bps = Header->Bps * Header->NumPlanes * 2; - Image->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes). - Image->Pal.PalSize = 16 * 3; - Image->Pal.PalType = IL_PAL_RGB24; - ScanLine = (ILubyte*)ialloc(Bps); - if (Image->Pal.Palette == NULL || ScanLine == NULL) { - ifree(ScanLine); - ilCloseImage(Image); - return NULL; - } - - memcpy(Image->Pal.Palette, Header->ColMap, 16 * 3); - imemclear(Image->Data, Image->SizeOfData); // Since we do a += later. - - for (y = 0; y < Image->Height; y++) { - for (c = 0; c < Header->NumPlanes; c++) { - x = 0; - while (x < Bps) { - if (iread(&HeadByte, 1, 1) != 1) - goto file_read_error; - if ((HeadByte & 0xC0) == 0xC0) { - HeadByte &= 0x3F; - if (iread(&Colour, 1, 1) != 1) - goto file_read_error; - for (i = 0; i < HeadByte; i++) { - k = 128; - for (j = 0; j < 8; j++) { - ScanLine[x++] = !!(Colour & k); - k >>= 1; - } - } - } - else { - k = 128; - for (j = 0; j < 8; j++) { - ScanLine[x++] = !!(HeadByte & k); - k >>= 1; - } - } - } - - for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes. ;) - Image->Data[y * Image->Width + x] += ScanLine[x] << c; - } - } - } - ifree(ScanLine); - } - - return Image; - -file_read_error: - ifree(ScanLine); - ilCloseImage(Image); - return NULL; -} - -#endif//IL_NO_DCX diff --git a/DevIL/src-IL/src/il_dcx.cpp b/DevIL/src-IL/src/il_dcx.cpp new file mode 100644 index 00000000..ec07e3ff --- /dev/null +++ b/DevIL/src-IL/src/il_dcx.cpp @@ -0,0 +1,485 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_dcx.c +// +// Description: Reads from a .dcx file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_DCX +#include "il_dcx.h" + + +//! Checks if the file specified in FileName is a valid .dcx file. +ILboolean ilIsValidDcx(ILconst_string FileName) +{ + ILHANDLE DcxFile; + ILboolean bDcx = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("dcx"))) { + ilSetError(IL_INVALID_EXTENSION); + return bDcx; + } + + DcxFile = iopenr(FileName); + if (DcxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDcx; + } + + bDcx = ilIsValidDcxF(DcxFile); + icloser(DcxFile); + + return bDcx; +} + + +//! Checks if the ILHANDLE contains a valid .dcx file at the current position. +ILboolean ilIsValidDcxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidDcx(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .dcx lump. +ILboolean ilIsValidDcxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidDcx(); +} + + +// Internal function obtain the .dcx header from the current file. +ILboolean iGetDcxHead(DCXHEAD *Head) +{ + Head->Xmin = GetLittleUShort(); + Head->Ymin = GetLittleUShort(); + Head->Xmax = GetLittleUShort(); + Head->Ymax = GetLittleUShort(); + Head->HDpi = GetLittleUShort(); + Head->VDpi = GetLittleUShort(); + Head->Bps = GetLittleUShort(); + Head->PaletteInfo = GetLittleUShort(); + Head->HScreenSize = GetLittleUShort(); + Head->VScreenSize = GetLittleUShort(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidDcx() +{ + ILuint Signature; + + if (iread(&Signature, 1, 4) != 4) + return IL_FALSE; + iseek(-4, IL_SEEK_CUR); + + return (Signature == 987654321); +} + + +// Internal function used to check if the HEADER is a valid .dcx header. +// Should we also do a check on Header->Bpp? +ILboolean iCheckDcx(DCXHEAD *Header) +{ + ILuint Test, i; + + // There are other versions, but I am not supporting them as of yet. + // Got rid of the Reserved check, because I've seen some .dcx files with invalid values in it. + if (Header->Manufacturer != 10 || Header->Version != 5 || Header->Encoding != 1/* || Header->Reserved != 0*/) + return IL_FALSE; + + // See if the padding size is correct + Test = Header->Xmax - Header->Xmin + 1; + /*if (Header->Bpp >= 8) { + if (Test & 1) { + if (Header->Bps != Test + 1) + return IL_FALSE; + } + else { + if (Header->Bps != Test) // No padding + return IL_FALSE; + } + }*/ + + for (i = 0; i < 54; i++) { + if (Header->Filler[i] != 0) + return IL_FALSE; + } + + return IL_TRUE; +} + + +//! Reads a .dcx file +ILboolean ilLoadDcx(ILconst_string FileName) +{ + ILHANDLE DcxFile; + ILboolean bDcx = IL_FALSE; + + DcxFile = iopenr(FileName); + if (DcxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDcx; + } + + bDcx = ilLoadDcxF(DcxFile); + icloser(DcxFile); + + return bDcx; +} + + +//! Reads an already-opened .dcx file +ILboolean ilLoadDcxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDcxInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .dcx +ILboolean ilLoadDcxL(const void *Lump, ILuint Size) { + iSetInputLump(Lump, Size); + return iLoadDcxInternal(); +} + + +// Internal function used to load the .dcx. +ILboolean iLoadDcxInternal() +{ + DCXHEAD Header; + ILuint Signature, i, Entries[1024], Num = 0; + ILimage *Image, *Base; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iIsValidDcx()) + return IL_FALSE; + iread(&Signature, 1, 4); + + do { + if (iread(&Entries[Num], 1, 4) != 4) + return IL_FALSE; + Num++; + } while (Entries[Num-1] != 0); + + for (i = 0; i < Num; i++) { + iseek(Entries[i], IL_SEEK_SET); + iGetDcxHead(&Header); + /*if (!iCheckDcx(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + }*/ + + Image = iUncompressDcx(&Header); + if (Image == NULL) + return IL_FALSE; + + if (i == 0) { + ilTexImage(Image->Width, Image->Height, 1, Image->Bpp, Image->Format, Image->Type, Image->Data); + Base = iCurImage; + Base->Origin = IL_ORIGIN_UPPER_LEFT; + ilCloseImage(Image); + } + else { + iCurImage->Next = Image; + iCurImage = iCurImage->Next; + } + } + + return ilFixImage(); +} + + +// Internal function to uncompress the .dcx (all .dcx files are rle compressed) +ILimage *iUncompressDcx(DCXHEAD *Header) +{ + ILubyte ByteHead, Colour, *ScanLine = NULL /* Only one plane */; + ILuint c, i, x, y;//, Read = 0; + ILimage *Image = NULL; + + if (Header->Bpp < 8) { + /*ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE;*/ + return iUncompressDcxSmall(Header); + } + + Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1); + if (Image == NULL) + return NULL; + /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + }*/ + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + ScanLine = (ILubyte*)ialloc(Header->Bps); + if (ScanLine == NULL) + goto dcx_error; + + switch (Image->Bpp) + { + case 1: + Image->Format = IL_COLOUR_INDEX; + Image->Pal.PalType = IL_PAL_RGB24; + Image->Pal.PalSize = 256 * 3; // Need to find out for sure... + Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); + if (Image->Pal.Palette == NULL) + goto dcx_error; + break; + //case 2: // No 16-bit images in the dcx format! + case 3: + Image->Format = IL_RGB; + Image->Pal.Palette = NULL; + Image->Pal.PalSize = 0; + Image->Pal.PalType = IL_PAL_NONE; + break; + case 4: + Image->Format = IL_RGBA; + Image->Pal.Palette = NULL; + Image->Pal.PalSize = 0; + Image->Pal.PalType = IL_PAL_NONE; + break; + + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + goto dcx_error; + } + + + /*StartPos = itell(); + Compressed = (ILubyte*)ialloc(Image->SizeOfData * 4 / 3); + iread(Compressed, 1, Image->SizeOfData * 4 / 3); + + for (y = 0; y < Image->Height; y++) { + for (c = 0; c < Image->Bpp; c++) { + x = 0; + while (x < Header->Bps) { + ByteHead = Compressed[Read++]; + if ((ByteHead & 0xC0) == 0xC0) { + ByteHead &= 0x3F; + Colour = Compressed[Read++]; + for (i = 0; i < ByteHead; i++) { + ScanLine[x++] = Colour; + } + } + else { + ScanLine[x++] = ByteHead; + } + } + + for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) + Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; + } + } + } + + ifree(Compressed); + iseek(StartPos + Read, IL_SEEK_SET);*/ + + //changed 2003-09-01 + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->SizeOfData); + + //TODO: because the .pcx-code was broken this + //code is probably broken, too + for (y = 0; y < Image->Height; y++) { + for (c = 0; c < Image->Bpp; c++) { + x = 0; + while (x < Header->Bps) { + if (iread(&ByteHead, 1, 1) != 1) { + iUnCache(); + goto dcx_error; + } + if ((ByteHead & 0xC0) == 0xC0) { + ByteHead &= 0x3F; + if (iread(&Colour, 1, 1) != 1) { + iUnCache(); + goto dcx_error; + } + for (i = 0; i < ByteHead; i++) { + ScanLine[x++] = Colour; + } + } + else { + ScanLine[x++] = ByteHead; + } + } + + for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) + Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; + } + } + } + + iUnCache(); + + + ifree(ScanLine); + + // Read in the palette + if (Image->Bpp == 1) { + ByteHead = igetc(); // the value 12, because it signals there's a palette for some reason... + // We should do a check to make certain it's 12... + if (ByteHead != 12) + iseek(-1, IL_SEEK_CUR); + if (iread(Image->Pal.Palette, 1, Image->Pal.PalSize) != Image->Pal.PalSize) { + ilCloseImage(Image); + return NULL; + } + } + + return Image; + +dcx_error: + ifree(ScanLine); + ilCloseImage(Image); + return NULL; +} + + +ILimage *iUncompressDcxSmall(DCXHEAD *Header) +{ + ILuint i = 0, j, k, c, d, x, y, Bps; + ILubyte HeadByte, Colour, Data = 0, *ScanLine = NULL; + ILimage *Image; + + Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1); + if (Image == NULL) + return NULL; + + /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + }*/ + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + switch (Header->NumPlanes) + { + case 1: + Image->Format = IL_LUMINANCE; + break; + case 4: + Image->Format = IL_COLOUR_INDEX; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + ilCloseImage(Image); + return NULL; + } + + if (Header->NumPlanes == 1) { + for (j = 0; j < Image->Height; j++) { + i = 0; + while (i < Image->Width) { + if (iread(&HeadByte, 1, 1) != 1) + goto file_read_error; + if (HeadByte >= 192) { + HeadByte -= 192; + if (iread(&Data, 1, 1) != 1) + goto file_read_error; + + for (c = 0; c < HeadByte; c++) { + k = 128; + for (d = 0; d < 8 && i < Image->Width; d++) { + Image->Data[j * Image->Width + i++] = (!!(Data & k) == 1 ? 255 : 0); + k >>= 1; + } + } + } + else { + k = 128; + for (c = 0; c < 8 && i < Image->Width; c++) { + Image->Data[j * Image->Width + i++] = (!!(HeadByte & k) == 1 ? 255 : 0); + k >>= 1; + } + } + } + if (Data != 0) + igetc(); // Skip pad byte if last byte not a 0 + } + } + else { // 4-bit images + Bps = Header->Bps * Header->NumPlanes * 2; + Image->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes). + Image->Pal.PalSize = 16 * 3; + Image->Pal.PalType = IL_PAL_RGB24; + ScanLine = (ILubyte*)ialloc(Bps); + if (Image->Pal.Palette == NULL || ScanLine == NULL) { + ifree(ScanLine); + ilCloseImage(Image); + return NULL; + } + + memcpy(Image->Pal.Palette, Header->ColMap, 16 * 3); + imemclear(Image->Data, Image->SizeOfData); // Since we do a += later. + + for (y = 0; y < Image->Height; y++) { + for (c = 0; c < Header->NumPlanes; c++) { + x = 0; + while (x < Bps) { + if (iread(&HeadByte, 1, 1) != 1) + goto file_read_error; + if ((HeadByte & 0xC0) == 0xC0) { + HeadByte &= 0x3F; + if (iread(&Colour, 1, 1) != 1) + goto file_read_error; + for (i = 0; i < HeadByte; i++) { + k = 128; + for (j = 0; j < 8; j++) { + ScanLine[x++] = !!(Colour & k); + k >>= 1; + } + } + } + else { + k = 128; + for (j = 0; j < 8; j++) { + ScanLine[x++] = !!(HeadByte & k); + k >>= 1; + } + } + } + + for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes. ;) + Image->Data[y * Image->Width + x] += ScanLine[x] << c; + } + } + } + ifree(ScanLine); + } + + return Image; + +file_read_error: + ifree(ScanLine); + ilCloseImage(Image); + return NULL; +} + +#endif//IL_NO_DCX diff --git a/DevIL/src-IL/src/il_dds-save.c b/DevIL/src-IL/src/il_dds-save.c deleted file mode 100644 index 0e8820c9..00000000 --- a/DevIL/src-IL/src/il_dds-save.c +++ /dev/null @@ -1,1313 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/09/2009 -// -// Filename: src-IL/src/il_dds-save.c -// -// Description: Saves a DirectDraw Surface (.dds) file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include "il_dds.h" -#include - - -#ifndef IL_NO_DDS - -//! Writes a Dds file -ILboolean ilSaveDds(const ILstring FileName) -{ - ILHANDLE DdsFile; - ILuint DdsSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - DdsFile = iopenw(FileName); - if (DdsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - DdsSize = ilSaveDdsF(DdsFile); - iclosew(DdsFile); - - if (DdsSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Dds to an already-opened file -ILuint ilSaveDdsF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveDdsInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Dds to a memory "lump" -ILuint ilSaveDdsL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveDdsInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Checks if an image is a cubemap -ILuint GetCubemapInfo(ILimage* image, ILint* faces) -{ - ILint indices[] = { -1, -1, -1, -1, -1, -1 }, i; - ILimage *img; - ILuint ret = 0, srcMipmapCount, srcImagesCount, mipmapCount; - - if (image == NULL) - return 0; - - iGetIntegervImage(image, IL_NUM_IMAGES, (ILint*) &srcImagesCount); - if (srcImagesCount != 5) //write only complete cubemaps (TODO?) - return 0; - - img = image; - iGetIntegervImage(image, IL_NUM_MIPMAPS, (ILint*) &srcMipmapCount); - mipmapCount = srcMipmapCount; - - for (i = 0; i < 6; ++i) { - switch (img->CubeFlags) - { - case DDS_CUBEMAP_POSITIVEX: - indices[i] = 0; - break; - case DDS_CUBEMAP_NEGATIVEX: - indices[i] = 1; - break; - case DDS_CUBEMAP_POSITIVEY: - indices[i] = 2; - break; - case DDS_CUBEMAP_NEGATIVEY: - indices[i] = 3; - break; - case DDS_CUBEMAP_POSITIVEZ: - indices[i] = 4; - break; - case DDS_CUBEMAP_NEGATIVEZ: - indices[i] = 5; - break; - } - iGetIntegervImage(img, IL_NUM_MIPMAPS, (ILint*) &srcMipmapCount); - if (srcMipmapCount != mipmapCount) - return 0; //equal # of mipmaps required - - ret |= img->CubeFlags; - img = img->Next; - } - - for (i = 0; i < 6; ++i) - if (indices[i] == -1) - return 0; //one face not found - - if (ret != 0) //should always be true - ret |= DDS_CUBEMAP; - - for (i = 0; i < 6; ++i) - faces[indices[i]] = i; - - return ret; -} - - -// Internal function used to save the Dds. -ILboolean iSaveDdsInternal() -{ - ILenum DXTCFormat; - ILuint counter, numMipMaps, image, numFaces, i; - ILubyte *CurData = NULL; - ILint CubeTable[6] = { 0 }; - ILuint CubeFlags; - - CubeFlags = GetCubemapInfo(iCurImage, CubeTable); - - image = ilGetInteger(IL_CUR_IMAGE); - DXTCFormat = iGetInt(IL_DXTC_FORMAT); - WriteHeader(iCurImage, DXTCFormat, CubeFlags); - - if (CubeFlags != 0) - numFaces = ilGetInteger(IL_NUM_FACES); // Should always be 5 for now - else - numFaces = 0; - - numMipMaps = ilGetInteger(IL_NUM_MIPMAPS); //this assumes all faces have same # of mipmaps - - for (i = 0; i <= numFaces; ++i) { - for (counter = 0; counter <= numMipMaps; counter++) { - ilBindImage(image); - ilActiveImage(CubeTable[i]); - ilActiveMipmap(counter); - - if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { - CurData = iCurImage->Data; - iCurImage->Data = iGetFlipped(iCurImage); - if (iCurImage->Data == NULL) { - iCurImage->Data = CurData; - return IL_FALSE; - } - } - - if (!Compress(iCurImage, DXTCFormat)) - return IL_FALSE; - - if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { - ifree(iCurImage->Data); - iCurImage->Data = CurData; - } - } - - } - - return IL_TRUE; -} - - -// @TODO: Finish this, as it is incomplete. -ILboolean WriteHeader(ILimage *Image, ILenum DXTCFormat, ILuint CubeFlags) -{ - ILuint i, FourCC, Flags1 = 0, Flags2 = 0, ddsCaps1 = 0, - LinearSize, BlockSize, ddsCaps2 = 0; - - Flags1 |= DDS_LINEARSIZE | DDS_MIPMAPCOUNT - | DDS_WIDTH | DDS_HEIGHT | DDS_CAPS | DDS_PIXELFORMAT; - Flags2 |= DDS_FOURCC; - - if (Image->Depth > 1) - Flags1 |= DDS_DEPTH; - - // @TODO: Fix the pre-multiplied alpha problem. - if (DXTCFormat == IL_DXT2) - DXTCFormat = IL_DXT3; - else if (DXTCFormat == IL_DXT4) - DXTCFormat = IL_DXT5; - - switch (DXTCFormat) - { - case IL_DXT1: - case IL_DXT1A: - FourCC = IL_MAKEFOURCC('D','X','T','1'); - break; - case IL_DXT2: - FourCC = IL_MAKEFOURCC('D','X','T','2'); - break; - case IL_DXT3: - FourCC = IL_MAKEFOURCC('D','X','T','3'); - break; - case IL_DXT4: - FourCC = IL_MAKEFOURCC('D','X','T','4'); - break; - case IL_DXT5: - FourCC = IL_MAKEFOURCC('D','X','T','5'); - break; - case IL_ATI1N: - FourCC = IL_MAKEFOURCC('A', 'T', 'I', '1'); - break; - case IL_3DC: - FourCC = IL_MAKEFOURCC('A','T','I','2'); - break; - case IL_RXGB: - FourCC = IL_MAKEFOURCC('R','X','G','B'); - break; - default: - // Error! - ilSetError(IL_INTERNAL_ERROR); // Should never happen, though. - return IL_FALSE; - } - - iwrite("DDS ", 1, 4); - SaveLittleUInt(124); // Size1 - SaveLittleUInt(Flags1); // Flags1 - SaveLittleUInt(Image->Height); - SaveLittleUInt(Image->Width); - - if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_ATI1N) { - BlockSize = 8; - } - else { - BlockSize = 16; - } - LinearSize = (((Image->Width + 3)/4) * ((Image->Height + 3)/4)) * BlockSize * Image->Depth; - - /* - // doing this is actually wrong, linear size is only size of one cube face - if (CubeFlags != 0) { - ILint numFaces = 0; - for (i = 0; i < 6; ++i) - if (CubeFlags & CubemapDirections[i]) - ++numFaces; - - LinearSize *= numFaces; - } - */ - - SaveLittleUInt(LinearSize); // LinearSize (TODO: change this when uncompressed formats are supported) - - if (Image->Depth > 1) { - SaveLittleUInt(Image->Depth); // Depth - ddsCaps2 |= DDS_VOLUME; - } - else - SaveLittleUInt(0); // Depth - - SaveLittleUInt(ilGetInteger(IL_NUM_MIPMAPS) + 1); // MipMapCount - SaveLittleUInt(0); // AlphaBitDepth - - for (i = 0; i < 10; i++) - SaveLittleUInt(0); // Not used - - SaveLittleUInt(32); // Size2 - SaveLittleUInt(Flags2); // Flags2 - SaveLittleUInt(FourCC); // FourCC - SaveLittleUInt(0); // RGBBitCount - SaveLittleUInt(0); // RBitMask - SaveLittleUInt(0); // GBitMask - SaveLittleUInt(0); // BBitMask - SaveLittleUInt(0); // RGBAlphaBitMask - ddsCaps1 |= DDS_TEXTURE; - //changed 20040516: set mipmap flag on mipmap images - //(non-compressed .dds files still not supported, - //though) - if (ilGetInteger(IL_NUM_MIPMAPS) > 0) - ddsCaps1 |= DDS_MIPMAP | DDS_COMPLEX; - if (CubeFlags != 0) { - ddsCaps1 |= DDS_COMPLEX; - ddsCaps2 |= CubeFlags; - } - - SaveLittleUInt(ddsCaps1); // ddsCaps1 - - SaveLittleUInt(ddsCaps2); // ddsCaps2 - SaveLittleUInt(0); // ddsCaps3 - SaveLittleUInt(0); // ddsCaps4 - SaveLittleUInt(0); // TextureStage - - return IL_TRUE; -} - -#endif//IL_NO_DDS - - -ILuint ILAPIENTRY ilGetDXTCData(void *Buffer, ILuint BufferSize, ILenum DXTCFormat) -{ - ILubyte *CurData = NULL; - ILuint retVal; - ILint BlockNum; - - if (Buffer == NULL) { // Return the number that will be written with a subsequent call. - BlockNum = ((iCurImage->Width + 3)/4) * ((iCurImage->Height + 3)/4) - * iCurImage->Depth; - - switch (DXTCFormat) - { - case IL_DXT1: - case IL_DXT1A: - case IL_ATI1N: - return BlockNum * 8; - case IL_DXT3: - case IL_DXT5: - case IL_3DC: - case IL_RXGB: - return BlockNum * 16; - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return 0; - } - } - - if (DXTCFormat == iCurImage->DxtcFormat && iCurImage->DxtcSize && iCurImage->DxtcData) { - memcpy(Buffer, iCurImage->DxtcData, IL_MIN(BufferSize, iCurImage->DxtcSize)); - return IL_MIN(BufferSize, iCurImage->DxtcSize); - } - - if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { - CurData = iCurImage->Data; - iCurImage->Data = iGetFlipped(iCurImage); - if (iCurImage->Data == NULL) { - iCurImage->Data = CurData; - return 0; - } - } - - //@TODO: Is this the best way to do this? - iSetOutputLump(Buffer, BufferSize); - retVal = Compress(iCurImage, DXTCFormat); - - if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { - ifree(iCurImage->Data); - iCurImage->Data = CurData; - } - - return retVal; -} - - -// Added the next two functions based on Charles Bloom's rant at -// http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html. -// This code is by ryg and from the Molly Rocket forums: -// https://mollyrocket.com/forums/viewtopic.php?t=392. -static ILint Mul8Bit(ILint a, ILint b) -{ - ILint t = a*b + 128; - return (t + (t >> 8)) >> 8; -} - -ILushort As16Bit(ILint r, ILint g, ILint b) -{ - return (Mul8Bit(r,31) << 11) + (Mul8Bit(g,63) << 5) + Mul8Bit(b,31); -} - - -ILushort *CompressTo565(ILimage *Image) -{ - ILimage *TempImage; - ILushort *Data; - ILuint i, j; - - if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) { - TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA. - if (TempImage == NULL) - return NULL; - } - else { - TempImage = Image; - } - - Data = (ILushort*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); - if (Data == NULL) { - if (TempImage != Image) - ilCloseImage(TempImage); - return NULL; - } - - //changed 20040623: Use TempImages format :) - switch (TempImage->Format) - { - case IL_RGB: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { - /*Data[j] = (TempImage->Data[i ] >> 3) << 11; - Data[j] |= (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i+2] >> 3;*/ - Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i+1], TempImage->Data[i+2]); - } - break; - - case IL_RGBA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { - /*Data[j] = (TempImage->Data[i ] >> 3) << 11; - Data[j] |= (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i+2] >> 3;*/ - Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i+1], TempImage->Data[i+2]); - } - break; - - case IL_BGR: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { - /*Data[j] = (TempImage->Data[i+2] >> 3) << 11; - Data[j] |= (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i ] >> 3;*/ - Data[j] = As16Bit(TempImage->Data[i+2], TempImage->Data[i+1], TempImage->Data[i]); - } - break; - - case IL_BGRA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { - /*Data[j] = (TempImage->Data[i+2] >> 3) << 11; - Data[j] |= (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i ] >> 3;*/ - Data[j] = As16Bit(TempImage->Data[i+2], TempImage->Data[i+1], TempImage->Data[i]); - } - break; - - case IL_LUMINANCE: - for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j++) { - //@TODO: Do better conversion here. - /*Data[j] = (TempImage->Data[i] >> 3) << 11; - Data[j] |= (TempImage->Data[i] >> 2) << 5; - Data[j] |= TempImage->Data[i] >> 3;*/ - Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i], TempImage->Data[i]); - } - break; - - case IL_LUMINANCE_ALPHA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 2, j++) { - //@TODO: Do better conversion here. - /*Data[j] = (TempImage->Data[i] >> 3) << 11; - Data[j] |= (TempImage->Data[i] >> 2) << 5; - Data[j] |= TempImage->Data[i] >> 3;*/ - Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i], TempImage->Data[i]); - } - break; - - case IL_ALPHA: - memset(Data, 0, iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); - break; - } - - if (TempImage != Image) - ilCloseImage(TempImage); - - return Data; -} - - -ILubyte *CompressTo88(ILimage *Image) -{ - ILimage *TempImage; - ILubyte *Data; - ILuint i, j; - - if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) { - TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA. - if (TempImage == NULL) - return NULL; - } - else { - TempImage = Image; - } - - Data = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); - if (Data == NULL) { - if (TempImage != Image) - ilCloseImage(TempImage); - return NULL; - } - - //changed 20040623: Use TempImage's format :) - switch (TempImage->Format) - { - case IL_RGB: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j += 2) { - Data[j ] = TempImage->Data[i+1]; - Data[j+1] = TempImage->Data[i ]; - } - break; - - case IL_RGBA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j += 2) { - Data[j ] = TempImage->Data[i+1]; - Data[j+1] = TempImage->Data[i ]; - } - break; - - case IL_BGR: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j += 2) { - Data[j ] = TempImage->Data[i+1]; - Data[j+1] = TempImage->Data[i+2]; - } - break; - - case IL_BGRA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j += 2) { - Data[j ] = TempImage->Data[i+1]; - Data[j+1] = TempImage->Data[i+2]; - } - break; - - case IL_LUMINANCE: - case IL_LUMINANCE_ALPHA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j += 2) { - Data[j ] = Data[j+1] = 0; //??? Luminance is no normal map format... - } - break; - } - - if (TempImage != Image) - ilCloseImage(TempImage); - - return Data; -} - -void CompressToRXGB(ILimage *Image, ILushort** xgb, ILubyte** r) -{ - ILimage *TempImage; - ILuint i, j; - ILushort *Data; - ILubyte *Alpha; - - *xgb = NULL; - *r = NULL; - - if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) { - TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA. - if (TempImage == NULL) - return; - } - else { - TempImage = Image; - } - - *xgb = (ILushort*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); - *r = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth); - if (*xgb == NULL || *r == NULL) { - if (TempImage != Image) - ilCloseImage(TempImage); - return; - } - - //Alias pointers to be able to use copy'n'pasted code :) - Data = *xgb; - Alpha = *r; - - switch (TempImage->Format) - { - case IL_RGB: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { - Alpha[j] = TempImage->Data[i]; - Data[j] = (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i+2] >> 3; - } - break; - - case IL_RGBA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { - Alpha[j] = TempImage->Data[i]; - Data[j] = (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i+2] >> 3; - } - break; - - case IL_BGR: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { - Alpha[j] = TempImage->Data[i+2]; - Data[j] = (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i ] >> 3; - } - break; - - case IL_BGRA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { - Alpha[j] = TempImage->Data[i+2]; - Data[j] = (TempImage->Data[i+1] >> 2) << 5; - Data[j] |= TempImage->Data[i ] >> 3; - } - break; - - case IL_LUMINANCE: - for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j++) { - Alpha[j] = TempImage->Data[i]; - Data[j] = (TempImage->Data[i] >> 2) << 5; - Data[j] |= TempImage->Data[i] >> 3; - } - break; - - case IL_LUMINANCE_ALPHA: - for (i = 0, j = 0; i < TempImage->SizeOfData; i += 2, j++) { - Alpha[j] = TempImage->Data[i]; - Data[j] = (TempImage->Data[i] >> 2) << 5; - Data[j] |= TempImage->Data[i] >> 3; - } - break; - } - - if (TempImage != Image) - ilCloseImage(TempImage); -} - - -ILuint Compress(ILimage *Image, ILenum DXTCFormat) -{ - ILushort *Data, Block[16], ex0, ex1, *Runner16, t0, t1; - ILuint x, y, z, i, BitMask, DXTCSize;//, Rms1, Rms2; - ILubyte *Alpha, AlphaBlock[16], AlphaBitMask[6], /*AlphaOut[16],*/ a0, a1; - ILboolean HasAlpha; - ILuint Count = 0; - ILubyte *Data3Dc, *Runner8, *ByteData, *BlockData; - - if (DXTCFormat == IL_3DC) { - Data3Dc = CompressTo88(Image); - if (Data3Dc == NULL) - return 0; - - Runner8 = Data3Dc; - - for (z = 0; z < Image->Depth; z++) { - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - Get3DcBlock(AlphaBlock, Runner8, Image, x, y, 0); - ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); - GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL); - iputc(a0); - iputc(a1); - iwrite(AlphaBitMask, 1, 6); - - Get3DcBlock(AlphaBlock, Runner8, Image, x, y, 1); - ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); - GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL); - iputc(a0); - iputc(a1); - iwrite(AlphaBitMask, 1, 6); - - Count += 16; - } - } - Runner8 += Image->Width * Image->Height * 2; - } - ifree(Data3Dc); - } - - else if (DXTCFormat == IL_ATI1N) - { - ILimage *TempImage; - - if (Image->Bpp != 1) { - TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return 0; - } - else { - TempImage = Image; - } - - Runner8 = TempImage->Data; - - for (z = 0; z < Image->Depth; z++) { - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); - ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); - GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL); - iputc(a0); - iputc(a1); - iwrite(AlphaBitMask, 1, 6); - Count += 8; - } - } - Runner8 += Image->Width * Image->Height; - } - - if (TempImage != Image) - ilCloseImage(TempImage); - } - else - { - // We want to try nVidia compression first, because it is the fastest. -#ifdef IL_USE_DXTC_NVIDIA - if (ilIsEnabled(IL_NVIDIA_COMPRESS) && Image->Depth == 1) { // See if we need to use the nVidia Texture Tools library. - if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) { - // NVTT needs data as BGRA 32-bit. - if (Image->Format != IL_BGRA || Image->Type != IL_UNSIGNED_BYTE) { // No need to convert if already this format/type. - ByteData = ilConvertBuffer(Image->SizeOfData, Image->Format, IL_BGRA, Image->Type, IL_UNSIGNED_BYTE, NULL, Image->Data); - if (ByteData == NULL) - return 0; - } - else - ByteData = Image->Data; - - // Here's where all the compression and writing goes on. - if (!ilNVidiaCompressDXTFile(ByteData, Image->Width, Image->Height, 1, DXTCFormat)) - return 0; - - if (ByteData != Image->Data) - ifree(ByteData); - - return Image->Width * Image->Height * 4; // Either compresses all or none. - } - } -#endif//IL_USE_DXTC_NVIDIA - - // libsquish generates better quality output than DevIL does, so we try it next. -#ifdef IL_USE_DXTC_SQUISH - if (ilIsEnabled(IL_SQUISH_COMPRESS) && Image->Depth == 1) { // See if we need to use the nVidia Texture Tools library. - if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) { - // libsquish needs data as RGBA 32-bit. - if (Image->Format != IL_RGBA || Image->Type != IL_UNSIGNED_BYTE) { // No need to convert if already this format/type. - ByteData = ilConvertBuffer(Image->SizeOfData, Image->Format, IL_RGBA, Image->Type, IL_UNSIGNED_BYTE, NULL, Image->Data); - if (ByteData == NULL) - return 0; - } - else - ByteData = Image->Data; - - // Get compressed data here. - BlockData = ilSquishCompressDXT(ByteData, Image->Width, Image->Height, 1, DXTCFormat, &DXTCSize); - if (BlockData == NULL) - return 0; - - if (iwrite(BlockData, 1, DXTCSize) != DXTCSize) { - if (ByteData != Image->Data) - ifree(ByteData); - ifree(BlockData); - return 0; - } - - if (ByteData != Image->Data) - ifree(ByteData); - ifree(BlockData); - - return Image->Width * Image->Height * 4; // Either compresses all or none. - } - } -#endif//IL_USE_DXTC_SQUISH - - if (DXTCFormat != IL_RXGB) { - Data = CompressTo565(Image); - if (Data == NULL) - return 0; - - Alpha = ilGetAlpha(IL_UNSIGNED_BYTE); - if (Alpha == NULL) { - ifree(Data); - return 0; - } - } - else { - CompressToRXGB(Image, &Data, &Alpha); - if (Data == NULL || Alpha == NULL) { - if (Data != NULL) - ifree(Data); - if (Alpha != NULL) - ifree(Alpha); - return 0; - } - } - - Runner8 = Alpha; - Runner16 = Data; - - switch (DXTCFormat) - { - case IL_DXT1: - case IL_DXT1A: - for (z = 0; z < Image->Depth; z++) { - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); - HasAlpha = IL_FALSE; - for (i = 0 ; i < 16; i++) { - if (AlphaBlock[i] < 128) { - HasAlpha = IL_TRUE; - break; - } - } - - GetBlock(Block, Runner16, Image, x, y); - ChooseEndpoints(Block, &ex0, &ex1); - CorrectEndDXT1(&ex0, &ex1, HasAlpha); - SaveLittleUShort(ex0); - SaveLittleUShort(ex1); - if (HasAlpha) - BitMask = GenBitMask(ex0, ex1, 3, Block, AlphaBlock, NULL); - else - BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); - SaveLittleUInt(BitMask); - Count += 8; - } - } - - Runner16 += Image->Width * Image->Height; - Runner8 += Image->Width * Image->Height; - } - break; - - /*case IL_DXT2: - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - GetAlphaBlock(AlphaBlock, Alpha, Image, x, y); - for (i = 0; i < 16; i += 2) { - iputc((ILubyte)(((AlphaBlock[i] >> 4) << 4) | (AlphaBlock[i+1] >> 4))); - } - - GetBlock(Block, Data, Image, x, y); - PreMult(Block, AlphaBlock); - ChooseEndpoints(Block, &ex0, &ex1); - SaveLittleUShort(ex0); - SaveLittleUShort(ex1); - BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); - SaveLittleUInt(BitMask); - } - } - break;*/ - - case IL_DXT3: - for (z = 0; z < Image->Depth; z++) { - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); - for (i = 0; i < 16; i += 2) { - iputc((ILubyte)(((AlphaBlock[i+1] >> 4) << 4) | (AlphaBlock[i] >> 4))); - } - - GetBlock(Block, Runner16, Image, x, y); - ChooseEndpoints(Block, &t0, &t1); - ex0 = IL_MAX(t0, t1); - ex1 = IL_MIN(t0, t1); - CorrectEndDXT1(&ex0, &ex1, 0); - SaveLittleUShort(ex0); - SaveLittleUShort(ex1); - BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); - SaveLittleUInt(BitMask); - Count += 16; - } - } - - Runner16 += Image->Width * Image->Height; - Runner8 += Image->Width * Image->Height; - } - break; - - case IL_RXGB: - case IL_DXT5: - for (z = 0; z < Image->Depth; z++) { - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); - ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); - GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL/*AlphaOut*/); - /*Rms2 = RMSAlpha(AlphaBlock, AlphaOut); - GenAlphaBitMask(a0, a1, 8, AlphaBlock, AlphaBitMask, AlphaOut); - Rms1 = RMSAlpha(AlphaBlock, AlphaOut); - if (Rms2 <= Rms1) { // Yeah, we have to regenerate... - GenAlphaBitMask(a0, a1, 6, AlphaBlock, AlphaBitMask, AlphaOut); - Rms2 = a1; // Just reuse Rms2 as a temporary variable... - a1 = a0; - a0 = Rms2; - }*/ - iputc(a0); - iputc(a1); - iwrite(AlphaBitMask, 1, 6); - - GetBlock(Block, Runner16, Image, x, y); - ChooseEndpoints(Block, &t0, &t1); - ex0 = IL_MAX(t0, t1); - ex1 = IL_MIN(t0, t1); - CorrectEndDXT1(&ex0, &ex1, 0); - SaveLittleUShort(ex0); - SaveLittleUShort(ex1); - BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); - SaveLittleUInt(BitMask); - Count += 16; - } - } - - Runner16 += Image->Width * Image->Height; - Runner8 += Image->Width * Image->Height; - } - break; - } - - ifree(Data); - ifree(Alpha); - } //else no 3DC - - return Count; // Returns 0 if no compression was done. -} - - -// Assumed to be 16-bit (5:6:5). -ILboolean GetBlock(ILushort *Block, ILushort *Data, ILimage *Image, ILuint XPos, ILuint YPos) -{ - ILuint x, y, i = 0, Offset = YPos * Image->Width + XPos; - - for (y = 0; y < 4; y++) { - for (x = 0; x < 4; x++) { - if (XPos + x < Image->Width && YPos + y < Image->Height) - Block[i++] = Data[Offset + x]; - else - // Variant of bugfix from https://sourceforge.net/forum/message.php?msg_id=5486779. - // If we are out of bounds of the image, just copy the adjacent data. - Block[i++] = Data[Offset]; - } - // We do not want to read past the end of the image. - if (YPos + y + 1 < Image->Height) - Offset += Image->Width; - } - - return IL_TRUE; -} - - -ILboolean GetAlphaBlock(ILubyte *Block, ILubyte *Data, ILimage *Image, ILuint XPos, ILuint YPos) -{ - ILuint x, y, i = 0, Offset = YPos * Image->Width + XPos; - - for (y = 0; y < 4; y++) { - for (x = 0; x < 4; x++) { - if (XPos + x < Image->Width && YPos + y < Image->Height) - Block[i++] = Data[Offset + x]; - else - // Variant of bugfix from https://sourceforge.net/forum/message.php?msg_id=5486779. - // If we are out of bounds of the image, just copy the adjacent data. - Block[i++] = Data[Offset]; - } - // We do not want to read past the end of the image. - if (YPos + y + 1 < Image->Height) - Offset += Image->Width; - } - - return IL_TRUE; -} - -ILboolean Get3DcBlock(ILubyte *Block, ILubyte *Data, ILimage *Image, ILuint XPos, ILuint YPos, int channel) -{ - ILuint x, y, i = 0, Offset = 2*(YPos * Image->Width + XPos) + channel; - - for (y = 0; y < 4; y++) { - for (x = 0; x < 4; x++) { - if (x < Image->Width && y < Image->Height) - Block[i++] = Data[Offset + 2*x]; - else - Block[i++] = Data[Offset]; - } - Offset += 2*Image->Width; - } - - return IL_TRUE; -} - - -void ShortToColor565(ILushort Pixel, Color565 *Colour) -{ - Colour->nRed = (Pixel & 0xF800) >> 11; - Colour->nGreen = (Pixel & 0x07E0) >> 5; - Colour->nBlue = (Pixel & 0x001F); - return; -} - - -void ShortToColor888(ILushort Pixel, Color888 *Colour) -{ - Colour->r = ((Pixel & 0xF800) >> 11) << 3; - Colour->g = ((Pixel & 0x07E0) >> 5) << 2; - Colour->b = ((Pixel & 0x001F)) << 3; - return; -} - - -ILushort Color565ToShort(Color565 *Colour) -{ - return (Colour->nRed << 11) | (Colour->nGreen << 5) | (Colour->nBlue); -} - - -ILushort Color888ToShort(Color888 *Colour) -{ - return ((Colour->r >> 3) << 11) | ((Colour->g >> 2) << 5) | (Colour->b >> 3); -} - - -ILuint GenBitMask(ILushort ex0, ILushort ex1, ILuint NumCols, ILushort *In, ILubyte *Alpha, Color888 *OutCol) -{ - ILuint i, j, Closest, Dist, BitMask = 0; - ILubyte Mask[16]; - Color888 c, Colours[4]; - - ShortToColor888(ex0, &Colours[0]); - ShortToColor888(ex1, &Colours[1]); - if (NumCols == 3) { - Colours[2].r = (Colours[0].r + Colours[1].r) / 2; - Colours[2].g = (Colours[0].g + Colours[1].g) / 2; - Colours[2].b = (Colours[0].b + Colours[1].b) / 2; - Colours[3].r = (Colours[0].r + Colours[1].r) / 2; - Colours[3].g = (Colours[0].g + Colours[1].g) / 2; - Colours[3].b = (Colours[0].b + Colours[1].b) / 2; - } - else { // NumCols == 4 - Colours[2].r = (2 * Colours[0].r + Colours[1].r + 1) / 3; - Colours[2].g = (2 * Colours[0].g + Colours[1].g + 1) / 3; - Colours[2].b = (2 * Colours[0].b + Colours[1].b + 1) / 3; - Colours[3].r = (Colours[0].r + 2 * Colours[1].r + 1) / 3; - Colours[3].g = (Colours[0].g + 2 * Colours[1].g + 1) / 3; - Colours[3].b = (Colours[0].b + 2 * Colours[1].b + 1) / 3; - } - - for (i = 0; i < 16; i++) { - if (Alpha) { // Test to see if we have 1-bit transparency - if (Alpha[i] < 128) { - Mask[i] = 3; // Transparent - if (OutCol) { - OutCol[i].r = Colours[3].r; - OutCol[i].g = Colours[3].g; - OutCol[i].b = Colours[3].b; - } - continue; - } - } - - // If no transparency, try to find which colour is the closest. - Closest = UINT_MAX; - ShortToColor888(In[i], &c); - for (j = 0; j < NumCols; j++) { - Dist = Distance(&c, &Colours[j]); - if (Dist < Closest) { - Closest = Dist; - Mask[i] = j; - if (OutCol) { - OutCol[i].r = Colours[j].r; - OutCol[i].g = Colours[j].g; - OutCol[i].b = Colours[j].b; - } - } - } - } - - for (i = 0; i < 16; i++) { - BitMask |= (Mask[i] << (i*2)); - } - - return BitMask; -} - - -void GenAlphaBitMask(ILubyte a0, ILubyte a1, ILubyte *In, ILubyte *Mask, ILubyte *Out) -{ - ILubyte Alphas[8], M[16]; - ILuint i, j, Closest, Dist; - - Alphas[0] = a0; - Alphas[1] = a1; - - // 8-alpha or 6-alpha block? - if (a0 > a1) { - // 8-alpha block: derive the other six alphas. - // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. - Alphas[2] = (6 * Alphas[0] + 1 * Alphas[1] + 3) / 7; // bit code 010 - Alphas[3] = (5 * Alphas[0] + 2 * Alphas[1] + 3) / 7; // bit code 011 - Alphas[4] = (4 * Alphas[0] + 3 * Alphas[1] + 3) / 7; // bit code 100 - Alphas[5] = (3 * Alphas[0] + 4 * Alphas[1] + 3) / 7; // bit code 101 - Alphas[6] = (2 * Alphas[0] + 5 * Alphas[1] + 3) / 7; // bit code 110 - Alphas[7] = (1 * Alphas[0] + 6 * Alphas[1] + 3) / 7; // bit code 111 - } - else { - // 6-alpha block. - // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. - Alphas[2] = (4 * Alphas[0] + 1 * Alphas[1] + 2) / 5; // Bit code 010 - Alphas[3] = (3 * Alphas[0] + 2 * Alphas[1] + 2) / 5; // Bit code 011 - Alphas[4] = (2 * Alphas[0] + 3 * Alphas[1] + 2) / 5; // Bit code 100 - Alphas[5] = (1 * Alphas[0] + 4 * Alphas[1] + 2) / 5; // Bit code 101 - Alphas[6] = 0x00; // Bit code 110 - Alphas[7] = 0xFF; // Bit code 111 - } - - for (i = 0; i < 16; i++) { - Closest = UINT_MAX; - for (j = 0; j < 8; j++) { - Dist = abs((ILint)In[i] - (ILint)Alphas[j]); - if (Dist < Closest) { - Closest = Dist; - M[i] = j; - } - } - } - - if (Out) { - for (i = 0; i < 16; i++) { - Out[i] = Alphas[M[i]]; - } - } - - //this was changed 20040623. There was a shift bug in here. Now the code - //produces much higher quality images. - // First three bytes. - Mask[0] = (M[0]) | (M[1] << 3) | ((M[2] & 0x03) << 6); - Mask[1] = ((M[2] & 0x04) >> 2) | (M[3] << 1) | (M[4] << 4) | ((M[5] & 0x01) << 7); - Mask[2] = ((M[5] & 0x06) >> 1) | (M[6] << 2) | (M[7] << 5); - - // Second three bytes. - Mask[3] = (M[8]) | (M[9] << 3) | ((M[10] & 0x03) << 6); - Mask[4] = ((M[10] & 0x04) >> 2) | (M[11] << 1) | (M[12] << 4) | ((M[13] & 0x01) << 7); - Mask[5] = ((M[13] & 0x06) >> 1) | (M[14] << 2) | (M[15] << 5); - - return; -} - - -ILuint RMSAlpha(ILubyte *Orig, ILubyte *Test) -{ - ILuint RMS = 0, i; - ILint d; - - for (i = 0; i < 16; i++) { - d = Orig[i] - Test[i]; - RMS += d*d; - } - - //RMS /= 16; - - return RMS; -} - - -ILuint Distance(Color888 *c1, Color888 *c2) -{ - return (c1->r - c2->r) * (c1->r - c2->r) + - (c1->g - c2->g) * (c1->g - c2->g) + - (c1->b - c2->b) * (c1->b - c2->b); -} - -#define Sum(c) ((c)->r + (c)->g + (c)->b) -#define NormSquared(c) ((c)->r * (c)->r + (c)->g * (c)->g + (c)->b * (c)->b) - -void ChooseEndpoints(ILushort *Block, ILushort *ex0, ILushort *ex1) -{ - ILuint i; - Color888 Colours[16]; - ILint Lowest=0, Highest=0; - - for (i = 0; i < 16; i++) { - ShortToColor888(Block[i], &Colours[i]); - - if (NormSquared(&Colours[i]) < NormSquared(&Colours[Lowest])) - Lowest = i; - if (NormSquared(&Colours[i]) > NormSquared(&Colours[Highest])) - Highest = i; - } - *ex0 = Block[Highest]; - *ex1 = Block[Lowest]; -} - -#undef Sum -#undef NormSquared - - -void ChooseAlphaEndpoints(ILubyte *Block, ILubyte *a0, ILubyte *a1) -{ - ILuint i, Lowest = 0xFF, Highest = 0; - - for (i = 0; i < 16; i++) { - if (Block[i] < Lowest) - Lowest = Block[i]; - if (Block[i] > Highest) - Highest = Block[i]; - } - - *a0 = Lowest; - *a1 = Highest; -} - - -void CorrectEndDXT1(ILushort *ex0, ILushort *ex1, ILboolean HasAlpha) -{ - ILushort Temp; - - if (HasAlpha) { - if (*ex0 > *ex1) { - Temp = *ex0; - *ex0 = *ex1; - *ex1 = Temp; - } - } - else { - if (*ex0 < *ex1) { - Temp = *ex0; - *ex0 = *ex1; - *ex1 = Temp; - } - } - - return; -} - - -void PreMult(ILushort *Data, ILubyte *Alpha) -{ - Color888 Colour; - ILuint i; - - for (i = 0; i < 16; i++) { - ShortToColor888(Data[i], &Colour); - Colour.r = (ILubyte)(((ILuint)Colour.r * Alpha[i]) >> 8); - Colour.g = (ILubyte)(((ILuint)Colour.g * Alpha[i]) >> 8); - Colour.b = (ILubyte)(((ILuint)Colour.b * Alpha[i]) >> 8); - - /*Colour.r = (ILubyte)(Colour.r * (Alpha[i] / 255.0)); - Colour.g = (ILubyte)(Colour.g * (Alpha[i] / 255.0)); - Colour.b = (ILubyte)(Colour.b * (Alpha[i] / 255.0));*/ - - Data[i] = Color888ToShort(&Colour); - ShortToColor888(Data[i], &Colour); - } - - return; -} - - -//! Compresses data to a DXT format using different methods. -// The data must be in unsigned byte RGBA or BGRA format. Only DXT1, DXT3 and DXT5 are supported. -ILAPI ILubyte* ILAPIENTRY ilCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DXTCFormat, ILuint *DXTCSize) -{ - ILimage *TempImage, *CurImage = iCurImage; - ILuint BuffSize; - ILubyte *Buffer; - - if ((DXTCFormat != IL_DXT1 && DXTCFormat != IL_DXT1A && DXTCFormat != IL_DXT3 && DXTCFormat != IL_DXT5) - || Data == NULL || Width == 0 || Height == 0 || Depth == 0) { - ilSetError(IL_INVALID_PARAM); - return NULL; - } - - // We want to try nVidia compression first, because it is the fastest. -#ifdef IL_USE_DXTC_NVIDIA - if (ilIsEnabled(IL_NVIDIA_COMPRESS) && Depth == 1) { // See if we need to use the nVidia Texture Tools library. - // NVTT needs data as BGRA 32-bit. - // Here's where all the compression and writing goes on. - return ilNVidiaCompressDXT(Data, Width, Height, 1, DXTCFormat, DXTCSize); - } -#endif//IL_USE_DXTC_NVIDIA - - // libsquish generates better quality output than DevIL does, so we try it next. -#ifdef IL_USE_DXTC_SQUISH - if (ilIsEnabled(IL_SQUISH_COMPRESS) && Depth == 1) { // See if we need to use the nVidia Texture Tools library. - if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) { - // libsquish needs data as RGBA 32-bit. - // Get compressed data here. - return ilSquishCompressDXT(Data, Width, Height, 1, DXTCFormat, DXTCSize); - } - } -#endif//IL_USE_DXTC_SQUISH - - TempImage = (ILimage*)ialloc(sizeof(ILimage)); - memset(TempImage, 0, sizeof(ILimage)); - TempImage->Width = Width; - TempImage->Height = Height; - TempImage->Depth = Depth; - TempImage->Bpp = 4; // RGBA or BGRA - TempImage->Format = IL_BGRA; - TempImage->Bpc = 1; // Unsigned bytes only - TempImage->Type = IL_UNSIGNED_BYTE; - TempImage->SizeOfPlane = TempImage->Bps * Height; - TempImage->SizeOfData = TempImage->SizeOfPlane * Depth; - TempImage->Origin = IL_ORIGIN_UPPER_LEFT; - TempImage->Data = Data; - - BuffSize = ilGetDXTCData(NULL, 0, DXTCFormat); - if (BuffSize == 0) - return NULL; - Buffer = (ILubyte*)ialloc(BuffSize); - if (Buffer == NULL) - return NULL; - - if (ilGetDXTCData(Buffer, BuffSize, DXTCFormat) != BuffSize) { - ifree(Buffer); - return NULL; - } - *DXTCSize = BuffSize; - - // Restore backup of iCurImage. - iCurImage = CurImage; - TempImage->Data = NULL; - ilCloseImage(TempImage); - - return Buffer; -} diff --git a/DevIL/src-IL/src/il_dds-save.cpp b/DevIL/src-IL/src/il_dds-save.cpp new file mode 100644 index 00000000..0e8820c9 --- /dev/null +++ b/DevIL/src-IL/src/il_dds-save.cpp @@ -0,0 +1,1313 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/09/2009 +// +// Filename: src-IL/src/il_dds-save.c +// +// Description: Saves a DirectDraw Surface (.dds) file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include "il_dds.h" +#include + + +#ifndef IL_NO_DDS + +//! Writes a Dds file +ILboolean ilSaveDds(const ILstring FileName) +{ + ILHANDLE DdsFile; + ILuint DdsSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + DdsFile = iopenw(FileName); + if (DdsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + DdsSize = ilSaveDdsF(DdsFile); + iclosew(DdsFile); + + if (DdsSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Dds to an already-opened file +ILuint ilSaveDdsF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveDdsInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Dds to a memory "lump" +ILuint ilSaveDdsL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveDdsInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Checks if an image is a cubemap +ILuint GetCubemapInfo(ILimage* image, ILint* faces) +{ + ILint indices[] = { -1, -1, -1, -1, -1, -1 }, i; + ILimage *img; + ILuint ret = 0, srcMipmapCount, srcImagesCount, mipmapCount; + + if (image == NULL) + return 0; + + iGetIntegervImage(image, IL_NUM_IMAGES, (ILint*) &srcImagesCount); + if (srcImagesCount != 5) //write only complete cubemaps (TODO?) + return 0; + + img = image; + iGetIntegervImage(image, IL_NUM_MIPMAPS, (ILint*) &srcMipmapCount); + mipmapCount = srcMipmapCount; + + for (i = 0; i < 6; ++i) { + switch (img->CubeFlags) + { + case DDS_CUBEMAP_POSITIVEX: + indices[i] = 0; + break; + case DDS_CUBEMAP_NEGATIVEX: + indices[i] = 1; + break; + case DDS_CUBEMAP_POSITIVEY: + indices[i] = 2; + break; + case DDS_CUBEMAP_NEGATIVEY: + indices[i] = 3; + break; + case DDS_CUBEMAP_POSITIVEZ: + indices[i] = 4; + break; + case DDS_CUBEMAP_NEGATIVEZ: + indices[i] = 5; + break; + } + iGetIntegervImage(img, IL_NUM_MIPMAPS, (ILint*) &srcMipmapCount); + if (srcMipmapCount != mipmapCount) + return 0; //equal # of mipmaps required + + ret |= img->CubeFlags; + img = img->Next; + } + + for (i = 0; i < 6; ++i) + if (indices[i] == -1) + return 0; //one face not found + + if (ret != 0) //should always be true + ret |= DDS_CUBEMAP; + + for (i = 0; i < 6; ++i) + faces[indices[i]] = i; + + return ret; +} + + +// Internal function used to save the Dds. +ILboolean iSaveDdsInternal() +{ + ILenum DXTCFormat; + ILuint counter, numMipMaps, image, numFaces, i; + ILubyte *CurData = NULL; + ILint CubeTable[6] = { 0 }; + ILuint CubeFlags; + + CubeFlags = GetCubemapInfo(iCurImage, CubeTable); + + image = ilGetInteger(IL_CUR_IMAGE); + DXTCFormat = iGetInt(IL_DXTC_FORMAT); + WriteHeader(iCurImage, DXTCFormat, CubeFlags); + + if (CubeFlags != 0) + numFaces = ilGetInteger(IL_NUM_FACES); // Should always be 5 for now + else + numFaces = 0; + + numMipMaps = ilGetInteger(IL_NUM_MIPMAPS); //this assumes all faces have same # of mipmaps + + for (i = 0; i <= numFaces; ++i) { + for (counter = 0; counter <= numMipMaps; counter++) { + ilBindImage(image); + ilActiveImage(CubeTable[i]); + ilActiveMipmap(counter); + + if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { + CurData = iCurImage->Data; + iCurImage->Data = iGetFlipped(iCurImage); + if (iCurImage->Data == NULL) { + iCurImage->Data = CurData; + return IL_FALSE; + } + } + + if (!Compress(iCurImage, DXTCFormat)) + return IL_FALSE; + + if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { + ifree(iCurImage->Data); + iCurImage->Data = CurData; + } + } + + } + + return IL_TRUE; +} + + +// @TODO: Finish this, as it is incomplete. +ILboolean WriteHeader(ILimage *Image, ILenum DXTCFormat, ILuint CubeFlags) +{ + ILuint i, FourCC, Flags1 = 0, Flags2 = 0, ddsCaps1 = 0, + LinearSize, BlockSize, ddsCaps2 = 0; + + Flags1 |= DDS_LINEARSIZE | DDS_MIPMAPCOUNT + | DDS_WIDTH | DDS_HEIGHT | DDS_CAPS | DDS_PIXELFORMAT; + Flags2 |= DDS_FOURCC; + + if (Image->Depth > 1) + Flags1 |= DDS_DEPTH; + + // @TODO: Fix the pre-multiplied alpha problem. + if (DXTCFormat == IL_DXT2) + DXTCFormat = IL_DXT3; + else if (DXTCFormat == IL_DXT4) + DXTCFormat = IL_DXT5; + + switch (DXTCFormat) + { + case IL_DXT1: + case IL_DXT1A: + FourCC = IL_MAKEFOURCC('D','X','T','1'); + break; + case IL_DXT2: + FourCC = IL_MAKEFOURCC('D','X','T','2'); + break; + case IL_DXT3: + FourCC = IL_MAKEFOURCC('D','X','T','3'); + break; + case IL_DXT4: + FourCC = IL_MAKEFOURCC('D','X','T','4'); + break; + case IL_DXT5: + FourCC = IL_MAKEFOURCC('D','X','T','5'); + break; + case IL_ATI1N: + FourCC = IL_MAKEFOURCC('A', 'T', 'I', '1'); + break; + case IL_3DC: + FourCC = IL_MAKEFOURCC('A','T','I','2'); + break; + case IL_RXGB: + FourCC = IL_MAKEFOURCC('R','X','G','B'); + break; + default: + // Error! + ilSetError(IL_INTERNAL_ERROR); // Should never happen, though. + return IL_FALSE; + } + + iwrite("DDS ", 1, 4); + SaveLittleUInt(124); // Size1 + SaveLittleUInt(Flags1); // Flags1 + SaveLittleUInt(Image->Height); + SaveLittleUInt(Image->Width); + + if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_ATI1N) { + BlockSize = 8; + } + else { + BlockSize = 16; + } + LinearSize = (((Image->Width + 3)/4) * ((Image->Height + 3)/4)) * BlockSize * Image->Depth; + + /* + // doing this is actually wrong, linear size is only size of one cube face + if (CubeFlags != 0) { + ILint numFaces = 0; + for (i = 0; i < 6; ++i) + if (CubeFlags & CubemapDirections[i]) + ++numFaces; + + LinearSize *= numFaces; + } + */ + + SaveLittleUInt(LinearSize); // LinearSize (TODO: change this when uncompressed formats are supported) + + if (Image->Depth > 1) { + SaveLittleUInt(Image->Depth); // Depth + ddsCaps2 |= DDS_VOLUME; + } + else + SaveLittleUInt(0); // Depth + + SaveLittleUInt(ilGetInteger(IL_NUM_MIPMAPS) + 1); // MipMapCount + SaveLittleUInt(0); // AlphaBitDepth + + for (i = 0; i < 10; i++) + SaveLittleUInt(0); // Not used + + SaveLittleUInt(32); // Size2 + SaveLittleUInt(Flags2); // Flags2 + SaveLittleUInt(FourCC); // FourCC + SaveLittleUInt(0); // RGBBitCount + SaveLittleUInt(0); // RBitMask + SaveLittleUInt(0); // GBitMask + SaveLittleUInt(0); // BBitMask + SaveLittleUInt(0); // RGBAlphaBitMask + ddsCaps1 |= DDS_TEXTURE; + //changed 20040516: set mipmap flag on mipmap images + //(non-compressed .dds files still not supported, + //though) + if (ilGetInteger(IL_NUM_MIPMAPS) > 0) + ddsCaps1 |= DDS_MIPMAP | DDS_COMPLEX; + if (CubeFlags != 0) { + ddsCaps1 |= DDS_COMPLEX; + ddsCaps2 |= CubeFlags; + } + + SaveLittleUInt(ddsCaps1); // ddsCaps1 + + SaveLittleUInt(ddsCaps2); // ddsCaps2 + SaveLittleUInt(0); // ddsCaps3 + SaveLittleUInt(0); // ddsCaps4 + SaveLittleUInt(0); // TextureStage + + return IL_TRUE; +} + +#endif//IL_NO_DDS + + +ILuint ILAPIENTRY ilGetDXTCData(void *Buffer, ILuint BufferSize, ILenum DXTCFormat) +{ + ILubyte *CurData = NULL; + ILuint retVal; + ILint BlockNum; + + if (Buffer == NULL) { // Return the number that will be written with a subsequent call. + BlockNum = ((iCurImage->Width + 3)/4) * ((iCurImage->Height + 3)/4) + * iCurImage->Depth; + + switch (DXTCFormat) + { + case IL_DXT1: + case IL_DXT1A: + case IL_ATI1N: + return BlockNum * 8; + case IL_DXT3: + case IL_DXT5: + case IL_3DC: + case IL_RXGB: + return BlockNum * 16; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return 0; + } + } + + if (DXTCFormat == iCurImage->DxtcFormat && iCurImage->DxtcSize && iCurImage->DxtcData) { + memcpy(Buffer, iCurImage->DxtcData, IL_MIN(BufferSize, iCurImage->DxtcSize)); + return IL_MIN(BufferSize, iCurImage->DxtcSize); + } + + if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { + CurData = iCurImage->Data; + iCurImage->Data = iGetFlipped(iCurImage); + if (iCurImage->Data == NULL) { + iCurImage->Data = CurData; + return 0; + } + } + + //@TODO: Is this the best way to do this? + iSetOutputLump(Buffer, BufferSize); + retVal = Compress(iCurImage, DXTCFormat); + + if (iCurImage->Origin != IL_ORIGIN_UPPER_LEFT) { + ifree(iCurImage->Data); + iCurImage->Data = CurData; + } + + return retVal; +} + + +// Added the next two functions based on Charles Bloom's rant at +// http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html. +// This code is by ryg and from the Molly Rocket forums: +// https://mollyrocket.com/forums/viewtopic.php?t=392. +static ILint Mul8Bit(ILint a, ILint b) +{ + ILint t = a*b + 128; + return (t + (t >> 8)) >> 8; +} + +ILushort As16Bit(ILint r, ILint g, ILint b) +{ + return (Mul8Bit(r,31) << 11) + (Mul8Bit(g,63) << 5) + Mul8Bit(b,31); +} + + +ILushort *CompressTo565(ILimage *Image) +{ + ILimage *TempImage; + ILushort *Data; + ILuint i, j; + + if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) { + TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA. + if (TempImage == NULL) + return NULL; + } + else { + TempImage = Image; + } + + Data = (ILushort*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); + if (Data == NULL) { + if (TempImage != Image) + ilCloseImage(TempImage); + return NULL; + } + + //changed 20040623: Use TempImages format :) + switch (TempImage->Format) + { + case IL_RGB: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { + /*Data[j] = (TempImage->Data[i ] >> 3) << 11; + Data[j] |= (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i+2] >> 3;*/ + Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i+1], TempImage->Data[i+2]); + } + break; + + case IL_RGBA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { + /*Data[j] = (TempImage->Data[i ] >> 3) << 11; + Data[j] |= (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i+2] >> 3;*/ + Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i+1], TempImage->Data[i+2]); + } + break; + + case IL_BGR: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { + /*Data[j] = (TempImage->Data[i+2] >> 3) << 11; + Data[j] |= (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i ] >> 3;*/ + Data[j] = As16Bit(TempImage->Data[i+2], TempImage->Data[i+1], TempImage->Data[i]); + } + break; + + case IL_BGRA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { + /*Data[j] = (TempImage->Data[i+2] >> 3) << 11; + Data[j] |= (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i ] >> 3;*/ + Data[j] = As16Bit(TempImage->Data[i+2], TempImage->Data[i+1], TempImage->Data[i]); + } + break; + + case IL_LUMINANCE: + for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j++) { + //@TODO: Do better conversion here. + /*Data[j] = (TempImage->Data[i] >> 3) << 11; + Data[j] |= (TempImage->Data[i] >> 2) << 5; + Data[j] |= TempImage->Data[i] >> 3;*/ + Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i], TempImage->Data[i]); + } + break; + + case IL_LUMINANCE_ALPHA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 2, j++) { + //@TODO: Do better conversion here. + /*Data[j] = (TempImage->Data[i] >> 3) << 11; + Data[j] |= (TempImage->Data[i] >> 2) << 5; + Data[j] |= TempImage->Data[i] >> 3;*/ + Data[j] = As16Bit(TempImage->Data[i], TempImage->Data[i], TempImage->Data[i]); + } + break; + + case IL_ALPHA: + memset(Data, 0, iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); + break; + } + + if (TempImage != Image) + ilCloseImage(TempImage); + + return Data; +} + + +ILubyte *CompressTo88(ILimage *Image) +{ + ILimage *TempImage; + ILubyte *Data; + ILuint i, j; + + if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) { + TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA. + if (TempImage == NULL) + return NULL; + } + else { + TempImage = Image; + } + + Data = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); + if (Data == NULL) { + if (TempImage != Image) + ilCloseImage(TempImage); + return NULL; + } + + //changed 20040623: Use TempImage's format :) + switch (TempImage->Format) + { + case IL_RGB: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j += 2) { + Data[j ] = TempImage->Data[i+1]; + Data[j+1] = TempImage->Data[i ]; + } + break; + + case IL_RGBA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j += 2) { + Data[j ] = TempImage->Data[i+1]; + Data[j+1] = TempImage->Data[i ]; + } + break; + + case IL_BGR: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j += 2) { + Data[j ] = TempImage->Data[i+1]; + Data[j+1] = TempImage->Data[i+2]; + } + break; + + case IL_BGRA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j += 2) { + Data[j ] = TempImage->Data[i+1]; + Data[j+1] = TempImage->Data[i+2]; + } + break; + + case IL_LUMINANCE: + case IL_LUMINANCE_ALPHA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j += 2) { + Data[j ] = Data[j+1] = 0; //??? Luminance is no normal map format... + } + break; + } + + if (TempImage != Image) + ilCloseImage(TempImage); + + return Data; +} + +void CompressToRXGB(ILimage *Image, ILushort** xgb, ILubyte** r) +{ + ILimage *TempImage; + ILuint i, j; + ILushort *Data; + ILubyte *Alpha; + + *xgb = NULL; + *r = NULL; + + if ((Image->Type != IL_UNSIGNED_BYTE && Image->Type != IL_BYTE) || Image->Format == IL_COLOUR_INDEX) { + TempImage = iConvertImage(iCurImage, IL_BGR, IL_UNSIGNED_BYTE); // @TODO: Needs to be BGRA. + if (TempImage == NULL) + return; + } + else { + TempImage = Image; + } + + *xgb = (ILushort*)ialloc(iCurImage->Width * iCurImage->Height * 2 * iCurImage->Depth); + *r = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth); + if (*xgb == NULL || *r == NULL) { + if (TempImage != Image) + ilCloseImage(TempImage); + return; + } + + //Alias pointers to be able to use copy'n'pasted code :) + Data = *xgb; + Alpha = *r; + + switch (TempImage->Format) + { + case IL_RGB: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { + Alpha[j] = TempImage->Data[i]; + Data[j] = (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i+2] >> 3; + } + break; + + case IL_RGBA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { + Alpha[j] = TempImage->Data[i]; + Data[j] = (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i+2] >> 3; + } + break; + + case IL_BGR: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 3, j++) { + Alpha[j] = TempImage->Data[i+2]; + Data[j] = (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i ] >> 3; + } + break; + + case IL_BGRA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 4, j++) { + Alpha[j] = TempImage->Data[i+2]; + Data[j] = (TempImage->Data[i+1] >> 2) << 5; + Data[j] |= TempImage->Data[i ] >> 3; + } + break; + + case IL_LUMINANCE: + for (i = 0, j = 0; i < TempImage->SizeOfData; i++, j++) { + Alpha[j] = TempImage->Data[i]; + Data[j] = (TempImage->Data[i] >> 2) << 5; + Data[j] |= TempImage->Data[i] >> 3; + } + break; + + case IL_LUMINANCE_ALPHA: + for (i = 0, j = 0; i < TempImage->SizeOfData; i += 2, j++) { + Alpha[j] = TempImage->Data[i]; + Data[j] = (TempImage->Data[i] >> 2) << 5; + Data[j] |= TempImage->Data[i] >> 3; + } + break; + } + + if (TempImage != Image) + ilCloseImage(TempImage); +} + + +ILuint Compress(ILimage *Image, ILenum DXTCFormat) +{ + ILushort *Data, Block[16], ex0, ex1, *Runner16, t0, t1; + ILuint x, y, z, i, BitMask, DXTCSize;//, Rms1, Rms2; + ILubyte *Alpha, AlphaBlock[16], AlphaBitMask[6], /*AlphaOut[16],*/ a0, a1; + ILboolean HasAlpha; + ILuint Count = 0; + ILubyte *Data3Dc, *Runner8, *ByteData, *BlockData; + + if (DXTCFormat == IL_3DC) { + Data3Dc = CompressTo88(Image); + if (Data3Dc == NULL) + return 0; + + Runner8 = Data3Dc; + + for (z = 0; z < Image->Depth; z++) { + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + Get3DcBlock(AlphaBlock, Runner8, Image, x, y, 0); + ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); + GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL); + iputc(a0); + iputc(a1); + iwrite(AlphaBitMask, 1, 6); + + Get3DcBlock(AlphaBlock, Runner8, Image, x, y, 1); + ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); + GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL); + iputc(a0); + iputc(a1); + iwrite(AlphaBitMask, 1, 6); + + Count += 16; + } + } + Runner8 += Image->Width * Image->Height * 2; + } + ifree(Data3Dc); + } + + else if (DXTCFormat == IL_ATI1N) + { + ILimage *TempImage; + + if (Image->Bpp != 1) { + TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return 0; + } + else { + TempImage = Image; + } + + Runner8 = TempImage->Data; + + for (z = 0; z < Image->Depth; z++) { + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); + ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); + GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL); + iputc(a0); + iputc(a1); + iwrite(AlphaBitMask, 1, 6); + Count += 8; + } + } + Runner8 += Image->Width * Image->Height; + } + + if (TempImage != Image) + ilCloseImage(TempImage); + } + else + { + // We want to try nVidia compression first, because it is the fastest. +#ifdef IL_USE_DXTC_NVIDIA + if (ilIsEnabled(IL_NVIDIA_COMPRESS) && Image->Depth == 1) { // See if we need to use the nVidia Texture Tools library. + if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) { + // NVTT needs data as BGRA 32-bit. + if (Image->Format != IL_BGRA || Image->Type != IL_UNSIGNED_BYTE) { // No need to convert if already this format/type. + ByteData = ilConvertBuffer(Image->SizeOfData, Image->Format, IL_BGRA, Image->Type, IL_UNSIGNED_BYTE, NULL, Image->Data); + if (ByteData == NULL) + return 0; + } + else + ByteData = Image->Data; + + // Here's where all the compression and writing goes on. + if (!ilNVidiaCompressDXTFile(ByteData, Image->Width, Image->Height, 1, DXTCFormat)) + return 0; + + if (ByteData != Image->Data) + ifree(ByteData); + + return Image->Width * Image->Height * 4; // Either compresses all or none. + } + } +#endif//IL_USE_DXTC_NVIDIA + + // libsquish generates better quality output than DevIL does, so we try it next. +#ifdef IL_USE_DXTC_SQUISH + if (ilIsEnabled(IL_SQUISH_COMPRESS) && Image->Depth == 1) { // See if we need to use the nVidia Texture Tools library. + if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) { + // libsquish needs data as RGBA 32-bit. + if (Image->Format != IL_RGBA || Image->Type != IL_UNSIGNED_BYTE) { // No need to convert if already this format/type. + ByteData = ilConvertBuffer(Image->SizeOfData, Image->Format, IL_RGBA, Image->Type, IL_UNSIGNED_BYTE, NULL, Image->Data); + if (ByteData == NULL) + return 0; + } + else + ByteData = Image->Data; + + // Get compressed data here. + BlockData = ilSquishCompressDXT(ByteData, Image->Width, Image->Height, 1, DXTCFormat, &DXTCSize); + if (BlockData == NULL) + return 0; + + if (iwrite(BlockData, 1, DXTCSize) != DXTCSize) { + if (ByteData != Image->Data) + ifree(ByteData); + ifree(BlockData); + return 0; + } + + if (ByteData != Image->Data) + ifree(ByteData); + ifree(BlockData); + + return Image->Width * Image->Height * 4; // Either compresses all or none. + } + } +#endif//IL_USE_DXTC_SQUISH + + if (DXTCFormat != IL_RXGB) { + Data = CompressTo565(Image); + if (Data == NULL) + return 0; + + Alpha = ilGetAlpha(IL_UNSIGNED_BYTE); + if (Alpha == NULL) { + ifree(Data); + return 0; + } + } + else { + CompressToRXGB(Image, &Data, &Alpha); + if (Data == NULL || Alpha == NULL) { + if (Data != NULL) + ifree(Data); + if (Alpha != NULL) + ifree(Alpha); + return 0; + } + } + + Runner8 = Alpha; + Runner16 = Data; + + switch (DXTCFormat) + { + case IL_DXT1: + case IL_DXT1A: + for (z = 0; z < Image->Depth; z++) { + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); + HasAlpha = IL_FALSE; + for (i = 0 ; i < 16; i++) { + if (AlphaBlock[i] < 128) { + HasAlpha = IL_TRUE; + break; + } + } + + GetBlock(Block, Runner16, Image, x, y); + ChooseEndpoints(Block, &ex0, &ex1); + CorrectEndDXT1(&ex0, &ex1, HasAlpha); + SaveLittleUShort(ex0); + SaveLittleUShort(ex1); + if (HasAlpha) + BitMask = GenBitMask(ex0, ex1, 3, Block, AlphaBlock, NULL); + else + BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); + SaveLittleUInt(BitMask); + Count += 8; + } + } + + Runner16 += Image->Width * Image->Height; + Runner8 += Image->Width * Image->Height; + } + break; + + /*case IL_DXT2: + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + GetAlphaBlock(AlphaBlock, Alpha, Image, x, y); + for (i = 0; i < 16; i += 2) { + iputc((ILubyte)(((AlphaBlock[i] >> 4) << 4) | (AlphaBlock[i+1] >> 4))); + } + + GetBlock(Block, Data, Image, x, y); + PreMult(Block, AlphaBlock); + ChooseEndpoints(Block, &ex0, &ex1); + SaveLittleUShort(ex0); + SaveLittleUShort(ex1); + BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); + SaveLittleUInt(BitMask); + } + } + break;*/ + + case IL_DXT3: + for (z = 0; z < Image->Depth; z++) { + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); + for (i = 0; i < 16; i += 2) { + iputc((ILubyte)(((AlphaBlock[i+1] >> 4) << 4) | (AlphaBlock[i] >> 4))); + } + + GetBlock(Block, Runner16, Image, x, y); + ChooseEndpoints(Block, &t0, &t1); + ex0 = IL_MAX(t0, t1); + ex1 = IL_MIN(t0, t1); + CorrectEndDXT1(&ex0, &ex1, 0); + SaveLittleUShort(ex0); + SaveLittleUShort(ex1); + BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); + SaveLittleUInt(BitMask); + Count += 16; + } + } + + Runner16 += Image->Width * Image->Height; + Runner8 += Image->Width * Image->Height; + } + break; + + case IL_RXGB: + case IL_DXT5: + for (z = 0; z < Image->Depth; z++) { + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + GetAlphaBlock(AlphaBlock, Runner8, Image, x, y); + ChooseAlphaEndpoints(AlphaBlock, &a0, &a1); + GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL/*AlphaOut*/); + /*Rms2 = RMSAlpha(AlphaBlock, AlphaOut); + GenAlphaBitMask(a0, a1, 8, AlphaBlock, AlphaBitMask, AlphaOut); + Rms1 = RMSAlpha(AlphaBlock, AlphaOut); + if (Rms2 <= Rms1) { // Yeah, we have to regenerate... + GenAlphaBitMask(a0, a1, 6, AlphaBlock, AlphaBitMask, AlphaOut); + Rms2 = a1; // Just reuse Rms2 as a temporary variable... + a1 = a0; + a0 = Rms2; + }*/ + iputc(a0); + iputc(a1); + iwrite(AlphaBitMask, 1, 6); + + GetBlock(Block, Runner16, Image, x, y); + ChooseEndpoints(Block, &t0, &t1); + ex0 = IL_MAX(t0, t1); + ex1 = IL_MIN(t0, t1); + CorrectEndDXT1(&ex0, &ex1, 0); + SaveLittleUShort(ex0); + SaveLittleUShort(ex1); + BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL); + SaveLittleUInt(BitMask); + Count += 16; + } + } + + Runner16 += Image->Width * Image->Height; + Runner8 += Image->Width * Image->Height; + } + break; + } + + ifree(Data); + ifree(Alpha); + } //else no 3DC + + return Count; // Returns 0 if no compression was done. +} + + +// Assumed to be 16-bit (5:6:5). +ILboolean GetBlock(ILushort *Block, ILushort *Data, ILimage *Image, ILuint XPos, ILuint YPos) +{ + ILuint x, y, i = 0, Offset = YPos * Image->Width + XPos; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + if (XPos + x < Image->Width && YPos + y < Image->Height) + Block[i++] = Data[Offset + x]; + else + // Variant of bugfix from https://sourceforge.net/forum/message.php?msg_id=5486779. + // If we are out of bounds of the image, just copy the adjacent data. + Block[i++] = Data[Offset]; + } + // We do not want to read past the end of the image. + if (YPos + y + 1 < Image->Height) + Offset += Image->Width; + } + + return IL_TRUE; +} + + +ILboolean GetAlphaBlock(ILubyte *Block, ILubyte *Data, ILimage *Image, ILuint XPos, ILuint YPos) +{ + ILuint x, y, i = 0, Offset = YPos * Image->Width + XPos; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + if (XPos + x < Image->Width && YPos + y < Image->Height) + Block[i++] = Data[Offset + x]; + else + // Variant of bugfix from https://sourceforge.net/forum/message.php?msg_id=5486779. + // If we are out of bounds of the image, just copy the adjacent data. + Block[i++] = Data[Offset]; + } + // We do not want to read past the end of the image. + if (YPos + y + 1 < Image->Height) + Offset += Image->Width; + } + + return IL_TRUE; +} + +ILboolean Get3DcBlock(ILubyte *Block, ILubyte *Data, ILimage *Image, ILuint XPos, ILuint YPos, int channel) +{ + ILuint x, y, i = 0, Offset = 2*(YPos * Image->Width + XPos) + channel; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + if (x < Image->Width && y < Image->Height) + Block[i++] = Data[Offset + 2*x]; + else + Block[i++] = Data[Offset]; + } + Offset += 2*Image->Width; + } + + return IL_TRUE; +} + + +void ShortToColor565(ILushort Pixel, Color565 *Colour) +{ + Colour->nRed = (Pixel & 0xF800) >> 11; + Colour->nGreen = (Pixel & 0x07E0) >> 5; + Colour->nBlue = (Pixel & 0x001F); + return; +} + + +void ShortToColor888(ILushort Pixel, Color888 *Colour) +{ + Colour->r = ((Pixel & 0xF800) >> 11) << 3; + Colour->g = ((Pixel & 0x07E0) >> 5) << 2; + Colour->b = ((Pixel & 0x001F)) << 3; + return; +} + + +ILushort Color565ToShort(Color565 *Colour) +{ + return (Colour->nRed << 11) | (Colour->nGreen << 5) | (Colour->nBlue); +} + + +ILushort Color888ToShort(Color888 *Colour) +{ + return ((Colour->r >> 3) << 11) | ((Colour->g >> 2) << 5) | (Colour->b >> 3); +} + + +ILuint GenBitMask(ILushort ex0, ILushort ex1, ILuint NumCols, ILushort *In, ILubyte *Alpha, Color888 *OutCol) +{ + ILuint i, j, Closest, Dist, BitMask = 0; + ILubyte Mask[16]; + Color888 c, Colours[4]; + + ShortToColor888(ex0, &Colours[0]); + ShortToColor888(ex1, &Colours[1]); + if (NumCols == 3) { + Colours[2].r = (Colours[0].r + Colours[1].r) / 2; + Colours[2].g = (Colours[0].g + Colours[1].g) / 2; + Colours[2].b = (Colours[0].b + Colours[1].b) / 2; + Colours[3].r = (Colours[0].r + Colours[1].r) / 2; + Colours[3].g = (Colours[0].g + Colours[1].g) / 2; + Colours[3].b = (Colours[0].b + Colours[1].b) / 2; + } + else { // NumCols == 4 + Colours[2].r = (2 * Colours[0].r + Colours[1].r + 1) / 3; + Colours[2].g = (2 * Colours[0].g + Colours[1].g + 1) / 3; + Colours[2].b = (2 * Colours[0].b + Colours[1].b + 1) / 3; + Colours[3].r = (Colours[0].r + 2 * Colours[1].r + 1) / 3; + Colours[3].g = (Colours[0].g + 2 * Colours[1].g + 1) / 3; + Colours[3].b = (Colours[0].b + 2 * Colours[1].b + 1) / 3; + } + + for (i = 0; i < 16; i++) { + if (Alpha) { // Test to see if we have 1-bit transparency + if (Alpha[i] < 128) { + Mask[i] = 3; // Transparent + if (OutCol) { + OutCol[i].r = Colours[3].r; + OutCol[i].g = Colours[3].g; + OutCol[i].b = Colours[3].b; + } + continue; + } + } + + // If no transparency, try to find which colour is the closest. + Closest = UINT_MAX; + ShortToColor888(In[i], &c); + for (j = 0; j < NumCols; j++) { + Dist = Distance(&c, &Colours[j]); + if (Dist < Closest) { + Closest = Dist; + Mask[i] = j; + if (OutCol) { + OutCol[i].r = Colours[j].r; + OutCol[i].g = Colours[j].g; + OutCol[i].b = Colours[j].b; + } + } + } + } + + for (i = 0; i < 16; i++) { + BitMask |= (Mask[i] << (i*2)); + } + + return BitMask; +} + + +void GenAlphaBitMask(ILubyte a0, ILubyte a1, ILubyte *In, ILubyte *Mask, ILubyte *Out) +{ + ILubyte Alphas[8], M[16]; + ILuint i, j, Closest, Dist; + + Alphas[0] = a0; + Alphas[1] = a1; + + // 8-alpha or 6-alpha block? + if (a0 > a1) { + // 8-alpha block: derive the other six alphas. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + Alphas[2] = (6 * Alphas[0] + 1 * Alphas[1] + 3) / 7; // bit code 010 + Alphas[3] = (5 * Alphas[0] + 2 * Alphas[1] + 3) / 7; // bit code 011 + Alphas[4] = (4 * Alphas[0] + 3 * Alphas[1] + 3) / 7; // bit code 100 + Alphas[5] = (3 * Alphas[0] + 4 * Alphas[1] + 3) / 7; // bit code 101 + Alphas[6] = (2 * Alphas[0] + 5 * Alphas[1] + 3) / 7; // bit code 110 + Alphas[7] = (1 * Alphas[0] + 6 * Alphas[1] + 3) / 7; // bit code 111 + } + else { + // 6-alpha block. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + Alphas[2] = (4 * Alphas[0] + 1 * Alphas[1] + 2) / 5; // Bit code 010 + Alphas[3] = (3 * Alphas[0] + 2 * Alphas[1] + 2) / 5; // Bit code 011 + Alphas[4] = (2 * Alphas[0] + 3 * Alphas[1] + 2) / 5; // Bit code 100 + Alphas[5] = (1 * Alphas[0] + 4 * Alphas[1] + 2) / 5; // Bit code 101 + Alphas[6] = 0x00; // Bit code 110 + Alphas[7] = 0xFF; // Bit code 111 + } + + for (i = 0; i < 16; i++) { + Closest = UINT_MAX; + for (j = 0; j < 8; j++) { + Dist = abs((ILint)In[i] - (ILint)Alphas[j]); + if (Dist < Closest) { + Closest = Dist; + M[i] = j; + } + } + } + + if (Out) { + for (i = 0; i < 16; i++) { + Out[i] = Alphas[M[i]]; + } + } + + //this was changed 20040623. There was a shift bug in here. Now the code + //produces much higher quality images. + // First three bytes. + Mask[0] = (M[0]) | (M[1] << 3) | ((M[2] & 0x03) << 6); + Mask[1] = ((M[2] & 0x04) >> 2) | (M[3] << 1) | (M[4] << 4) | ((M[5] & 0x01) << 7); + Mask[2] = ((M[5] & 0x06) >> 1) | (M[6] << 2) | (M[7] << 5); + + // Second three bytes. + Mask[3] = (M[8]) | (M[9] << 3) | ((M[10] & 0x03) << 6); + Mask[4] = ((M[10] & 0x04) >> 2) | (M[11] << 1) | (M[12] << 4) | ((M[13] & 0x01) << 7); + Mask[5] = ((M[13] & 0x06) >> 1) | (M[14] << 2) | (M[15] << 5); + + return; +} + + +ILuint RMSAlpha(ILubyte *Orig, ILubyte *Test) +{ + ILuint RMS = 0, i; + ILint d; + + for (i = 0; i < 16; i++) { + d = Orig[i] - Test[i]; + RMS += d*d; + } + + //RMS /= 16; + + return RMS; +} + + +ILuint Distance(Color888 *c1, Color888 *c2) +{ + return (c1->r - c2->r) * (c1->r - c2->r) + + (c1->g - c2->g) * (c1->g - c2->g) + + (c1->b - c2->b) * (c1->b - c2->b); +} + +#define Sum(c) ((c)->r + (c)->g + (c)->b) +#define NormSquared(c) ((c)->r * (c)->r + (c)->g * (c)->g + (c)->b * (c)->b) + +void ChooseEndpoints(ILushort *Block, ILushort *ex0, ILushort *ex1) +{ + ILuint i; + Color888 Colours[16]; + ILint Lowest=0, Highest=0; + + for (i = 0; i < 16; i++) { + ShortToColor888(Block[i], &Colours[i]); + + if (NormSquared(&Colours[i]) < NormSquared(&Colours[Lowest])) + Lowest = i; + if (NormSquared(&Colours[i]) > NormSquared(&Colours[Highest])) + Highest = i; + } + *ex0 = Block[Highest]; + *ex1 = Block[Lowest]; +} + +#undef Sum +#undef NormSquared + + +void ChooseAlphaEndpoints(ILubyte *Block, ILubyte *a0, ILubyte *a1) +{ + ILuint i, Lowest = 0xFF, Highest = 0; + + for (i = 0; i < 16; i++) { + if (Block[i] < Lowest) + Lowest = Block[i]; + if (Block[i] > Highest) + Highest = Block[i]; + } + + *a0 = Lowest; + *a1 = Highest; +} + + +void CorrectEndDXT1(ILushort *ex0, ILushort *ex1, ILboolean HasAlpha) +{ + ILushort Temp; + + if (HasAlpha) { + if (*ex0 > *ex1) { + Temp = *ex0; + *ex0 = *ex1; + *ex1 = Temp; + } + } + else { + if (*ex0 < *ex1) { + Temp = *ex0; + *ex0 = *ex1; + *ex1 = Temp; + } + } + + return; +} + + +void PreMult(ILushort *Data, ILubyte *Alpha) +{ + Color888 Colour; + ILuint i; + + for (i = 0; i < 16; i++) { + ShortToColor888(Data[i], &Colour); + Colour.r = (ILubyte)(((ILuint)Colour.r * Alpha[i]) >> 8); + Colour.g = (ILubyte)(((ILuint)Colour.g * Alpha[i]) >> 8); + Colour.b = (ILubyte)(((ILuint)Colour.b * Alpha[i]) >> 8); + + /*Colour.r = (ILubyte)(Colour.r * (Alpha[i] / 255.0)); + Colour.g = (ILubyte)(Colour.g * (Alpha[i] / 255.0)); + Colour.b = (ILubyte)(Colour.b * (Alpha[i] / 255.0));*/ + + Data[i] = Color888ToShort(&Colour); + ShortToColor888(Data[i], &Colour); + } + + return; +} + + +//! Compresses data to a DXT format using different methods. +// The data must be in unsigned byte RGBA or BGRA format. Only DXT1, DXT3 and DXT5 are supported. +ILAPI ILubyte* ILAPIENTRY ilCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DXTCFormat, ILuint *DXTCSize) +{ + ILimage *TempImage, *CurImage = iCurImage; + ILuint BuffSize; + ILubyte *Buffer; + + if ((DXTCFormat != IL_DXT1 && DXTCFormat != IL_DXT1A && DXTCFormat != IL_DXT3 && DXTCFormat != IL_DXT5) + || Data == NULL || Width == 0 || Height == 0 || Depth == 0) { + ilSetError(IL_INVALID_PARAM); + return NULL; + } + + // We want to try nVidia compression first, because it is the fastest. +#ifdef IL_USE_DXTC_NVIDIA + if (ilIsEnabled(IL_NVIDIA_COMPRESS) && Depth == 1) { // See if we need to use the nVidia Texture Tools library. + // NVTT needs data as BGRA 32-bit. + // Here's where all the compression and writing goes on. + return ilNVidiaCompressDXT(Data, Width, Height, 1, DXTCFormat, DXTCSize); + } +#endif//IL_USE_DXTC_NVIDIA + + // libsquish generates better quality output than DevIL does, so we try it next. +#ifdef IL_USE_DXTC_SQUISH + if (ilIsEnabled(IL_SQUISH_COMPRESS) && Depth == 1) { // See if we need to use the nVidia Texture Tools library. + if (DXTCFormat == IL_DXT1 || DXTCFormat == IL_DXT1A || DXTCFormat == IL_DXT3 || DXTCFormat == IL_DXT5) { + // libsquish needs data as RGBA 32-bit. + // Get compressed data here. + return ilSquishCompressDXT(Data, Width, Height, 1, DXTCFormat, DXTCSize); + } + } +#endif//IL_USE_DXTC_SQUISH + + TempImage = (ILimage*)ialloc(sizeof(ILimage)); + memset(TempImage, 0, sizeof(ILimage)); + TempImage->Width = Width; + TempImage->Height = Height; + TempImage->Depth = Depth; + TempImage->Bpp = 4; // RGBA or BGRA + TempImage->Format = IL_BGRA; + TempImage->Bpc = 1; // Unsigned bytes only + TempImage->Type = IL_UNSIGNED_BYTE; + TempImage->SizeOfPlane = TempImage->Bps * Height; + TempImage->SizeOfData = TempImage->SizeOfPlane * Depth; + TempImage->Origin = IL_ORIGIN_UPPER_LEFT; + TempImage->Data = Data; + + BuffSize = ilGetDXTCData(NULL, 0, DXTCFormat); + if (BuffSize == 0) + return NULL; + Buffer = (ILubyte*)ialloc(BuffSize); + if (Buffer == NULL) + return NULL; + + if (ilGetDXTCData(Buffer, BuffSize, DXTCFormat) != BuffSize) { + ifree(Buffer); + return NULL; + } + *DXTCSize = BuffSize; + + // Restore backup of iCurImage. + iCurImage = CurImage; + TempImage->Data = NULL; + ilCloseImage(TempImage); + + return Buffer; +} diff --git a/DevIL/src-IL/src/il_dds.c b/DevIL/src-IL/src/il_dds.c deleted file mode 100644 index 02978c7b..00000000 --- a/DevIL/src-IL/src/il_dds.c +++ /dev/null @@ -1,2523 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/28/2009 -// -// Filename: src-IL/src/il_dds.c -// -// Description: Reads from a DirectDraw Surface (.dds) file. -// -//----------------------------------------------------------------------------- - - -// -// -// Note: Almost all this code is from nVidia's DDS-loading example at -// http://www.nvidia.com/view.asp?IO=dxtc_decompression_code -// and from the specs at -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/hh/dx8_c/graphics_using_0j03.asp -// and -// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/ProgrammersGuide/Appendix/DDSFileFormat/ovwDDSFileFormat.asp -// However, some not really valid .dds files are also read, for example -// Volume Textures without the COMPLEX bit set, so the specs aren't taken -// too strictly while reading. - - -#include "il_internal.h" -#ifndef IL_NO_DDS -#include "il_dds.h" - - -// Global variables -static DDSHEAD Head; // Image header -static ILubyte *CompData = NULL; // Compressed data -static ILuint CompSize; // Compressed size -//static ILuint CompFormat; // Compressed format -static ILimage *Image; -static ILint Width, Height, Depth; -static ILboolean Has16BitComponents; - -ILuint CubemapDirections[CUBEMAP_SIDES] = { - DDS_CUBEMAP_POSITIVEX, - DDS_CUBEMAP_NEGATIVEX, - DDS_CUBEMAP_POSITIVEY, - DDS_CUBEMAP_NEGATIVEY, - DDS_CUBEMAP_POSITIVEZ, - DDS_CUBEMAP_NEGATIVEZ -}; - - -//! Checks if the file specified in FileName is a valid .dds file. -ILboolean ilIsValidDds(ILconst_string FileName) -{ - ILHANDLE DdsFile; - ILboolean bDds = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("dds"))) { - ilSetError(IL_INVALID_EXTENSION); - return bDds; - } - - DdsFile = iopenr(FileName); - if (DdsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDds; - } - - bDds = ilIsValidDdsF(DdsFile); - icloser(DdsFile); - - return bDds; -} - - -//! Checks if the ILHANDLE contains a valid .dds file at the current position. -ILboolean ilIsValidDdsF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidDds(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .dds lump. -ILboolean ilIsValidDdsL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidDds(); -} - - -// Internal function used to get the .dds header from the current file. -ILboolean iGetDdsHead(DDSHEAD *Header) -{ - ILint i; - - iread(&Header->Signature, 1, 4); - Header->Size1 = GetLittleUInt(); - Header->Flags1 = GetLittleUInt(); - Header->Height = GetLittleUInt(); - Header->Width = GetLittleUInt(); - Header->LinearSize = GetLittleUInt(); - Header->Depth = GetLittleUInt(); - Header->MipMapCount = GetLittleUInt(); - Header->AlphaBitDepth = GetLittleUInt(); - - for (i = 0; i < 10; ++i) - Header->NotUsed[i] = GetLittleUInt(); - - Header->Size2 = GetLittleUInt(); - Header->Flags2 = GetLittleUInt(); - Header->FourCC = GetLittleUInt(); - Header->RGBBitCount = GetLittleUInt(); - Header->RBitMask = GetLittleUInt(); - Header->GBitMask = GetLittleUInt(); - Header->BBitMask = GetLittleUInt(); - Header->RGBAlphaBitMask = GetLittleUInt(); - Header->ddsCaps1 = GetLittleUInt(); - Header->ddsCaps2 = GetLittleUInt(); - Header->ddsCaps3 = GetLittleUInt(); - Header->ddsCaps4 = GetLittleUInt(); - Header->TextureStage = GetLittleUInt(); - - if (Head.Depth == 0) - Head.Depth = 1; - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidDds() -{ - ILboolean IsValid; - DDSHEAD Head; - - iGetDdsHead(&Head); - iseek(-(ILint)sizeof(DDSHEAD), IL_SEEK_CUR); // Go ahead and restore to previous state - - IsValid = iCheckDds(&Head); - - return IsValid; -} - - -// Internal function used to check if the HEADER is a valid .dds header. -ILboolean iCheckDds(DDSHEAD *Head) -{ - if (strncmp((const char*)Head->Signature, "DDS ", 4)) - return IL_FALSE; - //note that if Size1 is "DDS " this is not a valid dds file according - //to the file spec. Some broken tool out there seems to produce files - //with this value in the size field, so we support reading them... - if (Head->Size1 != 124 && Head->Size1 != IL_MAKEFOURCC('D', 'D', 'S', ' ')) - return IL_FALSE; - if (Head->Size2 != 32) - return IL_FALSE; - if (Head->Width == 0 || Head->Height == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Reads a .dds file -ILboolean ilLoadDds(ILconst_string FileName) -{ - ILHANDLE DdsFile; - ILboolean bDds = IL_FALSE; - - DdsFile = iopenr(FileName); - if (DdsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDds; - } - - bDds = ilLoadDdsF(DdsFile); - icloser(DdsFile); - - return bDds; -} - - -//! Reads an already-opened .dds file -ILboolean ilLoadDdsF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDdsInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .dds -ILboolean ilLoadDdsL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadDdsInternal(); -} - - -void Check16BitComponents(DDSHEAD *Header) -{ - if (Header->RGBBitCount != 32) - Has16BitComponents = IL_FALSE; - // a2b10g10r10 format - if (Header->RBitMask == 0x3FF00000 && Header->GBitMask == 0x000FFC00 && Header->BBitMask == 0x000003FF - && Header->RGBAlphaBitMask == 0xC0000000) - Has16BitComponents = IL_TRUE; - // a2r10g10b10 format - else if (Header->RBitMask == 0x000003FF && Header->GBitMask == 0x000FFC00 && Header->BBitMask == 0x3FF00000 - && Header->RGBAlphaBitMask == 0xC0000000) - Has16BitComponents = IL_TRUE; - else - Has16BitComponents = IL_FALSE; - return; -} - - -ILubyte iCompFormatToBpp(ILenum Format) -{ - //non-compressed (= non-FOURCC) codes - if (Format == PF_LUMINANCE || Format == PF_LUMINANCE_ALPHA || Format == PF_ARGB) - return Head.RGBBitCount/8; - - //fourcc formats - else if (Format == PF_RGB || Format == PF_3DC || Format == PF_RXGB) - return 3; - else if (Format == PF_ATI1N) - return 1; - //else if (Format == PF_R16F) - // return 2; - else if (Format == PF_A16B16G16R16 || Format == PF_A16B16G16R16F - || Format == PF_G32R32F) - return 8; - else if (Format == PF_A32B32G32R32F) - return 16; - else //if (Format == PF_G16R16F || Format == PF_R32F || dxt) - return 4; -} - - -ILubyte iCompFormatToBpc(ILenum Format) -{ - if (Has16BitComponents) - return 2; - if (Format == PF_R16F || Format == PF_G16R16F || Format == PF_A16B16G16R16F) - //DevIL has no internal half type, so these formats are converted to 32 bits - return 4; - else if (Format == PF_R32F || Format == PF_R16F || Format == PF_G32R32F || Format == PF_A32B32G32R32F) - return 4; - else if(Format == PF_A16B16G16R16) - return 2; - else - return 1; -} - - -ILubyte iCompFormatToChannelCount(ILenum Format) -{ - if (Format == PF_RGB || Format == PF_3DC || Format == PF_RXGB) - return 3; - else if (Format == PF_LUMINANCE || /*Format == PF_R16F || Format == PF_R32F ||*/ Format == PF_ATI1N) - return 1; - else if (Format == PF_LUMINANCE_ALPHA /*|| Format == PF_G16R16F || Format == PF_G32R32F*/) - return 2; - else if (Format == PF_G16R16F || Format == PF_G32R32F || Format == PF_R32F || Format == PF_R16F) - return 3; - else //if(Format == PF_ARGB || dxt) - return 4; -} - - -ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) -{ - ILuint i; - ILubyte Bpp, Channels, Bpc; - ILimage *startImage; - - CompData = NULL; - - Bpp = iCompFormatToBpp(CompFormat); - Channels = iCompFormatToChannelCount(CompFormat); - Bpc = iCompFormatToBpc(CompFormat); - if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //@TODO: This is a HACK. - Bpc = 2; Bpp = 2; - } - - startImage = Image; - // Run through cube map possibilities - for (i = 0; i < CUBEMAP_SIDES; i++) { - // Reset each time - Width = Head.Width; - Height = Head.Height; - Depth = Head.Depth; - if (Head.ddsCaps2 & CubemapDirections[i]) { - if (i != 0) { - Image->Faces = ilNewImage(Width, Height, Depth, Channels, Bpc); - if (Image->Faces == NULL) - return IL_FALSE; - - Image = Image->Faces; - - if (CompFormat == PF_R16F - || CompFormat == PF_G16R16F - || CompFormat == PF_A16B16G16R16F - || CompFormat == PF_R32F - || CompFormat == PF_G32R32F - || CompFormat == PF_A32B32G32R32F) { - // DevIL's format autodetection doesn't work for - // float images...correct this. - Image->Type = IL_FLOAT; - Image->Bpp = Channels; - } - - ilBindImage(ilGetCurName()); // Set to parent image first. - //ilActiveImage(i); //@TODO: now Image == iCurImage...globals SUCK, fix this!!! - ilActiveFace(i); - } - - if (!ReadData()) - return IL_FALSE; - - if (!AllocImage(CompFormat)) { - if (CompData) { - ifree(CompData); - CompData = NULL; - } - return IL_FALSE; - } - - Image->CubeFlags = CubemapDirections[i]; - - if (!DdsDecompress(CompFormat)) { - if (CompData) { - ifree(CompData); - CompData = NULL; - } - return IL_FALSE; - } - - if (!ReadMipmaps(CompFormat)) { - if (CompData) { - ifree(CompData); - CompData = NULL; - } - return IL_FALSE; - } - } - } - - if (CompData) { - ifree(CompData); - CompData = NULL; - } - - ilBindImage(ilGetCurName()); // Set to parent image first. - return ilFixImage(); -} - - -ILboolean iLoadDdsInternal() -{ - ILuint BlockSize = 0; - ILuint CompFormat; - - CompData = NULL; - Image = NULL; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetDdsHead(&Head)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - if (!iCheckDds(&Head)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - BlockSize = DecodePixelFormat(&CompFormat); - if (CompFormat == PF_UNKNOWN) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - Check16BitComponents(&Head); - - // Microsoft bug, they're not following their own documentation. - if (!(Head.Flags1 & (DDS_LINEARSIZE | DDS_PITCH)) - || Head.LinearSize == 0) { - Head.Flags1 |= DDS_LINEARSIZE; - Head.LinearSize = BlockSize; - } - - Image = iCurImage; - if (Head.ddsCaps1 & DDS_COMPLEX) { - if (Head.ddsCaps2 & DDS_CUBEMAP) { - if (!iLoadDdsCubemapInternal(CompFormat)) - return IL_FALSE; - return IL_TRUE; - } - } - - Width = Head.Width; - Height = Head.Height; - Depth = Head.Depth; - AdjustVolumeTexture(&Head, CompFormat); - - if (!ReadData()) - return IL_FALSE; - if (!AllocImage(CompFormat)) { - if (CompData) { - ifree(CompData); - CompData = NULL; - } - return IL_FALSE; - } - if (!DdsDecompress(CompFormat)) { - if (CompData) { - ifree(CompData); - CompData = NULL; - } - return IL_FALSE; - } - - if (!ReadMipmaps(CompFormat)) { - if (CompData) { - ifree(CompData); - CompData = NULL; - } - return IL_FALSE; - } - - if (CompData) { - ifree(CompData); - CompData = NULL; - } - - ilBindImage(ilGetCurName()); // Set to parent image first. - return ilFixImage(); -} - - -ILuint DecodePixelFormat(ILuint *CompFormat) -{ - ILuint BlockSize; - - if (Head.Flags2 & DDS_FOURCC) { - BlockSize = ((Head.Width + 3)/4) * ((Head.Height + 3)/4) * Head.Depth; - switch (Head.FourCC) - { - case IL_MAKEFOURCC('D','X','T','1'): - *CompFormat = PF_DXT1; - BlockSize *= 8; - break; - - case IL_MAKEFOURCC('D','X','T','2'): - *CompFormat = PF_DXT2; - BlockSize *= 16; - break; - - case IL_MAKEFOURCC('D','X','T','3'): - *CompFormat = PF_DXT3; - BlockSize *= 16; - break; - - case IL_MAKEFOURCC('D','X','T','4'): - *CompFormat = PF_DXT4; - BlockSize *= 16; - break; - - case IL_MAKEFOURCC('D','X','T','5'): - *CompFormat = PF_DXT5; - BlockSize *= 16; - break; - - case IL_MAKEFOURCC('A', 'T', 'I', '1'): - *CompFormat = PF_ATI1N; - BlockSize *= 8; - break; - - case IL_MAKEFOURCC('A', 'T', 'I', '2'): - *CompFormat = PF_3DC; - BlockSize *= 16; - break; - - case IL_MAKEFOURCC('R', 'X', 'G', 'B'): - *CompFormat = PF_RXGB; - BlockSize *= 16; - break; - - case IL_MAKEFOURCC('$', '\0', '\0', '\0'): - *CompFormat = PF_A16B16G16R16; - BlockSize = Head.Width * Head.Height * Head.Depth * 8; - break; - - case IL_MAKEFOURCC('o', '\0', '\0', '\0'): - *CompFormat = PF_R16F; - BlockSize = Head.Width * Head.Height * Head.Depth * 2; - break; - - case IL_MAKEFOURCC('p', '\0', '\0', '\0'): - *CompFormat = PF_G16R16F; - BlockSize = Head.Width * Head.Height * Head.Depth * 4; - break; - - case IL_MAKEFOURCC('q', '\0', '\0', '\0'): - *CompFormat = PF_A16B16G16R16F; - BlockSize = Head.Width * Head.Height * Head.Depth * 8; - break; - - case IL_MAKEFOURCC('r', '\0', '\0', '\0'): - *CompFormat = PF_R32F; - BlockSize = Head.Width * Head.Height * Head.Depth * 4; - break; - - case IL_MAKEFOURCC('s', '\0', '\0', '\0'): - *CompFormat = PF_G32R32F; - BlockSize = Head.Width * Head.Height * Head.Depth * 8; - break; - - case IL_MAKEFOURCC('t', '\0', '\0', '\0'): - *CompFormat = PF_A32B32G32R32F; - BlockSize = Head.Width * Head.Height * Head.Depth * 16; - break; - - default: - *CompFormat = PF_UNKNOWN; - BlockSize *= 16; - break; - } - } else { - // This dds texture isn't compressed so write out ARGB or luminance format - if (Head.Flags2 & DDS_LUMINANCE) { - if (Head.Flags2 & DDS_ALPHAPIXELS) { - *CompFormat = PF_LUMINANCE_ALPHA; - } else { - *CompFormat = PF_LUMINANCE; - } - } - else { - if (Head.Flags2 & DDS_ALPHAPIXELS) { - *CompFormat = PF_ARGB; - } else { - *CompFormat = PF_RGB; - } - } - BlockSize = (Head.Width * Head.Height * Head.Depth * (Head.RGBBitCount >> 3)); - } - - return BlockSize; -} - - -// The few volume textures that I have don't have consistent LinearSize -// entries, even though the DDS_LINEARSIZE flag is set. -void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat) -{ - if (Head->Depth <= 1) - return; - - // All volume textures I've seem so far didn't have the DDS_COMPLEX flag set, - // even though this is normally required. But because noone does set it, - // also read images without it (TODO: check file size for 3d texture?) - if (/*!(Head->ddsCaps1 & DDS_COMPLEX) ||*/ !(Head->ddsCaps2 & DDS_VOLUME)) { - Head->Depth = 1; - Depth = 1; - } - - switch (CompFormat) - { - case PF_ARGB: - case PF_RGB: - case PF_LUMINANCE: - case PF_LUMINANCE_ALPHA: - //don't use the iCompFormatToBpp() function because this way - //argb images with only 8 bits (eg. a1r2g3b2) work as well - Head->LinearSize = IL_MAX(1,Head->Width) * IL_MAX(1,Head->Height) * - (Head->RGBBitCount / 8); - break; - - case PF_DXT1: - - case PF_ATI1N: - Head->LinearSize = ((Head->Width+3)/4) * ((Head->Height+3)/4) * 8; - break; - - case PF_DXT2: - case PF_DXT3: - case PF_DXT4: - case PF_DXT5: - case PF_3DC: - case PF_RXGB: - Head->LinearSize = ((Head->Width+3)/4) * ((Head->Height+3)/4) * 16; - break; - - case PF_A16B16G16R16: - case PF_R16F: - case PF_G16R16F: - case PF_A16B16G16R16F: - case PF_R32F: - case PF_G32R32F: - case PF_A32B32G32R32F: - Head->LinearSize = IL_MAX(1,Head->Width) * IL_MAX(1,Head->Height) * - iCompFormatToBpp(CompFormat); - break; - } - - Head->Flags1 |= DDS_LINEARSIZE; - Head->LinearSize *= Head->Depth; - - return; -} - - -// Reads the compressed data -ILboolean ReadData() -{ - ILuint Bps; - ILint y, z; - ILubyte *Temp; - - if (CompData) { - ifree(CompData); - CompData = NULL; - } - - if (Head.Flags1 & DDS_LINEARSIZE) { - //Head.LinearSize = Head.LinearSize * Depth; - - CompData = (ILubyte*)ialloc(Head.LinearSize); - if (CompData == NULL) { - return IL_FALSE; - } - - if (iread(CompData, 1, Head.LinearSize) != (ILuint)Head.LinearSize) { - ifree(CompData); - CompData = NULL; - return IL_FALSE; - } - } - else { - Bps = Width * Head.RGBBitCount / 8; - CompSize = Bps * Height * Depth; - - CompData = (ILubyte*)ialloc(CompSize); - if (CompData == NULL) { - return IL_FALSE; - } - - Temp = CompData; - for (z = 0; z < Depth; z++) { - for (y = 0; y < Height; y++) { - if (iread(Temp, 1, Bps) != Bps) { - ifree(CompData); - CompData = NULL; - return IL_FALSE; - } - Temp += Bps; - } - } - } - - return IL_TRUE; -} - - -ILboolean AllocImage(ILuint CompFormat) -{ - ILubyte channels = 4; - ILenum format = IL_RGBA; - - switch (CompFormat) - { - case PF_RGB: - if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - case PF_ARGB: - if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - - case PF_LUMINANCE: - if (Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK - if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) - return IL_FALSE; - } - else - if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - - case PF_LUMINANCE_ALPHA: - if (!ilTexImage(Width, Height, Depth, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - - case PF_ATI1N: - //right now there's no OpenGL api to use the compressed 3dc data, so - //throw it away (I don't know how DirectX works, though)? - if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - - case PF_3DC: - //right now there's no OpenGL api to use the compressed 3dc data, so - //throw it away (I don't know how DirectX works, though)? - if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - break; - - case PF_A16B16G16R16: - if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), - ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_UNSIGNED_SHORT, NULL)) - return IL_FALSE; - break; - - case PF_R16F: - case PF_G16R16F: - case PF_A16B16G16R16F: - case PF_R32F: - case PF_G32R32F: - case PF_A32B32G32R32F: - if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), - ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_FLOAT, NULL)) - return IL_FALSE; - break; - - default: - if (CompFormat == PF_RXGB) { - channels = 3; //normal map - format = IL_RGB; - } - - if (!ilTexImage(Width, Height, Depth, channels, format, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && CompData) { - iCurImage->DxtcData = (ILubyte*)ialloc(Head.LinearSize); - if (iCurImage->DxtcData == NULL) - return IL_FALSE; - iCurImage->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1; - iCurImage->DxtcSize = Head.LinearSize; - memcpy(iCurImage->DxtcData, CompData, iCurImage->DxtcSize); - } - break; - } - - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - return IL_TRUE; -} - - -/* - * Assumes that the global variable CompFormat stores the format of the - * global pointer CompData (that's the pointer to the compressed data). - * Decompresses this data into Image->Data, returns if it was successful. - * It also uses the globals Width and Height. - * - * Assumes that iCurImage has valid Width, Height, Depth, Data, SizeOfData, - * Bpp, Bpc, Bps, SizeOfPlane, Format and Type fields. It is more or - * less assumed that the image has u8 rgba data (perhaps not for float - * images...) - * - * - * @TODO: don't use globals, clean this function (and this file) up - */ -ILboolean DdsDecompress(ILuint CompFormat) -{ - switch (CompFormat) - { - case PF_ARGB: - case PF_RGB: - case PF_LUMINANCE: - case PF_LUMINANCE_ALPHA: - return DecompressARGB(CompFormat); - - case PF_DXT1: - return DecompressDXT1(Image, CompData); - - case PF_DXT2: - return DecompressDXT2(Image, CompData); - - case PF_DXT3: - return DecompressDXT3(Image, CompData); - - case PF_DXT4: - return DecompressDXT4(Image, CompData); - - case PF_DXT5: - return DecompressDXT5(Image, CompData); - - case PF_ATI1N: - return DecompressAti1n(); - - case PF_3DC: - return Decompress3Dc(); - - case PF_RXGB: - return DecompressRXGB(); - - case PF_A16B16G16R16: - memcpy(Image->Data, CompData, Image->SizeOfData); - return IL_TRUE; - - case PF_R16F: - case PF_G16R16F: - case PF_A16B16G16R16F: - case PF_R32F: - case PF_G32R32F: - case PF_A32B32G32R32F: - return DecompressFloat(CompFormat); - - case PF_UNKNOWN: - return IL_FALSE; - } - - return IL_FALSE; -} - - -ILboolean ReadMipmaps(ILuint CompFormat) -{ - ILuint i, CompFactor=0; - ILubyte Bpp, Channels, Bpc; - ILimage *StartImage, *TempImage; - ILuint LastLinear; - ILuint minW, minH; - - ILboolean isCompressed = IL_FALSE; - - Bpp = iCompFormatToBpp(CompFormat); - Channels = iCompFormatToChannelCount(CompFormat); - Bpc = iCompFormatToBpc(CompFormat); - if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK - Bpc = 2; Bpp = 2; - } - - //This doesn't work for images which first mipmap (= the image - //itself) has width or height < 4 - //if (Head.Flags1 & DDS_LINEARSIZE) { - // CompFactor = (Width * Height * Depth * Bpp) / Head.LinearSize; - //} - switch (CompFormat) - { - case PF_DXT1: - // This is officially 6, we have 8 here because DXT1 may contain alpha. - CompFactor = 8; - break; - case PF_DXT2: - case PF_DXT3: - case PF_DXT4: - case PF_DXT5: - CompFactor = 4; - break; - case PF_RXGB: - case PF_3DC: - // This is officially 4 for 3dc, but that's bullshit :) There's no - // alpha data in 3dc images. - CompFactor = 3; - break; - - case PF_ATI1N: - CompFactor = 2; - break; - default: - CompFactor = 1; - } - - StartImage = Image; - - if (!(Head.Flags1 & DDS_MIPMAPCOUNT) || Head.MipMapCount == 0) { - //some .dds-files have their mipmap flag set, - //but a mipmapcount of 0. Because mipMapCount is an uint, 0 - 1 gives - //overflow - don't let this happen: - Head.MipMapCount = 1; - } - - LastLinear = Head.LinearSize; - for (i = 0; i < Head.MipMapCount - 1; i++) { - Depth = Depth / 2; - Width = Width / 2; - Height = Height / 2; - - if (Depth == 0) - Depth = 1; - if (Width == 0) - Width = 1; - if (Height == 0) - Height = 1; - - Image->Mipmaps = ilNewImage(Width, Height, Depth, Channels, Bpc); - if (Image->Mipmaps == NULL) - goto mip_fail; - Image = Image->Mipmaps; - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - if (Head.Flags1 & DDS_LINEARSIZE) { - if (CompFormat == PF_R16F - || CompFormat == PF_G16R16F - || CompFormat == PF_A16B16G16R16F - || CompFormat == PF_R32F - || CompFormat == PF_G32R32F - || CompFormat == PF_A32B32G32R32F) { - Head.LinearSize = Width * Height * Depth * Bpp; - - //DevIL's format autodetection doesn't work for - //float images...correct this - Image->Type = IL_FLOAT; - Image->Bpp = Channels; - } - else if (CompFormat == PF_A16B16G16R16) - Head.LinearSize = Width * Height * Depth * Bpp; - else if (CompFormat != PF_RGB && CompFormat != PF_ARGB - && CompFormat != PF_LUMINANCE - && CompFormat != PF_LUMINANCE_ALPHA) { - - //compressed format - minW = (((Width+3)/4))*4; - minH = (((Height+3)/4))*4; - Head.LinearSize = (minW * minH * Depth * Bpp) / CompFactor; - - isCompressed = IL_TRUE; - } - else { - //don't use Bpp to support argb images with less than 32 bits - Head.LinearSize = Width * Height * Depth * (Head.RGBBitCount >> 3); - } - } - else { - Head.LinearSize >>= 1; - } - - if (!ReadData()) - goto mip_fail; - - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && isCompressed == IL_TRUE && CompData) { - Image->DxtcData = (ILubyte*)ialloc(Head.LinearSize); - if (Image->DxtcData == NULL) - return IL_FALSE; - Image->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1; - Image->DxtcSize = Head.LinearSize; - memcpy(Image->DxtcData, CompData, Image->DxtcSize); - } - - if (!DdsDecompress(CompFormat)) - goto mip_fail; - } - - Head.LinearSize = LastLinear; - Image = StartImage; - - return IL_TRUE; - -mip_fail: - Image = StartImage; - StartImage = StartImage->Mipmaps; - while (StartImage) { - TempImage = StartImage; - StartImage = StartImage->Mipmaps; - ifree(TempImage); - } - - Image->Mipmaps = NULL; - return IL_FALSE; -} - - -void DxtcReadColors(const ILubyte* Data, Color8888* Out) -{ - ILubyte r0, g0, b0, r1, g1, b1; - - b0 = Data[0] & 0x1F; - g0 = ((Data[0] & 0xE0) >> 5) | ((Data[1] & 0x7) << 3); - r0 = (Data[1] & 0xF8) >> 3; - - b1 = Data[2] & 0x1F; - g1 = ((Data[2] & 0xE0) >> 5) | ((Data[3] & 0x7) << 3); - r1 = (Data[3] & 0xF8) >> 3; - - Out[0].r = r0 << 3 | r0 >> 2; - Out[0].g = g0 << 2 | g0 >> 3; - Out[0].b = b0 << 3 | b0 >> 2; - - Out[1].r = r1 << 3 | r1 >> 2; - Out[1].g = g1 << 2 | g1 >> 3; - Out[1].b = b1 << 3 | b1 >> 2; -} - -//@TODO: Probably not safe on Big Endian. -void DxtcReadColor(ILushort Data, Color8888* Out) -{ - ILubyte r, g, b; - - b = Data & 0x1f; - g = (Data & 0x7E0) >> 5; - r = (Data & 0xF800) >> 11; - - Out->r = r << 3 | r >> 2; - Out->g = g << 2 | g >> 3; - Out->b = b << 3 | r >> 2; -} - -ILboolean DecompressDXT1(ILimage *lImage, ILubyte *lCompData) -{ - ILuint x, y, z, i, j, k, Select; - ILubyte *Temp; - Color8888 colours[4], *col; - ILushort color_0, color_1; - ILuint bitmask, Offset; - - if (!lCompData) - return IL_FALSE; - - Temp = lCompData; - colours[0].a = 0xFF; - colours[1].a = 0xFF; - colours[2].a = 0xFF; - //colours[3].a = 0xFF; - for (z = 0; z < lImage->Depth; z++) { - for (y = 0; y < lImage->Height; y += 4) { - for (x = 0; x < lImage->Width; x += 4) { - color_0 = *((ILushort*)Temp); - UShort(&color_0); - color_1 = *((ILushort*)(Temp + 2)); - UShort(&color_1); - DxtcReadColor(color_0, colours); - DxtcReadColor(color_1, colours + 1); - bitmask = ((ILuint*)Temp)[1]; - UInt(&bitmask); - Temp += 8; - - if (color_0 > color_1) { - // Four-color block: derive the other two colors. - // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; - colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; - colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; - //colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - colours[3].a = 0xFF; - } - else { - // Three-color block: derive the other color. - // 00 = color_0, 01 = color_1, 10 = color_2, - // 11 = transparent. - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (colours[0].b + colours[1].b) / 2; - colours[2].g = (colours[0].g + colours[1].g) / 2; - colours[2].r = (colours[0].r + colours[1].r) / 2; - //colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - colours[3].a = 0x00; - } - - for (j = 0, k = 0; j < 4; j++) { - for (i = 0; i < 4; i++, k++) { - Select = (bitmask & (0x03 << k*2)) >> k*2; - col = &colours[Select]; - - if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { - Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp; - lImage->Data[Offset + 0] = col->r; - lImage->Data[Offset + 1] = col->g; - lImage->Data[Offset + 2] = col->b; - lImage->Data[Offset + 3] = col->a; - } - } - } - } - } - } - - return IL_TRUE; -} - - -ILboolean DecompressDXT2(ILimage *lImage, ILubyte *lCompData) -{ - // Can do color & alpha same as dxt3, but color is pre-multiplied - // so the result will be wrong unless corrected. - if (!DecompressDXT3(Image, CompData)) - return IL_FALSE; - CorrectPreMult(); - - return IL_TRUE; -} - - -ILboolean DecompressDXT3(ILimage *lImage, ILubyte *lCompData) -{ - ILuint x, y, z, i, j, k, Select; - ILubyte *Temp; - //Color565 *color_0, *color_1; - Color8888 colours[4], *col; - ILuint bitmask, Offset; - ILushort word; - ILubyte *alpha; - - if (!lCompData) - return IL_FALSE; - - Temp = lCompData; - for (z = 0; z < lImage->Depth; z++) { - for (y = 0; y < lImage->Height; y += 4) { - for (x = 0; x < lImage->Width; x += 4) { - alpha = Temp; - Temp += 8; - DxtcReadColors(Temp, colours); - bitmask = ((ILuint*)Temp)[1]; - UInt(&bitmask); - Temp += 8; - - // Four-color block: derive the other two colors. - // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; - colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; - colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; - //colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - //colours[3].a = 0xFF; - - k = 0; - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++, k++) { - Select = (bitmask & (0x03 << k*2)) >> k*2; - col = &colours[Select]; - - if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { - Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp; - lImage->Data[Offset + 0] = col->r; - lImage->Data[Offset + 1] = col->g; - lImage->Data[Offset + 2] = col->b; - } - } - } - - for (j = 0; j < 4; j++) { - word = alpha[2*j] + 256*alpha[2*j+1]; - for (i = 0; i < 4; i++) { - if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { - Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp + 3; - lImage->Data[Offset] = word & 0x0F; - lImage->Data[Offset] = lImage->Data[Offset] | (lImage->Data[Offset] << 4); - } - word >>= 4; - } - } - - } - } - } - - return IL_TRUE; -} - - -ILboolean DecompressDXT4(ILimage *lImage, ILubyte *lCompData) -{ - // Can do color & alpha same as dxt5, but color is pre-multiplied - // so the result will be wrong unless corrected. - if (!DecompressDXT5(Image, CompData)) - return IL_FALSE; - CorrectPreMult(); - - return IL_FALSE; -} - - -ILboolean DecompressDXT5(ILimage *lImage, ILubyte *lCompData) -{ - ILuint x, y, z, i, j, k, Select; - ILubyte *Temp; //, r0, g0, b0, r1, g1, b1; - Color8888 colours[4], *col; - ILuint bitmask, Offset; - ILubyte alphas[8], *alphamask; - ILuint bits; - - if (!lCompData) - return IL_FALSE; - - Temp = lCompData; - for (z = 0; z < lImage->Depth; z++) { - for (y = 0; y < lImage->Height; y += 4) { - for (x = 0; x < lImage->Width; x += 4) { - if (y >= lImage->Height || x >= lImage->Width) - break; - alphas[0] = Temp[0]; - alphas[1] = Temp[1]; - alphamask = Temp + 2; - Temp += 8; - - DxtcReadColors(Temp, colours); - bitmask = ((ILuint*)Temp)[1]; - UInt(&bitmask); - Temp += 8; - - // Four-color block: derive the other two colors. - // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; - colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; - colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; - //colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - //colours[3].a = 0xFF; - - k = 0; - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++, k++) { - - Select = (bitmask & (0x03 << k*2)) >> k*2; - col = &colours[Select]; - - // only put pixels out < width or height - if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { - Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp; - lImage->Data[Offset + 0] = col->r; - lImage->Data[Offset + 1] = col->g; - lImage->Data[Offset + 2] = col->b; - } - } - } - - // 8-alpha or 6-alpha block? - if (alphas[0] > alphas[1]) { - // 8-alpha block: derive the other six alphas. - // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. - alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7; // bit code 010 - alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7; // bit code 011 - alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7; // bit code 100 - alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7; // bit code 101 - alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7; // bit code 110 - alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7; // bit code 111 - } - else { - // 6-alpha block. - // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. - alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5; // Bit code 010 - alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5; // Bit code 011 - alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5; // Bit code 100 - alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5; // Bit code 101 - alphas[6] = 0x00; // Bit code 110 - alphas[7] = 0xFF; // Bit code 111 - } - - // Note: Have to separate the next two loops, - // it operates on a 6-byte system. - - // First three bytes - //bits = *((ILint*)alphamask); - bits = (alphamask[0]) | (alphamask[1] << 8) | (alphamask[2] << 16); - for (j = 0; j < 2; j++) { - for (i = 0; i < 4; i++) { - // only put pixels out < width or height - if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { - Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp + 3; - lImage->Data[Offset] = alphas[bits & 0x07]; - } - bits >>= 3; - } - } - - // Last three bytes - //bits = *((ILint*)&alphamask[3]); - bits = (alphamask[3]) | (alphamask[4] << 8) | (alphamask[5] << 16); - for (j = 2; j < 4; j++) { - for (i = 0; i < 4; i++) { - // only put pixels out < width or height - if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { - Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp + 3; - lImage->Data[Offset] = alphas[bits & 0x07]; - } - bits >>= 3; - } - } - } - } - } - - return IL_TRUE; -} - - -ILboolean Decompress3Dc() -{ - int x, y, z, i, j, k, t1, t2; - ILubyte *Temp, *Temp2; - ILubyte XColours[8], YColours[8]; - ILuint bitmask, bitmask2, Offset, CurrOffset; - - if (!CompData) - return IL_FALSE; - - Temp = CompData; - Offset = 0; - for (z = 0; z < Depth; z++) { - for (y = 0; y < Height; y += 4) { - for (x = 0; x < Width; x += 4) { - Temp2 = Temp + 8; - - //Read Y palette - t1 = YColours[0] = Temp[0]; - t2 = YColours[1] = Temp[1]; - Temp += 2; - if (t1 > t2) - for (i = 2; i < 8; ++i) - YColours[i] = t1 + ((t2 - t1)*(i - 1))/7; - else { - for (i = 2; i < 6; ++i) - YColours[i] = t1 + ((t2 - t1)*(i - 1))/5; - YColours[6] = 0; - YColours[7] = 255; - } - - // Read X palette - t1 = XColours[0] = Temp2[0]; - t2 = XColours[1] = Temp2[1]; - Temp2 += 2; - if (t1 > t2) - for (i = 2; i < 8; ++i) - XColours[i] = t1 + ((t2 - t1)*(i - 1))/7; - else { - for (i = 2; i < 6; ++i) - XColours[i] = t1 + ((t2 - t1)*(i - 1))/5; - XColours[6] = 0; - XColours[7] = 255; - } - - //decompress pixel data - CurrOffset = Offset; - for (k = 0; k < 4; k += 2) { - // First three bytes - bitmask = ((ILuint)(Temp[0]) << 0) | ((ILuint)(Temp[1]) << 8) | ((ILuint)(Temp[2]) << 16); - bitmask2 = ((ILuint)(Temp2[0]) << 0) | ((ILuint)(Temp2[1]) << 8) | ((ILuint)(Temp2[2]) << 16); - for (j = 0; j < 2; j++) { - // only put pixels out < height - if ((y + k + j) < Height) { - for (i = 0; i < 4; i++) { - // only put pixels out < width - if (((x + i) < Width)) { - ILint t, tx, ty; - - t1 = CurrOffset + (x + i)*3; - Image->Data[t1 + 1] = ty = YColours[bitmask & 0x07]; - Image->Data[t1 + 0] = tx = XColours[bitmask2 & 0x07]; - - //calculate b (z) component ((r/255)^2 + (g/255)^2 + (b/255)^2 = 1 - t = 127*128 - (tx - 127)*(tx - 128) - (ty - 127)*(ty - 128); - if (t > 0) - Image->Data[t1 + 2] = (ILubyte)(iSqrt(t) + 128); - else - Image->Data[t1 + 2] = 0x7F; - } - bitmask >>= 3; - bitmask2 >>= 3; - } - CurrOffset += Image->Bps; - } - } - Temp += 3; - Temp2 += 3; - } - - //skip bytes that were read via Temp2 - Temp += 8; - } - Offset += Image->Bps*4; - } - } - - return IL_TRUE; -} - - -ILboolean DecompressAti1n() -{ - int x, y, z, i, j, k, t1, t2; - ILubyte *Temp; - ILubyte Colours[8]; - ILuint bitmask, Offset, CurrOffset; - - if (!CompData) - return IL_FALSE; - - Temp = CompData; - Offset = 0; - for (z = 0; z < Depth; z++) { - for (y = 0; y < Height; y += 4) { - for (x = 0; x < Width; x += 4) { - //Read palette - t1 = Colours[0] = Temp[0]; - t2 = Colours[1] = Temp[1]; - Temp += 2; - if (t1 > t2) - for (i = 2; i < 8; ++i) - Colours[i] = t1 + ((t2 - t1)*(i - 1))/7; - else { - for (i = 2; i < 6; ++i) - Colours[i] = t1 + ((t2 - t1)*(i - 1))/5; - Colours[6] = 0; - Colours[7] = 255; - } - - //decompress pixel data - CurrOffset = Offset; - for (k = 0; k < 4; k += 2) { - // First three bytes - bitmask = ((ILuint)(Temp[0]) << 0) | ((ILuint)(Temp[1]) << 8) | ((ILuint)(Temp[2]) << 16); - for (j = 0; j < 2; j++) { - // only put pixels out < height - if ((y + k + j) < Height) { - for (i = 0; i < 4; i++) { - // only put pixels out < width - if (((x + i) < Width)) { - t1 = CurrOffset + (x + i); - Image->Data[t1] = Colours[bitmask & 0x07]; - } - bitmask >>= 3; - } - CurrOffset += Image->Bps; - } - } - Temp += 3; - } - } - Offset += Image->Bps*4; - } - } - - return IL_TRUE; -} - - -//This is nearly exactly the same as DecompressDXT5... -//I have to clean up this file (put common code in -//helper functions etc) -ILboolean DecompressRXGB() -{ - int x, y, z, i, j, k, Select; - ILubyte *Temp; - Color565 *color_0, *color_1; - Color8888 colours[4], *col; - ILuint bitmask, Offset; - ILubyte alphas[8], *alphamask; - ILuint bits; - - if (!CompData) - return IL_FALSE; - - Temp = CompData; - for (z = 0; z < Depth; z++) { - for (y = 0; y < Height; y += 4) { - for (x = 0; x < Width; x += 4) { - if (y >= Height || x >= Width) - break; - alphas[0] = Temp[0]; - alphas[1] = Temp[1]; - alphamask = Temp + 2; - Temp += 8; - color_0 = ((Color565*)Temp); - color_1 = ((Color565*)(Temp+2)); - bitmask = ((ILuint*)Temp)[1]; - Temp += 8; - - colours[0].r = color_0->nRed << 3; - colours[0].g = color_0->nGreen << 2; - colours[0].b = color_0->nBlue << 3; - colours[0].a = 0xFF; - - colours[1].r = color_1->nRed << 3; - colours[1].g = color_1->nGreen << 2; - colours[1].b = color_1->nBlue << 3; - colours[1].a = 0xFF; - - // Four-color block: derive the other two colors. - // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; - colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; - colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; - colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - colours[3].a = 0xFF; - - k = 0; - for (j = 0; j < 4; j++) { - for (i = 0; i < 4; i++, k++) { - - Select = (bitmask & (0x03 << k*2)) >> k*2; - col = &colours[Select]; - - // only put pixels out < width or height - if (((x + i) < Width) && ((y + j) < Height)) { - Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp; - Image->Data[Offset + 0] = col->r; - Image->Data[Offset + 1] = col->g; - Image->Data[Offset + 2] = col->b; - } - } - } - - // 8-alpha or 6-alpha block? - if (alphas[0] > alphas[1]) { - // 8-alpha block: derive the other six alphas. - // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. - alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7; // bit code 010 - alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7; // bit code 011 - alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7; // bit code 100 - alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7; // bit code 101 - alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7; // bit code 110 - alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7; // bit code 111 - } - else { - // 6-alpha block. - // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. - alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5; // Bit code 010 - alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5; // Bit code 011 - alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5; // Bit code 100 - alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5; // Bit code 101 - alphas[6] = 0x00; // Bit code 110 - alphas[7] = 0xFF; // Bit code 111 - } - - // Note: Have to separate the next two loops, - // it operates on a 6-byte system. - // First three bytes - bits = *((ILint*)alphamask); - for (j = 0; j < 2; j++) { - for (i = 0; i < 4; i++) { - // only put pixels out < width or height - if (((x + i) < Width) && ((y + j) < Height)) { - Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 0; - Image->Data[Offset] = alphas[bits & 0x07]; - } - bits >>= 3; - } - } - - // Last three bytes - bits = *((ILint*)&alphamask[3]); - for (j = 2; j < 4; j++) { - for (i = 0; i < 4; i++) { - // only put pixels out < width or height - if (((x + i) < Width) && ((y + j) < Height)) { - Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 0; - Image->Data[Offset] = alphas[bits & 0x07]; - } - bits >>= 3; - } - } - } - } - } - - return IL_TRUE; -} - - -//Taken from OpenEXR -unsigned int -halfToFloat (unsigned short y) -{ - int s = (y >> 15) & 0x00000001; - int e = (y >> 10) & 0x0000001f; - int m = y & 0x000003ff; - - if (e == 0) - { - if (m == 0) - { - // - // Plus or minus zero - // - return s << 31; - } - else - { - // - // Denormalized number -- renormalize it - // - while (!(m & 0x00000400)) - { - m <<= 1; - e -= 1; - } - - e += 1; - m &= ~0x00000400; - } - } - else if (e == 31) - { - if (m == 0) - { - // - // Positive or negative infinity - // - return (s << 31) | 0x7f800000; - } - else - { - // - // Nan -- preserve sign and significand bits - // - return (s << 31) | 0x7f800000 | (m << 13); - } - } - - // - // Normalized number - // - e = e + (127 - 15); - m = m << 13; - - // - // Assemble s, e and m. - // - return (s << 31) | (e << 23) | m; -} - - -ILboolean iConvFloat16ToFloat32(ILuint* dest, ILushort* src, ILuint size) -{ - ILuint i; - for (i = 0; i < size; ++i, ++dest, ++src) { - //float: 1 sign bit, 8 exponent bits, 23 mantissa bits - //half: 1 sign bit, 5 exponent bits, 10 mantissa bits - *dest = halfToFloat(*src); - } - - return IL_TRUE; -} - - -// Same as iConvFloat16ToFloat32, but we have to set the blue channel to 1.0f. -// The destination format is RGB, and the source is R16G16 (little endian). -ILboolean iConvG16R16ToFloat32(ILuint* dest, ILushort* src, ILuint size) -{ - ILuint i; - for (i = 0; i < size; i += 3) { - //float: 1 sign bit, 8 exponent bits, 23 mantissa bits - //half: 1 sign bit, 5 exponent bits, 10 mantissa bits - *dest++ = halfToFloat(*src++); - *dest++ = halfToFloat(*src++); - *((ILfloat*)dest++) = 1.0f; - } - - return IL_TRUE; -} - - -// Same as iConvFloat16ToFloat32, but we have to set the green and blue channels -// to 1.0f. The destination format is RGB, and the source is R16. -ILboolean iConvR16ToFloat32(ILuint* dest, ILushort* src, ILuint size) -{ - ILuint i; - for (i = 0; i < size; i += 3) { - //float: 1 sign bit, 8 exponent bits, 23 mantissa bits - //half: 1 sign bit, 5 exponent bits, 10 mantissa bits - *dest++ = halfToFloat(*src++); - *((ILfloat*)dest++) = 1.0f; - *((ILfloat*)dest++) = 1.0f; - } - - return IL_TRUE; -} - - -ILboolean DecompressFloat(ILuint lCompFormat) -{ - ILuint i, j, Size; - - switch (lCompFormat) - { - case PF_R32F: // Red float, green = blue = max - Size = Image->Width * Image->Height * Image->Depth * 3; - for (i = 0, j = 0; i < Size; i += 3, j++) { - ((ILfloat*)Image->Data)[i] = ((ILfloat*)CompData)[j]; - ((ILfloat*)Image->Data)[i+1] = 1.0f; - ((ILfloat*)Image->Data)[i+2] = 1.0f; - } - return IL_TRUE; - case PF_A32B32G32R32F: // Direct copy of float RGBA data - memcpy(Image->Data, CompData, Image->SizeOfData); - return IL_TRUE; - case PF_G32R32F: // Red float, green float, blue = max - Size = Image->Width * Image->Height * Image->Depth * 3; - for (i = 0, j = 0; i < Size; i += 3, j += 2) { - ((ILfloat*)Image->Data)[i] = ((ILfloat*)CompData)[j]; - ((ILfloat*)Image->Data)[i+1] = ((ILfloat*)CompData)[j+1]; - ((ILfloat*)Image->Data)[i+2] = 1.0f; - } - return IL_TRUE; - case PF_R16F: // Red float, green = blue = max - return iConvR16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, - Image->Width * Image->Height * Image->Depth * Image->Bpp); - case PF_A16B16G16R16F: // Just convert from half to float. - return iConvFloat16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, - Image->Width * Image->Height * Image->Depth * Image->Bpp); - case PF_G16R16F: // Convert from half to float, set blue = max. - return iConvG16R16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, - Image->Width * Image->Height * Image->Depth * Image->Bpp); - default: - return IL_FALSE; - } -} - - -void CorrectPreMult() -{ - ILuint i; - - for (i = 0; i < Image->SizeOfData; i += 4) { - if (Image->Data[i+3] != 0) { // Cannot divide by 0. - Image->Data[i] = (ILubyte)(((ILuint)Image->Data[i] << 8) / Image->Data[i+3]); - Image->Data[i+1] = (ILubyte)(((ILuint)Image->Data[i+1] << 8) / Image->Data[i+3]); - Image->Data[i+2] = (ILubyte)(((ILuint)Image->Data[i+2] << 8) / Image->Data[i+3]); - } - } - - return; -} - - -ILboolean DecompressARGB(ILuint CompFormat) -{ - ILuint ReadI = 0, TempBpp, i; - ILuint RedL, RedR; - ILuint GreenL, GreenR; - ILuint BlueL, BlueR; - ILuint AlphaL, AlphaR; - ILubyte *Temp; - - if (Has16BitComponents) - return DecompressARGB16(CompFormat); - - if (!CompData) - return IL_FALSE; - - if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK - memcpy(Image->Data, CompData, Image->SizeOfData); - return IL_TRUE; - } - - GetBitsFromMask(Head.RBitMask, &RedL, &RedR); - GetBitsFromMask(Head.GBitMask, &GreenL, &GreenR); - GetBitsFromMask(Head.BBitMask, &BlueL, &BlueR); - GetBitsFromMask(Head.RGBAlphaBitMask, &AlphaL, &AlphaR); - Temp = CompData; - TempBpp = Head.RGBBitCount / 8; - - for (i = 0; i < Image->SizeOfData; i += Image->Bpp) { - - //@TODO: This is SLOOOW... - //but the old version crashed in release build under - //winxp (and xp is right to stop this code - I always - //wondered that it worked the old way at all) - if (Image->SizeOfData - i < 4) { //less than 4 byte to write? - if (TempBpp == 3) { //this branch is extra-SLOOOW - ReadI = - *Temp - | ((*(Temp + 1)) << 8) - | ((*(Temp + 2)) << 16); - } - else if (TempBpp == 1) - ReadI = *((ILubyte*)Temp); - else if (TempBpp == 2) - ReadI = Temp[0] | (Temp[1] << 8); - } - else - ReadI = Temp[0] | (Temp[1] << 8) | (Temp[2] << 16) | (Temp[3] << 24); - Temp += TempBpp; - - Image->Data[i] = ((ReadI & Head.RBitMask) >> RedR) << RedL; - - if (Image->Bpp >= 3) { - Image->Data[i+1] = ((ReadI & Head.GBitMask) >> GreenR) << GreenL; - Image->Data[i+2] = ((ReadI & Head.BBitMask) >> BlueR) << BlueL; - - if (Image->Bpp == 4) { - Image->Data[i+3] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; - if (AlphaL >= 7) { - Image->Data[i+3] = Image->Data[i+3] ? 0xFF : 0x00; - } - else if (AlphaL >= 4) { - Image->Data[i+3] = Image->Data[i+3] | (Image->Data[i+3] >> 4); - } - } - } - else if (Image->Bpp == 2) { - Image->Data[i+1] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; - if (AlphaL >= 7) { - Image->Data[i+1] = Image->Data[i+1] ? 0xFF : 0x00; - } - else if (AlphaL >= 4) { - Image->Data[i+1] = Image->Data[i+1] | (Image->Data[i+3] >> 4); - } - } - } - - return IL_TRUE; -} - - -// This function simply counts how many contiguous bits are in the mask. -ILuint CountBitsFromMask(ILuint Mask) -{ - ILuint i, TestBit = 0x01, Count = 0; - ILboolean FoundBit = IL_FALSE; - - for (i = 0; i < 32; i++, TestBit <<= 1) { - if (Mask & TestBit) { - if (!FoundBit) - FoundBit = IL_TRUE; - Count++; - } - else if (FoundBit) - return Count; - } - - return Count; -} - - -// Same as DecompressARGB, but it works on images with more than 8 bits -// per channel, such as a2r10g10b10 and a2b10g10r10. -ILboolean DecompressARGB16(ILuint CompFormat) -{ - ILuint ReadI = 0, TempBpp, i; - ILuint RedL, RedR; - ILuint GreenL, GreenR; - ILuint BlueL, BlueR; - ILuint AlphaL, AlphaR; - ILuint RedPad, GreenPad, BluePad, AlphaPad; - ILubyte *Temp; - - if (!CompData) - return IL_FALSE; - - GetBitsFromMask(Head.RBitMask, &RedL, &RedR); - GetBitsFromMask(Head.GBitMask, &GreenL, &GreenR); - GetBitsFromMask(Head.BBitMask, &BlueL, &BlueR); - GetBitsFromMask(Head.RGBAlphaBitMask, &AlphaL, &AlphaR); - RedPad = 16 - CountBitsFromMask(Head.RBitMask); - GreenPad = 16 - CountBitsFromMask(Head.GBitMask); - BluePad = 16 - CountBitsFromMask(Head.BBitMask); - AlphaPad = 16 - CountBitsFromMask(Head.RGBAlphaBitMask); - - RedL = RedL + RedPad; - GreenL = GreenL + GreenPad; - BlueL = BlueL + BluePad; - AlphaL = AlphaL + AlphaPad; - - Temp = CompData; - TempBpp = Head.RGBBitCount / 8; - - for (i = 0; i < Image->SizeOfData / 2; i += Image->Bpp) { - - //@TODO: This is SLOOOW... - //but the old version crashed in release build under - //winxp (and xp is right to stop this code - I always - //wondered that it worked the old way at all) - if (Image->SizeOfData - i < 4) { //less than 4 byte to write? - if (TempBpp == 3) { //this branch is extra-SLOOOW - ReadI = - *Temp - | ((*(Temp + 1)) << 8) - | ((*(Temp + 2)) << 16); - } - else if (TempBpp == 1) - ReadI = *((ILubyte*)Temp); - else if (TempBpp == 2) - ReadI = Temp[0] | (Temp[1] << 8); - } - else - ReadI = Temp[0] | (Temp[1] << 8) | (Temp[2] << 16) | (Temp[3] << 24); - Temp += TempBpp; - - ((ILushort*)Image->Data)[i+2] = ((ReadI & Head.RBitMask) >> RedR) << RedL; - - if (Image->Bpp >= 3) { - ((ILushort*)Image->Data)[i+1] = ((ReadI & Head.GBitMask) >> GreenR) << GreenL; - ((ILushort*)Image->Data)[i] = ((ReadI & Head.BBitMask) >> BlueR) << BlueL; - - if (Image->Bpp == 4) { - ((ILushort*)Image->Data)[i+3] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; - if (AlphaL >= 7) { - ((ILushort*)Image->Data)[i+3] = ((ILushort*)Image->Data)[i+3] ? 0xFF : 0x00; - } - else if (AlphaL >= 4) { - ((ILushort*)Image->Data)[i+3] = ((ILushort*)Image->Data)[i+3] | (((ILushort*)Image->Data)[i+3] >> 4); - } - } - } - else if (Image->Bpp == 2) { - ((ILushort*)Image->Data)[i+1] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; - if (AlphaL >= 7) { - ((ILushort*)Image->Data)[i+1] = ((ILushort*)Image->Data)[i+1] ? 0xFF : 0x00; - } - else if (AlphaL >= 4) { - ((ILushort*)Image->Data)[i+1] = ((ILushort*)Image->Data)[i+1] | (Image->Data[i+3] >> 4); - } - } - } - - return IL_TRUE; -} - - -// @TODO: Look at using the BSF/BSR operands for inline ASM here. -void GetBitsFromMask(ILuint Mask, ILuint *ShiftLeft, ILuint *ShiftRight) -{ - ILuint Temp, i; - - if (Mask == 0) { - *ShiftLeft = *ShiftRight = 0; - return; - } - - Temp = Mask; - for (i = 0; i < 32; i++, Temp >>= 1) { - if (Temp & 1) - break; - } - *ShiftRight = i; - - // Temp is preserved, so use it again: - for (i = 0; i < 8; i++, Temp >>= 1) { - if (!(Temp & 1)) - break; - } - *ShiftLeft = 8 - i; - - return; -} - - -// -// -// DXT extension code -// -// -ILubyte* ILAPIENTRY ilGetDxtcData() -{ - if (iCurImage == NULL) { - ilSetError(IL_INTERNAL_ERROR); - return NULL; - } - return iCurImage->DxtcData; -} - -void ilFreeSurfaceDxtcData() -{ - if (iCurImage != NULL && iCurImage->DxtcData != NULL) { - ifree(iCurImage->DxtcData); - iCurImage->DxtcData = NULL; - iCurImage->DxtcSize = 0; - iCurImage->DxtcFormat = IL_DXT_NO_COMP; - } -} - -void ilFreeImageDxtcData() -{ - ILint i, j; - ILuint ImgID = ilGetInteger(IL_CUR_IMAGE); - ILint ImgCount = ilGetInteger(IL_NUM_IMAGES); - ILint MipCount; - - for(i = 0; i <= ImgCount; ++i) { - ilBindImage(ImgID); - ilActiveImage(i); - - MipCount = ilGetInteger(IL_NUM_MIPMAPS); - for(j = 0; j <= MipCount; ++j) { - ilBindImage(ImgID); - ilActiveImage(i); - ilActiveMipmap(j); - - ilFreeSurfaceDxtcData(); - } - } -} - -/* - * This assumes DxtcData, DxtcFormat, width, height, and depth are valid - */ -ILAPI ILboolean ILAPIENTRY ilDxtcDataToSurface() -{ - ILuint CompFormat; - - if (iCurImage == NULL || iCurImage->DxtcData == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (!(iCurImage->DxtcFormat == IL_DXT1 || iCurImage->DxtcFormat == IL_DXT3 - || iCurImage->DxtcFormat == IL_DXT5)) { - ilSetError(IL_INVALID_PARAM); //TODO - return IL_FALSE; - } - - //@TODO: is this right for all dxt formats? works for - // DXT1, 3, 5 - iCurImage->Bpp = 4; - iCurImage->Bpc = 1; - iCurImage->Bps = iCurImage->Width*iCurImage->Bpp*iCurImage->Bpc; - iCurImage->SizeOfPlane = iCurImage->Height*iCurImage->Bps; - iCurImage->Format = IL_RGBA; - iCurImage->Type = IL_UNSIGNED_BYTE; - - if (iCurImage->SizeOfData != iCurImage->SizeOfPlane*iCurImage->Depth) { - iCurImage->SizeOfData = iCurImage->Depth*iCurImage->SizeOfPlane; - if (iCurImage->Data != NULL) - ifree(iCurImage->Data); - iCurImage->Data = NULL; - } - - if (iCurImage->Data == NULL) { - iCurImage->Data = ialloc(iCurImage->SizeOfData); - } - - Image = iCurImage; - Width = iCurImage->Width; - Height = iCurImage->Height; - Depth = iCurImage->Depth; - switch(iCurImage->DxtcFormat) - { - case IL_DXT1: CompFormat = PF_DXT1; break; - case IL_DXT3: CompFormat = PF_DXT3; break; - case IL_DXT5: CompFormat = PF_DXT5; break; - } - CompData = iCurImage->DxtcData; - DdsDecompress(CompFormat); //globals suck...fix this - - //@TODO: origin should be set in Decompress()... - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - return ilFixCur(); -} - - -ILAPI ILboolean ILAPIENTRY ilDxtcDataToImage() -{ - ILint i, j; - ILuint ImgID = ilGetInteger(IL_CUR_IMAGE); - ILint ImgCount = ilGetInteger(IL_NUM_IMAGES); - ILint MipCount; - ILboolean ret = IL_TRUE; - - for(i = 0; i <= ImgCount; ++i) { - ilBindImage(ImgID); - ilActiveImage(i); - - MipCount = ilGetInteger(IL_NUM_MIPMAPS); - for(j = 0; j <= MipCount; ++j) { - ilBindImage(ImgID); - ilActiveImage(i); - ilActiveMipmap(j); - - if (!ilDxtcDataToSurface()) - ret = IL_FALSE; - } - } - ilBindImage(ImgID); - - return ret; -} - - -ILAPI ILboolean ILAPIENTRY ilSurfaceToDxtcData(ILenum Format) -{ - ILuint Size; - void* Data; - ilFreeSurfaceDxtcData(); - - Size = ilGetDXTCData(NULL, 0, Format); - if (Size == 0) { - return IL_FALSE; - } - - Data = ialloc(Size); - - if (Data == NULL) - return IL_FALSE; - - ilGetDXTCData(Data, Size, Format); - - //These have to be after the call to ilGetDXTCData() - iCurImage->DxtcData = Data; - iCurImage->DxtcFormat = Format; - iCurImage->DxtcSize = Size; - - return IL_TRUE; -} - - -ILAPI ILboolean ILAPIENTRY ilImageToDxtcData(ILenum Format) -{ - ILint i, j; - ILuint ImgID = ilGetInteger(IL_CUR_IMAGE); - ILint ImgCount = ilGetInteger(IL_NUM_IMAGES); - ILint MipCount; - ILboolean ret = IL_TRUE; - - for (i = 0; i <= ImgCount; ++i) { - ilBindImage(ImgID); - ilActiveImage(i); - - MipCount = ilGetInteger(IL_NUM_MIPMAPS); - for(j = 0; j <= MipCount; ++j) { - ilBindImage(ImgID); - ilActiveImage(i); - ilActiveMipmap(j); - - if (!ilSurfaceToDxtcData(Format)) - ret = IL_FALSE; - } - } - - return ret; -} - - -//works like ilTexImage(), ie. destroys mipmaps etc (which sucks, but -//is consistent. There should be a ilTexSurface() and ilTexSurfaceDxtc() -//functions as well, but for now this is sufficient) -ILAPI ILboolean ILAPIENTRY ilTexImageDxtc(ILint w, ILint h, ILint d, ILenum DxtFormat, const ILubyte* data) -{ - ILimage* Image = iCurImage; - - ILint xBlocks, yBlocks, BlockSize, LineSize, DataSize; - - - //The next few lines are copied from ilTexImage() and ilInitImage() - - //should be factored in more reusable functions... - if (Image == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - //// - - // Not sure if we should be getting rid of the palette... - if (Image->Pal.Palette && Image->Pal.PalSize && Image->Pal.PalType != IL_PAL_NONE) { - ifree(Image->Pal.Palette); - } - - // These are set NULL later by the memset call. - ilCloseImage(Image->Mipmaps); - ilCloseImage(Image->Next); - ilCloseImage(Image->Faces); - ilCloseImage(Image->Layers); - - if (Image->AnimList) ifree(Image->AnimList); - if (Image->Profile) ifree(Image->Profile); - if (Image->DxtcData) ifree(Image->DxtcData); - if (Image->Data) ifree(Image->Data); - - - //// - - memset(Image, 0, sizeof(ILimage)); - Image->Width = w; - Image->Height = h; - Image->Depth = d; - - //TODO: What about origin with dxtc data? - Image->Origin = IL_ORIGIN_LOWER_LEFT; - Image->Pal.PalType = IL_PAL_NONE; - - // Allocate DXT data buffer - xBlocks = (w + 3)/4; - yBlocks = (h + 3)/4; - if (DxtFormat == IL_DXT1) - BlockSize = 8; - else - BlockSize = 16; - - LineSize = xBlocks * BlockSize; - - DataSize = yBlocks * LineSize * d; - - Image->DxtcFormat = DxtFormat; - Image->DxtcSize = DataSize; - Image->DxtcData = ialloc(DataSize); - - if (Image->DxtcData == NULL) { - return IL_FALSE; - } - - if (data != NULL) - memcpy(Image->DxtcData, data, DataSize); - - return IL_TRUE; -} - - -/* ------------------------------------------------------------------- */ - -void iFlipColorBlock(ILubyte *data) -{ - ILubyte tmp; - - tmp = data[4]; - data[4] = data[7]; - data[7] = tmp; - - tmp = data[5]; - data[5] = data[6]; - data[6] = tmp; -} - -void iFlipSimpleAlphaBlock(ILushort *data) -{ - ILushort tmp; - - tmp = data[0]; - data[0] = data[3]; - data[3] = tmp; - - tmp = data[1]; - data[1] = data[2]; - data[2] = tmp; -} - -void iComplexAlphaHelper(ILubyte* Data) -{ - ILushort tmp[2]; - - //one 4 pixel line is 12 bit, copy each line into - //a ushort, swap them and copy back - tmp[0] = (Data[0] | (Data[1] << 8)) & 0xfff; - tmp[1] = ((Data[1] >> 4) | (Data[2] << 4)) & 0xfff; - - Data[0] = (ILubyte)tmp[1]; - Data[1] = (tmp[1] >> 8) | (tmp[0] << 4); - Data[2] = tmp[0] >> 4; -} - -void iFlipComplexAlphaBlock(ILubyte *Data) -{ - ILubyte tmp[3]; - Data += 2; //Skip 'palette' - - //swap upper two rows with lower two rows - memcpy(tmp, Data, 3); - memcpy(Data, Data + 3, 3); - memcpy(Data + 3, tmp, 3); - - //swap 1st with 2nd row, 3rd with 4th - iComplexAlphaHelper(Data); - iComplexAlphaHelper(Data + 3); -} - -void iFlipDxt1(ILubyte* data, ILuint count) -{ - ILuint i; - - for (i = 0; i < count; ++i) { - iFlipColorBlock(data); - data += 8; //advance to next block - } -} - -void iFlipDxt3(ILubyte* data, ILuint count) -{ - ILuint i; - for (i = 0; i < count; ++i) { - iFlipSimpleAlphaBlock((ILushort*)data); - iFlipColorBlock(data + 8); - data += 16; //advance to next block - } -} - -void iFlipDxt5(ILubyte* data, ILuint count) -{ - ILuint i; - for (i = 0; i < count; ++i) { - iFlipComplexAlphaBlock(data); - iFlipColorBlock(data + 8); - data += 16; //advance to next block - } -} - -void iFlip3dc(ILubyte* data, ILuint count) -{ - ILuint i; - for (i = 0; i < count; ++i) { - iFlipComplexAlphaBlock(data); - iFlipComplexAlphaBlock(data + 8); - data += 16; //advance to next block - } -} - - -ILAPI void ILAPIENTRY ilFlipSurfaceDxtcData() -{ - ILuint y, z; - ILuint BlockSize, LineSize; - ILubyte *Temp, *Runner, *Top, *Bottom; - ILuint numXBlocks, numYBlocks; - void (*FlipBlocks)(ILubyte* data, ILuint count); - - if (iCurImage == NULL || iCurImage->DxtcData == NULL) { - ilSetError(IL_INVALID_PARAM); - return; - } - - numXBlocks = (iCurImage->Width + 3)/4; - numYBlocks = (iCurImage->Height + 3)/4; - - switch (iCurImage->DxtcFormat) - { - case IL_DXT1: - BlockSize = 8; - FlipBlocks = iFlipDxt1; - break; - case IL_DXT2: - case IL_DXT3: - BlockSize = 16; - FlipBlocks = iFlipDxt3; - break; - case IL_DXT4: - case IL_DXT5: - case IL_RXGB: - BlockSize = 16; - FlipBlocks = iFlipDxt5; - break; - case IL_3DC: - BlockSize = 16; - FlipBlocks = iFlip3dc; - break; - default: - ilSetError(IL_INVALID_PARAM); - return; - } - - LineSize = numXBlocks * BlockSize; - Temp = ialloc(LineSize); - - if (Temp == NULL) - return; - - Runner = iCurImage->DxtcData; - for (z = 0; z < iCurImage->Depth; ++z) { - Top = Runner; - Bottom = Runner + (numYBlocks - 1)*LineSize; - - for (y = 0; y < numYBlocks/2; ++y) { - //swap block row - memcpy(Temp, Top, LineSize); - memcpy(Top, Bottom, LineSize); - memcpy(Bottom, Temp, LineSize); - - - //swap blocks - FlipBlocks(Top, numXBlocks); - FlipBlocks(Bottom, numXBlocks); - - Top += LineSize; - Bottom -= LineSize; - } - - //middle line - if (numYBlocks % 2 != 0) - FlipBlocks(Top, numXBlocks); - - Runner += LineSize * numYBlocks; - } - - ifree(Temp); -} - -/**********************************************************************/ - -void iInvertDxt3Alpha(ILubyte *data) -{ - ILint i; - - for (i = 0; i < 8; ++i) { - /* - ILubyte b, t1, t2; - b = data[i]; - - t1 = b & 0xf; - t1 = 15 - t1; - t2 = b >> 4; - t2 = 15 - t2; - - data[i] = (t2 << 4) | t1; - */ - //simpler: - data[i] = ~data[i]; - } -} - -void iInvertDxt5Alpha(ILubyte *data) -{ - ILubyte a0, a1; - ILint i, j; - const ILubyte map1[] = { 1, 0, 7, 6, 5, 4, 3, 2 }; - const ILubyte map2[] = { 1, 0, 5, 4, 3, 2, 7, 6 }; - - - a0 = data[0]; - a1 = data[1]; - - //a0 > a1 <=> 255 - a0 < 255 - a1. Because of this, - //a1 and a2 have to be swapped, and the indices - //have to be changed as well. - - //invert and swap alpha - data[0] = 255 - a1; - data[1] = 255 - a0; - data += 2; - - //fix indices - for (i = 0; i < 6; i += 3) { - ILuint in = data[i] | (data[i+1] << 8) | (data[i+2] << 16); - ILuint out = 0; - - for (j = 0; j < 24; j += 3) { - ILubyte b = (in >> j) & 0x7; - - if (a0 > a1) - b = map1[b]; - else - b = map2[b]; - - out |= b << j; - } - - data[i] = out; - data[i+1] = out >> 8; - data[i+2] = out >> 16; - } -} - - -ILAPI ILboolean ILAPIENTRY ilInvertSurfaceDxtcDataAlpha() -{ - ILint i; - ILuint BlockSize; - ILubyte *Runner; - ILint numXBlocks, numYBlocks, numBlocks; - void (*InvertAlpha)(ILubyte* data); - - if (iCurImage == NULL || iCurImage->DxtcData == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - numXBlocks = (iCurImage->Width + 3)/4; - numYBlocks = (iCurImage->Height + 3)/4; - numBlocks = numXBlocks*numYBlocks*iCurImage->Depth; - BlockSize = 16; - - switch (iCurImage->DxtcFormat) - { - case IL_DXT3: - InvertAlpha = iInvertDxt3Alpha; - break; - case IL_DXT5: - InvertAlpha = iInvertDxt5Alpha; - break; - default: - //DXT2/4 are not supported yet because nobody - //uses them anyway and I would have to change - //the color blocks as well... - //DXT1 is not supported because DXT1 alpha is - //seldom used and it's not easily invertable. - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - Runner = iCurImage->DxtcData; - for (i = 0; i < numBlocks; ++i, Runner += BlockSize) { - InvertAlpha(Runner); - } - - return IL_TRUE; -} - - - - -#endif//IL_NO_DDS diff --git a/DevIL/src-IL/src/il_dds.cpp b/DevIL/src-IL/src/il_dds.cpp new file mode 100644 index 00000000..02978c7b --- /dev/null +++ b/DevIL/src-IL/src/il_dds.cpp @@ -0,0 +1,2523 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/28/2009 +// +// Filename: src-IL/src/il_dds.c +// +// Description: Reads from a DirectDraw Surface (.dds) file. +// +//----------------------------------------------------------------------------- + + +// +// +// Note: Almost all this code is from nVidia's DDS-loading example at +// http://www.nvidia.com/view.asp?IO=dxtc_decompression_code +// and from the specs at +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/hh/dx8_c/graphics_using_0j03.asp +// and +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dx8_c/directx_cpp/Graphics/ProgrammersGuide/Appendix/DDSFileFormat/ovwDDSFileFormat.asp +// However, some not really valid .dds files are also read, for example +// Volume Textures without the COMPLEX bit set, so the specs aren't taken +// too strictly while reading. + + +#include "il_internal.h" +#ifndef IL_NO_DDS +#include "il_dds.h" + + +// Global variables +static DDSHEAD Head; // Image header +static ILubyte *CompData = NULL; // Compressed data +static ILuint CompSize; // Compressed size +//static ILuint CompFormat; // Compressed format +static ILimage *Image; +static ILint Width, Height, Depth; +static ILboolean Has16BitComponents; + +ILuint CubemapDirections[CUBEMAP_SIDES] = { + DDS_CUBEMAP_POSITIVEX, + DDS_CUBEMAP_NEGATIVEX, + DDS_CUBEMAP_POSITIVEY, + DDS_CUBEMAP_NEGATIVEY, + DDS_CUBEMAP_POSITIVEZ, + DDS_CUBEMAP_NEGATIVEZ +}; + + +//! Checks if the file specified in FileName is a valid .dds file. +ILboolean ilIsValidDds(ILconst_string FileName) +{ + ILHANDLE DdsFile; + ILboolean bDds = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("dds"))) { + ilSetError(IL_INVALID_EXTENSION); + return bDds; + } + + DdsFile = iopenr(FileName); + if (DdsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDds; + } + + bDds = ilIsValidDdsF(DdsFile); + icloser(DdsFile); + + return bDds; +} + + +//! Checks if the ILHANDLE contains a valid .dds file at the current position. +ILboolean ilIsValidDdsF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidDds(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .dds lump. +ILboolean ilIsValidDdsL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidDds(); +} + + +// Internal function used to get the .dds header from the current file. +ILboolean iGetDdsHead(DDSHEAD *Header) +{ + ILint i; + + iread(&Header->Signature, 1, 4); + Header->Size1 = GetLittleUInt(); + Header->Flags1 = GetLittleUInt(); + Header->Height = GetLittleUInt(); + Header->Width = GetLittleUInt(); + Header->LinearSize = GetLittleUInt(); + Header->Depth = GetLittleUInt(); + Header->MipMapCount = GetLittleUInt(); + Header->AlphaBitDepth = GetLittleUInt(); + + for (i = 0; i < 10; ++i) + Header->NotUsed[i] = GetLittleUInt(); + + Header->Size2 = GetLittleUInt(); + Header->Flags2 = GetLittleUInt(); + Header->FourCC = GetLittleUInt(); + Header->RGBBitCount = GetLittleUInt(); + Header->RBitMask = GetLittleUInt(); + Header->GBitMask = GetLittleUInt(); + Header->BBitMask = GetLittleUInt(); + Header->RGBAlphaBitMask = GetLittleUInt(); + Header->ddsCaps1 = GetLittleUInt(); + Header->ddsCaps2 = GetLittleUInt(); + Header->ddsCaps3 = GetLittleUInt(); + Header->ddsCaps4 = GetLittleUInt(); + Header->TextureStage = GetLittleUInt(); + + if (Head.Depth == 0) + Head.Depth = 1; + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidDds() +{ + ILboolean IsValid; + DDSHEAD Head; + + iGetDdsHead(&Head); + iseek(-(ILint)sizeof(DDSHEAD), IL_SEEK_CUR); // Go ahead and restore to previous state + + IsValid = iCheckDds(&Head); + + return IsValid; +} + + +// Internal function used to check if the HEADER is a valid .dds header. +ILboolean iCheckDds(DDSHEAD *Head) +{ + if (strncmp((const char*)Head->Signature, "DDS ", 4)) + return IL_FALSE; + //note that if Size1 is "DDS " this is not a valid dds file according + //to the file spec. Some broken tool out there seems to produce files + //with this value in the size field, so we support reading them... + if (Head->Size1 != 124 && Head->Size1 != IL_MAKEFOURCC('D', 'D', 'S', ' ')) + return IL_FALSE; + if (Head->Size2 != 32) + return IL_FALSE; + if (Head->Width == 0 || Head->Height == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Reads a .dds file +ILboolean ilLoadDds(ILconst_string FileName) +{ + ILHANDLE DdsFile; + ILboolean bDds = IL_FALSE; + + DdsFile = iopenr(FileName); + if (DdsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDds; + } + + bDds = ilLoadDdsF(DdsFile); + icloser(DdsFile); + + return bDds; +} + + +//! Reads an already-opened .dds file +ILboolean ilLoadDdsF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDdsInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .dds +ILboolean ilLoadDdsL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadDdsInternal(); +} + + +void Check16BitComponents(DDSHEAD *Header) +{ + if (Header->RGBBitCount != 32) + Has16BitComponents = IL_FALSE; + // a2b10g10r10 format + if (Header->RBitMask == 0x3FF00000 && Header->GBitMask == 0x000FFC00 && Header->BBitMask == 0x000003FF + && Header->RGBAlphaBitMask == 0xC0000000) + Has16BitComponents = IL_TRUE; + // a2r10g10b10 format + else if (Header->RBitMask == 0x000003FF && Header->GBitMask == 0x000FFC00 && Header->BBitMask == 0x3FF00000 + && Header->RGBAlphaBitMask == 0xC0000000) + Has16BitComponents = IL_TRUE; + else + Has16BitComponents = IL_FALSE; + return; +} + + +ILubyte iCompFormatToBpp(ILenum Format) +{ + //non-compressed (= non-FOURCC) codes + if (Format == PF_LUMINANCE || Format == PF_LUMINANCE_ALPHA || Format == PF_ARGB) + return Head.RGBBitCount/8; + + //fourcc formats + else if (Format == PF_RGB || Format == PF_3DC || Format == PF_RXGB) + return 3; + else if (Format == PF_ATI1N) + return 1; + //else if (Format == PF_R16F) + // return 2; + else if (Format == PF_A16B16G16R16 || Format == PF_A16B16G16R16F + || Format == PF_G32R32F) + return 8; + else if (Format == PF_A32B32G32R32F) + return 16; + else //if (Format == PF_G16R16F || Format == PF_R32F || dxt) + return 4; +} + + +ILubyte iCompFormatToBpc(ILenum Format) +{ + if (Has16BitComponents) + return 2; + if (Format == PF_R16F || Format == PF_G16R16F || Format == PF_A16B16G16R16F) + //DevIL has no internal half type, so these formats are converted to 32 bits + return 4; + else if (Format == PF_R32F || Format == PF_R16F || Format == PF_G32R32F || Format == PF_A32B32G32R32F) + return 4; + else if(Format == PF_A16B16G16R16) + return 2; + else + return 1; +} + + +ILubyte iCompFormatToChannelCount(ILenum Format) +{ + if (Format == PF_RGB || Format == PF_3DC || Format == PF_RXGB) + return 3; + else if (Format == PF_LUMINANCE || /*Format == PF_R16F || Format == PF_R32F ||*/ Format == PF_ATI1N) + return 1; + else if (Format == PF_LUMINANCE_ALPHA /*|| Format == PF_G16R16F || Format == PF_G32R32F*/) + return 2; + else if (Format == PF_G16R16F || Format == PF_G32R32F || Format == PF_R32F || Format == PF_R16F) + return 3; + else //if(Format == PF_ARGB || dxt) + return 4; +} + + +ILboolean iLoadDdsCubemapInternal(ILuint CompFormat) +{ + ILuint i; + ILubyte Bpp, Channels, Bpc; + ILimage *startImage; + + CompData = NULL; + + Bpp = iCompFormatToBpp(CompFormat); + Channels = iCompFormatToChannelCount(CompFormat); + Bpc = iCompFormatToBpc(CompFormat); + if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //@TODO: This is a HACK. + Bpc = 2; Bpp = 2; + } + + startImage = Image; + // Run through cube map possibilities + for (i = 0; i < CUBEMAP_SIDES; i++) { + // Reset each time + Width = Head.Width; + Height = Head.Height; + Depth = Head.Depth; + if (Head.ddsCaps2 & CubemapDirections[i]) { + if (i != 0) { + Image->Faces = ilNewImage(Width, Height, Depth, Channels, Bpc); + if (Image->Faces == NULL) + return IL_FALSE; + + Image = Image->Faces; + + if (CompFormat == PF_R16F + || CompFormat == PF_G16R16F + || CompFormat == PF_A16B16G16R16F + || CompFormat == PF_R32F + || CompFormat == PF_G32R32F + || CompFormat == PF_A32B32G32R32F) { + // DevIL's format autodetection doesn't work for + // float images...correct this. + Image->Type = IL_FLOAT; + Image->Bpp = Channels; + } + + ilBindImage(ilGetCurName()); // Set to parent image first. + //ilActiveImage(i); //@TODO: now Image == iCurImage...globals SUCK, fix this!!! + ilActiveFace(i); + } + + if (!ReadData()) + return IL_FALSE; + + if (!AllocImage(CompFormat)) { + if (CompData) { + ifree(CompData); + CompData = NULL; + } + return IL_FALSE; + } + + Image->CubeFlags = CubemapDirections[i]; + + if (!DdsDecompress(CompFormat)) { + if (CompData) { + ifree(CompData); + CompData = NULL; + } + return IL_FALSE; + } + + if (!ReadMipmaps(CompFormat)) { + if (CompData) { + ifree(CompData); + CompData = NULL; + } + return IL_FALSE; + } + } + } + + if (CompData) { + ifree(CompData); + CompData = NULL; + } + + ilBindImage(ilGetCurName()); // Set to parent image first. + return ilFixImage(); +} + + +ILboolean iLoadDdsInternal() +{ + ILuint BlockSize = 0; + ILuint CompFormat; + + CompData = NULL; + Image = NULL; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetDdsHead(&Head)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!iCheckDds(&Head)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + BlockSize = DecodePixelFormat(&CompFormat); + if (CompFormat == PF_UNKNOWN) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + Check16BitComponents(&Head); + + // Microsoft bug, they're not following their own documentation. + if (!(Head.Flags1 & (DDS_LINEARSIZE | DDS_PITCH)) + || Head.LinearSize == 0) { + Head.Flags1 |= DDS_LINEARSIZE; + Head.LinearSize = BlockSize; + } + + Image = iCurImage; + if (Head.ddsCaps1 & DDS_COMPLEX) { + if (Head.ddsCaps2 & DDS_CUBEMAP) { + if (!iLoadDdsCubemapInternal(CompFormat)) + return IL_FALSE; + return IL_TRUE; + } + } + + Width = Head.Width; + Height = Head.Height; + Depth = Head.Depth; + AdjustVolumeTexture(&Head, CompFormat); + + if (!ReadData()) + return IL_FALSE; + if (!AllocImage(CompFormat)) { + if (CompData) { + ifree(CompData); + CompData = NULL; + } + return IL_FALSE; + } + if (!DdsDecompress(CompFormat)) { + if (CompData) { + ifree(CompData); + CompData = NULL; + } + return IL_FALSE; + } + + if (!ReadMipmaps(CompFormat)) { + if (CompData) { + ifree(CompData); + CompData = NULL; + } + return IL_FALSE; + } + + if (CompData) { + ifree(CompData); + CompData = NULL; + } + + ilBindImage(ilGetCurName()); // Set to parent image first. + return ilFixImage(); +} + + +ILuint DecodePixelFormat(ILuint *CompFormat) +{ + ILuint BlockSize; + + if (Head.Flags2 & DDS_FOURCC) { + BlockSize = ((Head.Width + 3)/4) * ((Head.Height + 3)/4) * Head.Depth; + switch (Head.FourCC) + { + case IL_MAKEFOURCC('D','X','T','1'): + *CompFormat = PF_DXT1; + BlockSize *= 8; + break; + + case IL_MAKEFOURCC('D','X','T','2'): + *CompFormat = PF_DXT2; + BlockSize *= 16; + break; + + case IL_MAKEFOURCC('D','X','T','3'): + *CompFormat = PF_DXT3; + BlockSize *= 16; + break; + + case IL_MAKEFOURCC('D','X','T','4'): + *CompFormat = PF_DXT4; + BlockSize *= 16; + break; + + case IL_MAKEFOURCC('D','X','T','5'): + *CompFormat = PF_DXT5; + BlockSize *= 16; + break; + + case IL_MAKEFOURCC('A', 'T', 'I', '1'): + *CompFormat = PF_ATI1N; + BlockSize *= 8; + break; + + case IL_MAKEFOURCC('A', 'T', 'I', '2'): + *CompFormat = PF_3DC; + BlockSize *= 16; + break; + + case IL_MAKEFOURCC('R', 'X', 'G', 'B'): + *CompFormat = PF_RXGB; + BlockSize *= 16; + break; + + case IL_MAKEFOURCC('$', '\0', '\0', '\0'): + *CompFormat = PF_A16B16G16R16; + BlockSize = Head.Width * Head.Height * Head.Depth * 8; + break; + + case IL_MAKEFOURCC('o', '\0', '\0', '\0'): + *CompFormat = PF_R16F; + BlockSize = Head.Width * Head.Height * Head.Depth * 2; + break; + + case IL_MAKEFOURCC('p', '\0', '\0', '\0'): + *CompFormat = PF_G16R16F; + BlockSize = Head.Width * Head.Height * Head.Depth * 4; + break; + + case IL_MAKEFOURCC('q', '\0', '\0', '\0'): + *CompFormat = PF_A16B16G16R16F; + BlockSize = Head.Width * Head.Height * Head.Depth * 8; + break; + + case IL_MAKEFOURCC('r', '\0', '\0', '\0'): + *CompFormat = PF_R32F; + BlockSize = Head.Width * Head.Height * Head.Depth * 4; + break; + + case IL_MAKEFOURCC('s', '\0', '\0', '\0'): + *CompFormat = PF_G32R32F; + BlockSize = Head.Width * Head.Height * Head.Depth * 8; + break; + + case IL_MAKEFOURCC('t', '\0', '\0', '\0'): + *CompFormat = PF_A32B32G32R32F; + BlockSize = Head.Width * Head.Height * Head.Depth * 16; + break; + + default: + *CompFormat = PF_UNKNOWN; + BlockSize *= 16; + break; + } + } else { + // This dds texture isn't compressed so write out ARGB or luminance format + if (Head.Flags2 & DDS_LUMINANCE) { + if (Head.Flags2 & DDS_ALPHAPIXELS) { + *CompFormat = PF_LUMINANCE_ALPHA; + } else { + *CompFormat = PF_LUMINANCE; + } + } + else { + if (Head.Flags2 & DDS_ALPHAPIXELS) { + *CompFormat = PF_ARGB; + } else { + *CompFormat = PF_RGB; + } + } + BlockSize = (Head.Width * Head.Height * Head.Depth * (Head.RGBBitCount >> 3)); + } + + return BlockSize; +} + + +// The few volume textures that I have don't have consistent LinearSize +// entries, even though the DDS_LINEARSIZE flag is set. +void AdjustVolumeTexture(DDSHEAD *Head, ILuint CompFormat) +{ + if (Head->Depth <= 1) + return; + + // All volume textures I've seem so far didn't have the DDS_COMPLEX flag set, + // even though this is normally required. But because noone does set it, + // also read images without it (TODO: check file size for 3d texture?) + if (/*!(Head->ddsCaps1 & DDS_COMPLEX) ||*/ !(Head->ddsCaps2 & DDS_VOLUME)) { + Head->Depth = 1; + Depth = 1; + } + + switch (CompFormat) + { + case PF_ARGB: + case PF_RGB: + case PF_LUMINANCE: + case PF_LUMINANCE_ALPHA: + //don't use the iCompFormatToBpp() function because this way + //argb images with only 8 bits (eg. a1r2g3b2) work as well + Head->LinearSize = IL_MAX(1,Head->Width) * IL_MAX(1,Head->Height) * + (Head->RGBBitCount / 8); + break; + + case PF_DXT1: + + case PF_ATI1N: + Head->LinearSize = ((Head->Width+3)/4) * ((Head->Height+3)/4) * 8; + break; + + case PF_DXT2: + case PF_DXT3: + case PF_DXT4: + case PF_DXT5: + case PF_3DC: + case PF_RXGB: + Head->LinearSize = ((Head->Width+3)/4) * ((Head->Height+3)/4) * 16; + break; + + case PF_A16B16G16R16: + case PF_R16F: + case PF_G16R16F: + case PF_A16B16G16R16F: + case PF_R32F: + case PF_G32R32F: + case PF_A32B32G32R32F: + Head->LinearSize = IL_MAX(1,Head->Width) * IL_MAX(1,Head->Height) * + iCompFormatToBpp(CompFormat); + break; + } + + Head->Flags1 |= DDS_LINEARSIZE; + Head->LinearSize *= Head->Depth; + + return; +} + + +// Reads the compressed data +ILboolean ReadData() +{ + ILuint Bps; + ILint y, z; + ILubyte *Temp; + + if (CompData) { + ifree(CompData); + CompData = NULL; + } + + if (Head.Flags1 & DDS_LINEARSIZE) { + //Head.LinearSize = Head.LinearSize * Depth; + + CompData = (ILubyte*)ialloc(Head.LinearSize); + if (CompData == NULL) { + return IL_FALSE; + } + + if (iread(CompData, 1, Head.LinearSize) != (ILuint)Head.LinearSize) { + ifree(CompData); + CompData = NULL; + return IL_FALSE; + } + } + else { + Bps = Width * Head.RGBBitCount / 8; + CompSize = Bps * Height * Depth; + + CompData = (ILubyte*)ialloc(CompSize); + if (CompData == NULL) { + return IL_FALSE; + } + + Temp = CompData; + for (z = 0; z < Depth; z++) { + for (y = 0; y < Height; y++) { + if (iread(Temp, 1, Bps) != Bps) { + ifree(CompData); + CompData = NULL; + return IL_FALSE; + } + Temp += Bps; + } + } + } + + return IL_TRUE; +} + + +ILboolean AllocImage(ILuint CompFormat) +{ + ILubyte channels = 4; + ILenum format = IL_RGBA; + + switch (CompFormat) + { + case PF_RGB: + if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + case PF_ARGB: + if (!ilTexImage(Width, Height, Depth, 4, IL_RGBA, Has16BitComponents ? IL_UNSIGNED_SHORT : IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + + case PF_LUMINANCE: + if (Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK + if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + } + else + if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + + case PF_LUMINANCE_ALPHA: + if (!ilTexImage(Width, Height, Depth, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + + case PF_ATI1N: + //right now there's no OpenGL api to use the compressed 3dc data, so + //throw it away (I don't know how DirectX works, though)? + if (!ilTexImage(Width, Height, Depth, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + + case PF_3DC: + //right now there's no OpenGL api to use the compressed 3dc data, so + //throw it away (I don't know how DirectX works, though)? + if (!ilTexImage(Width, Height, Depth, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + break; + + case PF_A16B16G16R16: + if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), + ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + break; + + case PF_R16F: + case PF_G16R16F: + case PF_A16B16G16R16F: + case PF_R32F: + case PF_G32R32F: + case PF_A32B32G32R32F: + if (!ilTexImage(Width, Height, Depth, iCompFormatToChannelCount(CompFormat), + ilGetFormatBpp(iCompFormatToChannelCount(CompFormat)), IL_FLOAT, NULL)) + return IL_FALSE; + break; + + default: + if (CompFormat == PF_RXGB) { + channels = 3; //normal map + format = IL_RGB; + } + + if (!ilTexImage(Width, Height, Depth, channels, format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && CompData) { + iCurImage->DxtcData = (ILubyte*)ialloc(Head.LinearSize); + if (iCurImage->DxtcData == NULL) + return IL_FALSE; + iCurImage->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1; + iCurImage->DxtcSize = Head.LinearSize; + memcpy(iCurImage->DxtcData, CompData, iCurImage->DxtcSize); + } + break; + } + + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + return IL_TRUE; +} + + +/* + * Assumes that the global variable CompFormat stores the format of the + * global pointer CompData (that's the pointer to the compressed data). + * Decompresses this data into Image->Data, returns if it was successful. + * It also uses the globals Width and Height. + * + * Assumes that iCurImage has valid Width, Height, Depth, Data, SizeOfData, + * Bpp, Bpc, Bps, SizeOfPlane, Format and Type fields. It is more or + * less assumed that the image has u8 rgba data (perhaps not for float + * images...) + * + * + * @TODO: don't use globals, clean this function (and this file) up + */ +ILboolean DdsDecompress(ILuint CompFormat) +{ + switch (CompFormat) + { + case PF_ARGB: + case PF_RGB: + case PF_LUMINANCE: + case PF_LUMINANCE_ALPHA: + return DecompressARGB(CompFormat); + + case PF_DXT1: + return DecompressDXT1(Image, CompData); + + case PF_DXT2: + return DecompressDXT2(Image, CompData); + + case PF_DXT3: + return DecompressDXT3(Image, CompData); + + case PF_DXT4: + return DecompressDXT4(Image, CompData); + + case PF_DXT5: + return DecompressDXT5(Image, CompData); + + case PF_ATI1N: + return DecompressAti1n(); + + case PF_3DC: + return Decompress3Dc(); + + case PF_RXGB: + return DecompressRXGB(); + + case PF_A16B16G16R16: + memcpy(Image->Data, CompData, Image->SizeOfData); + return IL_TRUE; + + case PF_R16F: + case PF_G16R16F: + case PF_A16B16G16R16F: + case PF_R32F: + case PF_G32R32F: + case PF_A32B32G32R32F: + return DecompressFloat(CompFormat); + + case PF_UNKNOWN: + return IL_FALSE; + } + + return IL_FALSE; +} + + +ILboolean ReadMipmaps(ILuint CompFormat) +{ + ILuint i, CompFactor=0; + ILubyte Bpp, Channels, Bpc; + ILimage *StartImage, *TempImage; + ILuint LastLinear; + ILuint minW, minH; + + ILboolean isCompressed = IL_FALSE; + + Bpp = iCompFormatToBpp(CompFormat); + Channels = iCompFormatToChannelCount(CompFormat); + Bpc = iCompFormatToBpc(CompFormat); + if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK + Bpc = 2; Bpp = 2; + } + + //This doesn't work for images which first mipmap (= the image + //itself) has width or height < 4 + //if (Head.Flags1 & DDS_LINEARSIZE) { + // CompFactor = (Width * Height * Depth * Bpp) / Head.LinearSize; + //} + switch (CompFormat) + { + case PF_DXT1: + // This is officially 6, we have 8 here because DXT1 may contain alpha. + CompFactor = 8; + break; + case PF_DXT2: + case PF_DXT3: + case PF_DXT4: + case PF_DXT5: + CompFactor = 4; + break; + case PF_RXGB: + case PF_3DC: + // This is officially 4 for 3dc, but that's bullshit :) There's no + // alpha data in 3dc images. + CompFactor = 3; + break; + + case PF_ATI1N: + CompFactor = 2; + break; + default: + CompFactor = 1; + } + + StartImage = Image; + + if (!(Head.Flags1 & DDS_MIPMAPCOUNT) || Head.MipMapCount == 0) { + //some .dds-files have their mipmap flag set, + //but a mipmapcount of 0. Because mipMapCount is an uint, 0 - 1 gives + //overflow - don't let this happen: + Head.MipMapCount = 1; + } + + LastLinear = Head.LinearSize; + for (i = 0; i < Head.MipMapCount - 1; i++) { + Depth = Depth / 2; + Width = Width / 2; + Height = Height / 2; + + if (Depth == 0) + Depth = 1; + if (Width == 0) + Width = 1; + if (Height == 0) + Height = 1; + + Image->Mipmaps = ilNewImage(Width, Height, Depth, Channels, Bpc); + if (Image->Mipmaps == NULL) + goto mip_fail; + Image = Image->Mipmaps; + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + if (Head.Flags1 & DDS_LINEARSIZE) { + if (CompFormat == PF_R16F + || CompFormat == PF_G16R16F + || CompFormat == PF_A16B16G16R16F + || CompFormat == PF_R32F + || CompFormat == PF_G32R32F + || CompFormat == PF_A32B32G32R32F) { + Head.LinearSize = Width * Height * Depth * Bpp; + + //DevIL's format autodetection doesn't work for + //float images...correct this + Image->Type = IL_FLOAT; + Image->Bpp = Channels; + } + else if (CompFormat == PF_A16B16G16R16) + Head.LinearSize = Width * Height * Depth * Bpp; + else if (CompFormat != PF_RGB && CompFormat != PF_ARGB + && CompFormat != PF_LUMINANCE + && CompFormat != PF_LUMINANCE_ALPHA) { + + //compressed format + minW = (((Width+3)/4))*4; + minH = (((Height+3)/4))*4; + Head.LinearSize = (minW * minH * Depth * Bpp) / CompFactor; + + isCompressed = IL_TRUE; + } + else { + //don't use Bpp to support argb images with less than 32 bits + Head.LinearSize = Width * Height * Depth * (Head.RGBBitCount >> 3); + } + } + else { + Head.LinearSize >>= 1; + } + + if (!ReadData()) + goto mip_fail; + + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE && isCompressed == IL_TRUE && CompData) { + Image->DxtcData = (ILubyte*)ialloc(Head.LinearSize); + if (Image->DxtcData == NULL) + return IL_FALSE; + Image->DxtcFormat = CompFormat - PF_DXT1 + IL_DXT1; + Image->DxtcSize = Head.LinearSize; + memcpy(Image->DxtcData, CompData, Image->DxtcSize); + } + + if (!DdsDecompress(CompFormat)) + goto mip_fail; + } + + Head.LinearSize = LastLinear; + Image = StartImage; + + return IL_TRUE; + +mip_fail: + Image = StartImage; + StartImage = StartImage->Mipmaps; + while (StartImage) { + TempImage = StartImage; + StartImage = StartImage->Mipmaps; + ifree(TempImage); + } + + Image->Mipmaps = NULL; + return IL_FALSE; +} + + +void DxtcReadColors(const ILubyte* Data, Color8888* Out) +{ + ILubyte r0, g0, b0, r1, g1, b1; + + b0 = Data[0] & 0x1F; + g0 = ((Data[0] & 0xE0) >> 5) | ((Data[1] & 0x7) << 3); + r0 = (Data[1] & 0xF8) >> 3; + + b1 = Data[2] & 0x1F; + g1 = ((Data[2] & 0xE0) >> 5) | ((Data[3] & 0x7) << 3); + r1 = (Data[3] & 0xF8) >> 3; + + Out[0].r = r0 << 3 | r0 >> 2; + Out[0].g = g0 << 2 | g0 >> 3; + Out[0].b = b0 << 3 | b0 >> 2; + + Out[1].r = r1 << 3 | r1 >> 2; + Out[1].g = g1 << 2 | g1 >> 3; + Out[1].b = b1 << 3 | b1 >> 2; +} + +//@TODO: Probably not safe on Big Endian. +void DxtcReadColor(ILushort Data, Color8888* Out) +{ + ILubyte r, g, b; + + b = Data & 0x1f; + g = (Data & 0x7E0) >> 5; + r = (Data & 0xF800) >> 11; + + Out->r = r << 3 | r >> 2; + Out->g = g << 2 | g >> 3; + Out->b = b << 3 | r >> 2; +} + +ILboolean DecompressDXT1(ILimage *lImage, ILubyte *lCompData) +{ + ILuint x, y, z, i, j, k, Select; + ILubyte *Temp; + Color8888 colours[4], *col; + ILushort color_0, color_1; + ILuint bitmask, Offset; + + if (!lCompData) + return IL_FALSE; + + Temp = lCompData; + colours[0].a = 0xFF; + colours[1].a = 0xFF; + colours[2].a = 0xFF; + //colours[3].a = 0xFF; + for (z = 0; z < lImage->Depth; z++) { + for (y = 0; y < lImage->Height; y += 4) { + for (x = 0; x < lImage->Width; x += 4) { + color_0 = *((ILushort*)Temp); + UShort(&color_0); + color_1 = *((ILushort*)(Temp + 2)); + UShort(&color_1); + DxtcReadColor(color_0, colours); + DxtcReadColor(color_1, colours + 1); + bitmask = ((ILuint*)Temp)[1]; + UInt(&bitmask); + Temp += 8; + + if (color_0 > color_1) { + // Four-color block: derive the other two colors. + // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; + colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; + colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; + //colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + colours[3].a = 0xFF; + } + else { + // Three-color block: derive the other color. + // 00 = color_0, 01 = color_1, 10 = color_2, + // 11 = transparent. + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (colours[0].b + colours[1].b) / 2; + colours[2].g = (colours[0].g + colours[1].g) / 2; + colours[2].r = (colours[0].r + colours[1].r) / 2; + //colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + colours[3].a = 0x00; + } + + for (j = 0, k = 0; j < 4; j++) { + for (i = 0; i < 4; i++, k++) { + Select = (bitmask & (0x03 << k*2)) >> k*2; + col = &colours[Select]; + + if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { + Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp; + lImage->Data[Offset + 0] = col->r; + lImage->Data[Offset + 1] = col->g; + lImage->Data[Offset + 2] = col->b; + lImage->Data[Offset + 3] = col->a; + } + } + } + } + } + } + + return IL_TRUE; +} + + +ILboolean DecompressDXT2(ILimage *lImage, ILubyte *lCompData) +{ + // Can do color & alpha same as dxt3, but color is pre-multiplied + // so the result will be wrong unless corrected. + if (!DecompressDXT3(Image, CompData)) + return IL_FALSE; + CorrectPreMult(); + + return IL_TRUE; +} + + +ILboolean DecompressDXT3(ILimage *lImage, ILubyte *lCompData) +{ + ILuint x, y, z, i, j, k, Select; + ILubyte *Temp; + //Color565 *color_0, *color_1; + Color8888 colours[4], *col; + ILuint bitmask, Offset; + ILushort word; + ILubyte *alpha; + + if (!lCompData) + return IL_FALSE; + + Temp = lCompData; + for (z = 0; z < lImage->Depth; z++) { + for (y = 0; y < lImage->Height; y += 4) { + for (x = 0; x < lImage->Width; x += 4) { + alpha = Temp; + Temp += 8; + DxtcReadColors(Temp, colours); + bitmask = ((ILuint*)Temp)[1]; + UInt(&bitmask); + Temp += 8; + + // Four-color block: derive the other two colors. + // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; + colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; + colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; + //colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + //colours[3].a = 0xFF; + + k = 0; + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++, k++) { + Select = (bitmask & (0x03 << k*2)) >> k*2; + col = &colours[Select]; + + if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { + Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp; + lImage->Data[Offset + 0] = col->r; + lImage->Data[Offset + 1] = col->g; + lImage->Data[Offset + 2] = col->b; + } + } + } + + for (j = 0; j < 4; j++) { + word = alpha[2*j] + 256*alpha[2*j+1]; + for (i = 0; i < 4; i++) { + if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { + Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp + 3; + lImage->Data[Offset] = word & 0x0F; + lImage->Data[Offset] = lImage->Data[Offset] | (lImage->Data[Offset] << 4); + } + word >>= 4; + } + } + + } + } + } + + return IL_TRUE; +} + + +ILboolean DecompressDXT4(ILimage *lImage, ILubyte *lCompData) +{ + // Can do color & alpha same as dxt5, but color is pre-multiplied + // so the result will be wrong unless corrected. + if (!DecompressDXT5(Image, CompData)) + return IL_FALSE; + CorrectPreMult(); + + return IL_FALSE; +} + + +ILboolean DecompressDXT5(ILimage *lImage, ILubyte *lCompData) +{ + ILuint x, y, z, i, j, k, Select; + ILubyte *Temp; //, r0, g0, b0, r1, g1, b1; + Color8888 colours[4], *col; + ILuint bitmask, Offset; + ILubyte alphas[8], *alphamask; + ILuint bits; + + if (!lCompData) + return IL_FALSE; + + Temp = lCompData; + for (z = 0; z < lImage->Depth; z++) { + for (y = 0; y < lImage->Height; y += 4) { + for (x = 0; x < lImage->Width; x += 4) { + if (y >= lImage->Height || x >= lImage->Width) + break; + alphas[0] = Temp[0]; + alphas[1] = Temp[1]; + alphamask = Temp + 2; + Temp += 8; + + DxtcReadColors(Temp, colours); + bitmask = ((ILuint*)Temp)[1]; + UInt(&bitmask); + Temp += 8; + + // Four-color block: derive the other two colors. + // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; + colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; + colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; + //colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + //colours[3].a = 0xFF; + + k = 0; + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++, k++) { + + Select = (bitmask & (0x03 << k*2)) >> k*2; + col = &colours[Select]; + + // only put pixels out < width or height + if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { + Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp; + lImage->Data[Offset + 0] = col->r; + lImage->Data[Offset + 1] = col->g; + lImage->Data[Offset + 2] = col->b; + } + } + } + + // 8-alpha or 6-alpha block? + if (alphas[0] > alphas[1]) { + // 8-alpha block: derive the other six alphas. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7; // bit code 010 + alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7; // bit code 011 + alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7; // bit code 100 + alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7; // bit code 101 + alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7; // bit code 110 + alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7; // bit code 111 + } + else { + // 6-alpha block. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5; // Bit code 010 + alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5; // Bit code 011 + alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5; // Bit code 100 + alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5; // Bit code 101 + alphas[6] = 0x00; // Bit code 110 + alphas[7] = 0xFF; // Bit code 111 + } + + // Note: Have to separate the next two loops, + // it operates on a 6-byte system. + + // First three bytes + //bits = *((ILint*)alphamask); + bits = (alphamask[0]) | (alphamask[1] << 8) | (alphamask[2] << 16); + for (j = 0; j < 2; j++) { + for (i = 0; i < 4; i++) { + // only put pixels out < width or height + if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { + Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp + 3; + lImage->Data[Offset] = alphas[bits & 0x07]; + } + bits >>= 3; + } + } + + // Last three bytes + //bits = *((ILint*)&alphamask[3]); + bits = (alphamask[3]) | (alphamask[4] << 8) | (alphamask[5] << 16); + for (j = 2; j < 4; j++) { + for (i = 0; i < 4; i++) { + // only put pixels out < width or height + if (((x + i) < lImage->Width) && ((y + j) < lImage->Height)) { + Offset = z * lImage->SizeOfPlane + (y + j) * lImage->Bps + (x + i) * lImage->Bpp + 3; + lImage->Data[Offset] = alphas[bits & 0x07]; + } + bits >>= 3; + } + } + } + } + } + + return IL_TRUE; +} + + +ILboolean Decompress3Dc() +{ + int x, y, z, i, j, k, t1, t2; + ILubyte *Temp, *Temp2; + ILubyte XColours[8], YColours[8]; + ILuint bitmask, bitmask2, Offset, CurrOffset; + + if (!CompData) + return IL_FALSE; + + Temp = CompData; + Offset = 0; + for (z = 0; z < Depth; z++) { + for (y = 0; y < Height; y += 4) { + for (x = 0; x < Width; x += 4) { + Temp2 = Temp + 8; + + //Read Y palette + t1 = YColours[0] = Temp[0]; + t2 = YColours[1] = Temp[1]; + Temp += 2; + if (t1 > t2) + for (i = 2; i < 8; ++i) + YColours[i] = t1 + ((t2 - t1)*(i - 1))/7; + else { + for (i = 2; i < 6; ++i) + YColours[i] = t1 + ((t2 - t1)*(i - 1))/5; + YColours[6] = 0; + YColours[7] = 255; + } + + // Read X palette + t1 = XColours[0] = Temp2[0]; + t2 = XColours[1] = Temp2[1]; + Temp2 += 2; + if (t1 > t2) + for (i = 2; i < 8; ++i) + XColours[i] = t1 + ((t2 - t1)*(i - 1))/7; + else { + for (i = 2; i < 6; ++i) + XColours[i] = t1 + ((t2 - t1)*(i - 1))/5; + XColours[6] = 0; + XColours[7] = 255; + } + + //decompress pixel data + CurrOffset = Offset; + for (k = 0; k < 4; k += 2) { + // First three bytes + bitmask = ((ILuint)(Temp[0]) << 0) | ((ILuint)(Temp[1]) << 8) | ((ILuint)(Temp[2]) << 16); + bitmask2 = ((ILuint)(Temp2[0]) << 0) | ((ILuint)(Temp2[1]) << 8) | ((ILuint)(Temp2[2]) << 16); + for (j = 0; j < 2; j++) { + // only put pixels out < height + if ((y + k + j) < Height) { + for (i = 0; i < 4; i++) { + // only put pixels out < width + if (((x + i) < Width)) { + ILint t, tx, ty; + + t1 = CurrOffset + (x + i)*3; + Image->Data[t1 + 1] = ty = YColours[bitmask & 0x07]; + Image->Data[t1 + 0] = tx = XColours[bitmask2 & 0x07]; + + //calculate b (z) component ((r/255)^2 + (g/255)^2 + (b/255)^2 = 1 + t = 127*128 - (tx - 127)*(tx - 128) - (ty - 127)*(ty - 128); + if (t > 0) + Image->Data[t1 + 2] = (ILubyte)(iSqrt(t) + 128); + else + Image->Data[t1 + 2] = 0x7F; + } + bitmask >>= 3; + bitmask2 >>= 3; + } + CurrOffset += Image->Bps; + } + } + Temp += 3; + Temp2 += 3; + } + + //skip bytes that were read via Temp2 + Temp += 8; + } + Offset += Image->Bps*4; + } + } + + return IL_TRUE; +} + + +ILboolean DecompressAti1n() +{ + int x, y, z, i, j, k, t1, t2; + ILubyte *Temp; + ILubyte Colours[8]; + ILuint bitmask, Offset, CurrOffset; + + if (!CompData) + return IL_FALSE; + + Temp = CompData; + Offset = 0; + for (z = 0; z < Depth; z++) { + for (y = 0; y < Height; y += 4) { + for (x = 0; x < Width; x += 4) { + //Read palette + t1 = Colours[0] = Temp[0]; + t2 = Colours[1] = Temp[1]; + Temp += 2; + if (t1 > t2) + for (i = 2; i < 8; ++i) + Colours[i] = t1 + ((t2 - t1)*(i - 1))/7; + else { + for (i = 2; i < 6; ++i) + Colours[i] = t1 + ((t2 - t1)*(i - 1))/5; + Colours[6] = 0; + Colours[7] = 255; + } + + //decompress pixel data + CurrOffset = Offset; + for (k = 0; k < 4; k += 2) { + // First three bytes + bitmask = ((ILuint)(Temp[0]) << 0) | ((ILuint)(Temp[1]) << 8) | ((ILuint)(Temp[2]) << 16); + for (j = 0; j < 2; j++) { + // only put pixels out < height + if ((y + k + j) < Height) { + for (i = 0; i < 4; i++) { + // only put pixels out < width + if (((x + i) < Width)) { + t1 = CurrOffset + (x + i); + Image->Data[t1] = Colours[bitmask & 0x07]; + } + bitmask >>= 3; + } + CurrOffset += Image->Bps; + } + } + Temp += 3; + } + } + Offset += Image->Bps*4; + } + } + + return IL_TRUE; +} + + +//This is nearly exactly the same as DecompressDXT5... +//I have to clean up this file (put common code in +//helper functions etc) +ILboolean DecompressRXGB() +{ + int x, y, z, i, j, k, Select; + ILubyte *Temp; + Color565 *color_0, *color_1; + Color8888 colours[4], *col; + ILuint bitmask, Offset; + ILubyte alphas[8], *alphamask; + ILuint bits; + + if (!CompData) + return IL_FALSE; + + Temp = CompData; + for (z = 0; z < Depth; z++) { + for (y = 0; y < Height; y += 4) { + for (x = 0; x < Width; x += 4) { + if (y >= Height || x >= Width) + break; + alphas[0] = Temp[0]; + alphas[1] = Temp[1]; + alphamask = Temp + 2; + Temp += 8; + color_0 = ((Color565*)Temp); + color_1 = ((Color565*)(Temp+2)); + bitmask = ((ILuint*)Temp)[1]; + Temp += 8; + + colours[0].r = color_0->nRed << 3; + colours[0].g = color_0->nGreen << 2; + colours[0].b = color_0->nBlue << 3; + colours[0].a = 0xFF; + + colours[1].r = color_1->nRed << 3; + colours[1].g = color_1->nGreen << 2; + colours[1].b = color_1->nBlue << 3; + colours[1].a = 0xFF; + + // Four-color block: derive the other two colors. + // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; + colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; + colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; + colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + colours[3].a = 0xFF; + + k = 0; + for (j = 0; j < 4; j++) { + for (i = 0; i < 4; i++, k++) { + + Select = (bitmask & (0x03 << k*2)) >> k*2; + col = &colours[Select]; + + // only put pixels out < width or height + if (((x + i) < Width) && ((y + j) < Height)) { + Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp; + Image->Data[Offset + 0] = col->r; + Image->Data[Offset + 1] = col->g; + Image->Data[Offset + 2] = col->b; + } + } + } + + // 8-alpha or 6-alpha block? + if (alphas[0] > alphas[1]) { + // 8-alpha block: derive the other six alphas. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + alphas[2] = (6 * alphas[0] + 1 * alphas[1] + 3) / 7; // bit code 010 + alphas[3] = (5 * alphas[0] + 2 * alphas[1] + 3) / 7; // bit code 011 + alphas[4] = (4 * alphas[0] + 3 * alphas[1] + 3) / 7; // bit code 100 + alphas[5] = (3 * alphas[0] + 4 * alphas[1] + 3) / 7; // bit code 101 + alphas[6] = (2 * alphas[0] + 5 * alphas[1] + 3) / 7; // bit code 110 + alphas[7] = (1 * alphas[0] + 6 * alphas[1] + 3) / 7; // bit code 111 + } + else { + // 6-alpha block. + // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated. + alphas[2] = (4 * alphas[0] + 1 * alphas[1] + 2) / 5; // Bit code 010 + alphas[3] = (3 * alphas[0] + 2 * alphas[1] + 2) / 5; // Bit code 011 + alphas[4] = (2 * alphas[0] + 3 * alphas[1] + 2) / 5; // Bit code 100 + alphas[5] = (1 * alphas[0] + 4 * alphas[1] + 2) / 5; // Bit code 101 + alphas[6] = 0x00; // Bit code 110 + alphas[7] = 0xFF; // Bit code 111 + } + + // Note: Have to separate the next two loops, + // it operates on a 6-byte system. + // First three bytes + bits = *((ILint*)alphamask); + for (j = 0; j < 2; j++) { + for (i = 0; i < 4; i++) { + // only put pixels out < width or height + if (((x + i) < Width) && ((y + j) < Height)) { + Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 0; + Image->Data[Offset] = alphas[bits & 0x07]; + } + bits >>= 3; + } + } + + // Last three bytes + bits = *((ILint*)&alphamask[3]); + for (j = 2; j < 4; j++) { + for (i = 0; i < 4; i++) { + // only put pixels out < width or height + if (((x + i) < Width) && ((y + j) < Height)) { + Offset = z * Image->SizeOfPlane + (y + j) * Image->Bps + (x + i) * Image->Bpp + 0; + Image->Data[Offset] = alphas[bits & 0x07]; + } + bits >>= 3; + } + } + } + } + } + + return IL_TRUE; +} + + +//Taken from OpenEXR +unsigned int +halfToFloat (unsigned short y) +{ + int s = (y >> 15) & 0x00000001; + int e = (y >> 10) & 0x0000001f; + int m = y & 0x000003ff; + + if (e == 0) + { + if (m == 0) + { + // + // Plus or minus zero + // + return s << 31; + } + else + { + // + // Denormalized number -- renormalize it + // + while (!(m & 0x00000400)) + { + m <<= 1; + e -= 1; + } + + e += 1; + m &= ~0x00000400; + } + } + else if (e == 31) + { + if (m == 0) + { + // + // Positive or negative infinity + // + return (s << 31) | 0x7f800000; + } + else + { + // + // Nan -- preserve sign and significand bits + // + return (s << 31) | 0x7f800000 | (m << 13); + } + } + + // + // Normalized number + // + e = e + (127 - 15); + m = m << 13; + + // + // Assemble s, e and m. + // + return (s << 31) | (e << 23) | m; +} + + +ILboolean iConvFloat16ToFloat32(ILuint* dest, ILushort* src, ILuint size) +{ + ILuint i; + for (i = 0; i < size; ++i, ++dest, ++src) { + //float: 1 sign bit, 8 exponent bits, 23 mantissa bits + //half: 1 sign bit, 5 exponent bits, 10 mantissa bits + *dest = halfToFloat(*src); + } + + return IL_TRUE; +} + + +// Same as iConvFloat16ToFloat32, but we have to set the blue channel to 1.0f. +// The destination format is RGB, and the source is R16G16 (little endian). +ILboolean iConvG16R16ToFloat32(ILuint* dest, ILushort* src, ILuint size) +{ + ILuint i; + for (i = 0; i < size; i += 3) { + //float: 1 sign bit, 8 exponent bits, 23 mantissa bits + //half: 1 sign bit, 5 exponent bits, 10 mantissa bits + *dest++ = halfToFloat(*src++); + *dest++ = halfToFloat(*src++); + *((ILfloat*)dest++) = 1.0f; + } + + return IL_TRUE; +} + + +// Same as iConvFloat16ToFloat32, but we have to set the green and blue channels +// to 1.0f. The destination format is RGB, and the source is R16. +ILboolean iConvR16ToFloat32(ILuint* dest, ILushort* src, ILuint size) +{ + ILuint i; + for (i = 0; i < size; i += 3) { + //float: 1 sign bit, 8 exponent bits, 23 mantissa bits + //half: 1 sign bit, 5 exponent bits, 10 mantissa bits + *dest++ = halfToFloat(*src++); + *((ILfloat*)dest++) = 1.0f; + *((ILfloat*)dest++) = 1.0f; + } + + return IL_TRUE; +} + + +ILboolean DecompressFloat(ILuint lCompFormat) +{ + ILuint i, j, Size; + + switch (lCompFormat) + { + case PF_R32F: // Red float, green = blue = max + Size = Image->Width * Image->Height * Image->Depth * 3; + for (i = 0, j = 0; i < Size; i += 3, j++) { + ((ILfloat*)Image->Data)[i] = ((ILfloat*)CompData)[j]; + ((ILfloat*)Image->Data)[i+1] = 1.0f; + ((ILfloat*)Image->Data)[i+2] = 1.0f; + } + return IL_TRUE; + case PF_A32B32G32R32F: // Direct copy of float RGBA data + memcpy(Image->Data, CompData, Image->SizeOfData); + return IL_TRUE; + case PF_G32R32F: // Red float, green float, blue = max + Size = Image->Width * Image->Height * Image->Depth * 3; + for (i = 0, j = 0; i < Size; i += 3, j += 2) { + ((ILfloat*)Image->Data)[i] = ((ILfloat*)CompData)[j]; + ((ILfloat*)Image->Data)[i+1] = ((ILfloat*)CompData)[j+1]; + ((ILfloat*)Image->Data)[i+2] = 1.0f; + } + return IL_TRUE; + case PF_R16F: // Red float, green = blue = max + return iConvR16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, + Image->Width * Image->Height * Image->Depth * Image->Bpp); + case PF_A16B16G16R16F: // Just convert from half to float. + return iConvFloat16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, + Image->Width * Image->Height * Image->Depth * Image->Bpp); + case PF_G16R16F: // Convert from half to float, set blue = max. + return iConvG16R16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, + Image->Width * Image->Height * Image->Depth * Image->Bpp); + default: + return IL_FALSE; + } +} + + +void CorrectPreMult() +{ + ILuint i; + + for (i = 0; i < Image->SizeOfData; i += 4) { + if (Image->Data[i+3] != 0) { // Cannot divide by 0. + Image->Data[i] = (ILubyte)(((ILuint)Image->Data[i] << 8) / Image->Data[i+3]); + Image->Data[i+1] = (ILubyte)(((ILuint)Image->Data[i+1] << 8) / Image->Data[i+3]); + Image->Data[i+2] = (ILubyte)(((ILuint)Image->Data[i+2] << 8) / Image->Data[i+3]); + } + } + + return; +} + + +ILboolean DecompressARGB(ILuint CompFormat) +{ + ILuint ReadI = 0, TempBpp, i; + ILuint RedL, RedR; + ILuint GreenL, GreenR; + ILuint BlueL, BlueR; + ILuint AlphaL, AlphaR; + ILubyte *Temp; + + if (Has16BitComponents) + return DecompressARGB16(CompFormat); + + if (!CompData) + return IL_FALSE; + + if (CompFormat == PF_LUMINANCE && Head.RGBBitCount == 16 && Head.RBitMask == 0xFFFF) { //HACK + memcpy(Image->Data, CompData, Image->SizeOfData); + return IL_TRUE; + } + + GetBitsFromMask(Head.RBitMask, &RedL, &RedR); + GetBitsFromMask(Head.GBitMask, &GreenL, &GreenR); + GetBitsFromMask(Head.BBitMask, &BlueL, &BlueR); + GetBitsFromMask(Head.RGBAlphaBitMask, &AlphaL, &AlphaR); + Temp = CompData; + TempBpp = Head.RGBBitCount / 8; + + for (i = 0; i < Image->SizeOfData; i += Image->Bpp) { + + //@TODO: This is SLOOOW... + //but the old version crashed in release build under + //winxp (and xp is right to stop this code - I always + //wondered that it worked the old way at all) + if (Image->SizeOfData - i < 4) { //less than 4 byte to write? + if (TempBpp == 3) { //this branch is extra-SLOOOW + ReadI = + *Temp + | ((*(Temp + 1)) << 8) + | ((*(Temp + 2)) << 16); + } + else if (TempBpp == 1) + ReadI = *((ILubyte*)Temp); + else if (TempBpp == 2) + ReadI = Temp[0] | (Temp[1] << 8); + } + else + ReadI = Temp[0] | (Temp[1] << 8) | (Temp[2] << 16) | (Temp[3] << 24); + Temp += TempBpp; + + Image->Data[i] = ((ReadI & Head.RBitMask) >> RedR) << RedL; + + if (Image->Bpp >= 3) { + Image->Data[i+1] = ((ReadI & Head.GBitMask) >> GreenR) << GreenL; + Image->Data[i+2] = ((ReadI & Head.BBitMask) >> BlueR) << BlueL; + + if (Image->Bpp == 4) { + Image->Data[i+3] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; + if (AlphaL >= 7) { + Image->Data[i+3] = Image->Data[i+3] ? 0xFF : 0x00; + } + else if (AlphaL >= 4) { + Image->Data[i+3] = Image->Data[i+3] | (Image->Data[i+3] >> 4); + } + } + } + else if (Image->Bpp == 2) { + Image->Data[i+1] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; + if (AlphaL >= 7) { + Image->Data[i+1] = Image->Data[i+1] ? 0xFF : 0x00; + } + else if (AlphaL >= 4) { + Image->Data[i+1] = Image->Data[i+1] | (Image->Data[i+3] >> 4); + } + } + } + + return IL_TRUE; +} + + +// This function simply counts how many contiguous bits are in the mask. +ILuint CountBitsFromMask(ILuint Mask) +{ + ILuint i, TestBit = 0x01, Count = 0; + ILboolean FoundBit = IL_FALSE; + + for (i = 0; i < 32; i++, TestBit <<= 1) { + if (Mask & TestBit) { + if (!FoundBit) + FoundBit = IL_TRUE; + Count++; + } + else if (FoundBit) + return Count; + } + + return Count; +} + + +// Same as DecompressARGB, but it works on images with more than 8 bits +// per channel, such as a2r10g10b10 and a2b10g10r10. +ILboolean DecompressARGB16(ILuint CompFormat) +{ + ILuint ReadI = 0, TempBpp, i; + ILuint RedL, RedR; + ILuint GreenL, GreenR; + ILuint BlueL, BlueR; + ILuint AlphaL, AlphaR; + ILuint RedPad, GreenPad, BluePad, AlphaPad; + ILubyte *Temp; + + if (!CompData) + return IL_FALSE; + + GetBitsFromMask(Head.RBitMask, &RedL, &RedR); + GetBitsFromMask(Head.GBitMask, &GreenL, &GreenR); + GetBitsFromMask(Head.BBitMask, &BlueL, &BlueR); + GetBitsFromMask(Head.RGBAlphaBitMask, &AlphaL, &AlphaR); + RedPad = 16 - CountBitsFromMask(Head.RBitMask); + GreenPad = 16 - CountBitsFromMask(Head.GBitMask); + BluePad = 16 - CountBitsFromMask(Head.BBitMask); + AlphaPad = 16 - CountBitsFromMask(Head.RGBAlphaBitMask); + + RedL = RedL + RedPad; + GreenL = GreenL + GreenPad; + BlueL = BlueL + BluePad; + AlphaL = AlphaL + AlphaPad; + + Temp = CompData; + TempBpp = Head.RGBBitCount / 8; + + for (i = 0; i < Image->SizeOfData / 2; i += Image->Bpp) { + + //@TODO: This is SLOOOW... + //but the old version crashed in release build under + //winxp (and xp is right to stop this code - I always + //wondered that it worked the old way at all) + if (Image->SizeOfData - i < 4) { //less than 4 byte to write? + if (TempBpp == 3) { //this branch is extra-SLOOOW + ReadI = + *Temp + | ((*(Temp + 1)) << 8) + | ((*(Temp + 2)) << 16); + } + else if (TempBpp == 1) + ReadI = *((ILubyte*)Temp); + else if (TempBpp == 2) + ReadI = Temp[0] | (Temp[1] << 8); + } + else + ReadI = Temp[0] | (Temp[1] << 8) | (Temp[2] << 16) | (Temp[3] << 24); + Temp += TempBpp; + + ((ILushort*)Image->Data)[i+2] = ((ReadI & Head.RBitMask) >> RedR) << RedL; + + if (Image->Bpp >= 3) { + ((ILushort*)Image->Data)[i+1] = ((ReadI & Head.GBitMask) >> GreenR) << GreenL; + ((ILushort*)Image->Data)[i] = ((ReadI & Head.BBitMask) >> BlueR) << BlueL; + + if (Image->Bpp == 4) { + ((ILushort*)Image->Data)[i+3] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; + if (AlphaL >= 7) { + ((ILushort*)Image->Data)[i+3] = ((ILushort*)Image->Data)[i+3] ? 0xFF : 0x00; + } + else if (AlphaL >= 4) { + ((ILushort*)Image->Data)[i+3] = ((ILushort*)Image->Data)[i+3] | (((ILushort*)Image->Data)[i+3] >> 4); + } + } + } + else if (Image->Bpp == 2) { + ((ILushort*)Image->Data)[i+1] = ((ReadI & Head.RGBAlphaBitMask) >> AlphaR) << AlphaL; + if (AlphaL >= 7) { + ((ILushort*)Image->Data)[i+1] = ((ILushort*)Image->Data)[i+1] ? 0xFF : 0x00; + } + else if (AlphaL >= 4) { + ((ILushort*)Image->Data)[i+1] = ((ILushort*)Image->Data)[i+1] | (Image->Data[i+3] >> 4); + } + } + } + + return IL_TRUE; +} + + +// @TODO: Look at using the BSF/BSR operands for inline ASM here. +void GetBitsFromMask(ILuint Mask, ILuint *ShiftLeft, ILuint *ShiftRight) +{ + ILuint Temp, i; + + if (Mask == 0) { + *ShiftLeft = *ShiftRight = 0; + return; + } + + Temp = Mask; + for (i = 0; i < 32; i++, Temp >>= 1) { + if (Temp & 1) + break; + } + *ShiftRight = i; + + // Temp is preserved, so use it again: + for (i = 0; i < 8; i++, Temp >>= 1) { + if (!(Temp & 1)) + break; + } + *ShiftLeft = 8 - i; + + return; +} + + +// +// +// DXT extension code +// +// +ILubyte* ILAPIENTRY ilGetDxtcData() +{ + if (iCurImage == NULL) { + ilSetError(IL_INTERNAL_ERROR); + return NULL; + } + return iCurImage->DxtcData; +} + +void ilFreeSurfaceDxtcData() +{ + if (iCurImage != NULL && iCurImage->DxtcData != NULL) { + ifree(iCurImage->DxtcData); + iCurImage->DxtcData = NULL; + iCurImage->DxtcSize = 0; + iCurImage->DxtcFormat = IL_DXT_NO_COMP; + } +} + +void ilFreeImageDxtcData() +{ + ILint i, j; + ILuint ImgID = ilGetInteger(IL_CUR_IMAGE); + ILint ImgCount = ilGetInteger(IL_NUM_IMAGES); + ILint MipCount; + + for(i = 0; i <= ImgCount; ++i) { + ilBindImage(ImgID); + ilActiveImage(i); + + MipCount = ilGetInteger(IL_NUM_MIPMAPS); + for(j = 0; j <= MipCount; ++j) { + ilBindImage(ImgID); + ilActiveImage(i); + ilActiveMipmap(j); + + ilFreeSurfaceDxtcData(); + } + } +} + +/* + * This assumes DxtcData, DxtcFormat, width, height, and depth are valid + */ +ILAPI ILboolean ILAPIENTRY ilDxtcDataToSurface() +{ + ILuint CompFormat; + + if (iCurImage == NULL || iCurImage->DxtcData == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (!(iCurImage->DxtcFormat == IL_DXT1 || iCurImage->DxtcFormat == IL_DXT3 + || iCurImage->DxtcFormat == IL_DXT5)) { + ilSetError(IL_INVALID_PARAM); //TODO + return IL_FALSE; + } + + //@TODO: is this right for all dxt formats? works for + // DXT1, 3, 5 + iCurImage->Bpp = 4; + iCurImage->Bpc = 1; + iCurImage->Bps = iCurImage->Width*iCurImage->Bpp*iCurImage->Bpc; + iCurImage->SizeOfPlane = iCurImage->Height*iCurImage->Bps; + iCurImage->Format = IL_RGBA; + iCurImage->Type = IL_UNSIGNED_BYTE; + + if (iCurImage->SizeOfData != iCurImage->SizeOfPlane*iCurImage->Depth) { + iCurImage->SizeOfData = iCurImage->Depth*iCurImage->SizeOfPlane; + if (iCurImage->Data != NULL) + ifree(iCurImage->Data); + iCurImage->Data = NULL; + } + + if (iCurImage->Data == NULL) { + iCurImage->Data = ialloc(iCurImage->SizeOfData); + } + + Image = iCurImage; + Width = iCurImage->Width; + Height = iCurImage->Height; + Depth = iCurImage->Depth; + switch(iCurImage->DxtcFormat) + { + case IL_DXT1: CompFormat = PF_DXT1; break; + case IL_DXT3: CompFormat = PF_DXT3; break; + case IL_DXT5: CompFormat = PF_DXT5; break; + } + CompData = iCurImage->DxtcData; + DdsDecompress(CompFormat); //globals suck...fix this + + //@TODO: origin should be set in Decompress()... + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + return ilFixCur(); +} + + +ILAPI ILboolean ILAPIENTRY ilDxtcDataToImage() +{ + ILint i, j; + ILuint ImgID = ilGetInteger(IL_CUR_IMAGE); + ILint ImgCount = ilGetInteger(IL_NUM_IMAGES); + ILint MipCount; + ILboolean ret = IL_TRUE; + + for(i = 0; i <= ImgCount; ++i) { + ilBindImage(ImgID); + ilActiveImage(i); + + MipCount = ilGetInteger(IL_NUM_MIPMAPS); + for(j = 0; j <= MipCount; ++j) { + ilBindImage(ImgID); + ilActiveImage(i); + ilActiveMipmap(j); + + if (!ilDxtcDataToSurface()) + ret = IL_FALSE; + } + } + ilBindImage(ImgID); + + return ret; +} + + +ILAPI ILboolean ILAPIENTRY ilSurfaceToDxtcData(ILenum Format) +{ + ILuint Size; + void* Data; + ilFreeSurfaceDxtcData(); + + Size = ilGetDXTCData(NULL, 0, Format); + if (Size == 0) { + return IL_FALSE; + } + + Data = ialloc(Size); + + if (Data == NULL) + return IL_FALSE; + + ilGetDXTCData(Data, Size, Format); + + //These have to be after the call to ilGetDXTCData() + iCurImage->DxtcData = Data; + iCurImage->DxtcFormat = Format; + iCurImage->DxtcSize = Size; + + return IL_TRUE; +} + + +ILAPI ILboolean ILAPIENTRY ilImageToDxtcData(ILenum Format) +{ + ILint i, j; + ILuint ImgID = ilGetInteger(IL_CUR_IMAGE); + ILint ImgCount = ilGetInteger(IL_NUM_IMAGES); + ILint MipCount; + ILboolean ret = IL_TRUE; + + for (i = 0; i <= ImgCount; ++i) { + ilBindImage(ImgID); + ilActiveImage(i); + + MipCount = ilGetInteger(IL_NUM_MIPMAPS); + for(j = 0; j <= MipCount; ++j) { + ilBindImage(ImgID); + ilActiveImage(i); + ilActiveMipmap(j); + + if (!ilSurfaceToDxtcData(Format)) + ret = IL_FALSE; + } + } + + return ret; +} + + +//works like ilTexImage(), ie. destroys mipmaps etc (which sucks, but +//is consistent. There should be a ilTexSurface() and ilTexSurfaceDxtc() +//functions as well, but for now this is sufficient) +ILAPI ILboolean ILAPIENTRY ilTexImageDxtc(ILint w, ILint h, ILint d, ILenum DxtFormat, const ILubyte* data) +{ + ILimage* Image = iCurImage; + + ILint xBlocks, yBlocks, BlockSize, LineSize, DataSize; + + + //The next few lines are copied from ilTexImage() and ilInitImage() - + //should be factored in more reusable functions... + if (Image == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + //// + + // Not sure if we should be getting rid of the palette... + if (Image->Pal.Palette && Image->Pal.PalSize && Image->Pal.PalType != IL_PAL_NONE) { + ifree(Image->Pal.Palette); + } + + // These are set NULL later by the memset call. + ilCloseImage(Image->Mipmaps); + ilCloseImage(Image->Next); + ilCloseImage(Image->Faces); + ilCloseImage(Image->Layers); + + if (Image->AnimList) ifree(Image->AnimList); + if (Image->Profile) ifree(Image->Profile); + if (Image->DxtcData) ifree(Image->DxtcData); + if (Image->Data) ifree(Image->Data); + + + //// + + memset(Image, 0, sizeof(ILimage)); + Image->Width = w; + Image->Height = h; + Image->Depth = d; + + //TODO: What about origin with dxtc data? + Image->Origin = IL_ORIGIN_LOWER_LEFT; + Image->Pal.PalType = IL_PAL_NONE; + + // Allocate DXT data buffer + xBlocks = (w + 3)/4; + yBlocks = (h + 3)/4; + if (DxtFormat == IL_DXT1) + BlockSize = 8; + else + BlockSize = 16; + + LineSize = xBlocks * BlockSize; + + DataSize = yBlocks * LineSize * d; + + Image->DxtcFormat = DxtFormat; + Image->DxtcSize = DataSize; + Image->DxtcData = ialloc(DataSize); + + if (Image->DxtcData == NULL) { + return IL_FALSE; + } + + if (data != NULL) + memcpy(Image->DxtcData, data, DataSize); + + return IL_TRUE; +} + + +/* ------------------------------------------------------------------- */ + +void iFlipColorBlock(ILubyte *data) +{ + ILubyte tmp; + + tmp = data[4]; + data[4] = data[7]; + data[7] = tmp; + + tmp = data[5]; + data[5] = data[6]; + data[6] = tmp; +} + +void iFlipSimpleAlphaBlock(ILushort *data) +{ + ILushort tmp; + + tmp = data[0]; + data[0] = data[3]; + data[3] = tmp; + + tmp = data[1]; + data[1] = data[2]; + data[2] = tmp; +} + +void iComplexAlphaHelper(ILubyte* Data) +{ + ILushort tmp[2]; + + //one 4 pixel line is 12 bit, copy each line into + //a ushort, swap them and copy back + tmp[0] = (Data[0] | (Data[1] << 8)) & 0xfff; + tmp[1] = ((Data[1] >> 4) | (Data[2] << 4)) & 0xfff; + + Data[0] = (ILubyte)tmp[1]; + Data[1] = (tmp[1] >> 8) | (tmp[0] << 4); + Data[2] = tmp[0] >> 4; +} + +void iFlipComplexAlphaBlock(ILubyte *Data) +{ + ILubyte tmp[3]; + Data += 2; //Skip 'palette' + + //swap upper two rows with lower two rows + memcpy(tmp, Data, 3); + memcpy(Data, Data + 3, 3); + memcpy(Data + 3, tmp, 3); + + //swap 1st with 2nd row, 3rd with 4th + iComplexAlphaHelper(Data); + iComplexAlphaHelper(Data + 3); +} + +void iFlipDxt1(ILubyte* data, ILuint count) +{ + ILuint i; + + for (i = 0; i < count; ++i) { + iFlipColorBlock(data); + data += 8; //advance to next block + } +} + +void iFlipDxt3(ILubyte* data, ILuint count) +{ + ILuint i; + for (i = 0; i < count; ++i) { + iFlipSimpleAlphaBlock((ILushort*)data); + iFlipColorBlock(data + 8); + data += 16; //advance to next block + } +} + +void iFlipDxt5(ILubyte* data, ILuint count) +{ + ILuint i; + for (i = 0; i < count; ++i) { + iFlipComplexAlphaBlock(data); + iFlipColorBlock(data + 8); + data += 16; //advance to next block + } +} + +void iFlip3dc(ILubyte* data, ILuint count) +{ + ILuint i; + for (i = 0; i < count; ++i) { + iFlipComplexAlphaBlock(data); + iFlipComplexAlphaBlock(data + 8); + data += 16; //advance to next block + } +} + + +ILAPI void ILAPIENTRY ilFlipSurfaceDxtcData() +{ + ILuint y, z; + ILuint BlockSize, LineSize; + ILubyte *Temp, *Runner, *Top, *Bottom; + ILuint numXBlocks, numYBlocks; + void (*FlipBlocks)(ILubyte* data, ILuint count); + + if (iCurImage == NULL || iCurImage->DxtcData == NULL) { + ilSetError(IL_INVALID_PARAM); + return; + } + + numXBlocks = (iCurImage->Width + 3)/4; + numYBlocks = (iCurImage->Height + 3)/4; + + switch (iCurImage->DxtcFormat) + { + case IL_DXT1: + BlockSize = 8; + FlipBlocks = iFlipDxt1; + break; + case IL_DXT2: + case IL_DXT3: + BlockSize = 16; + FlipBlocks = iFlipDxt3; + break; + case IL_DXT4: + case IL_DXT5: + case IL_RXGB: + BlockSize = 16; + FlipBlocks = iFlipDxt5; + break; + case IL_3DC: + BlockSize = 16; + FlipBlocks = iFlip3dc; + break; + default: + ilSetError(IL_INVALID_PARAM); + return; + } + + LineSize = numXBlocks * BlockSize; + Temp = ialloc(LineSize); + + if (Temp == NULL) + return; + + Runner = iCurImage->DxtcData; + for (z = 0; z < iCurImage->Depth; ++z) { + Top = Runner; + Bottom = Runner + (numYBlocks - 1)*LineSize; + + for (y = 0; y < numYBlocks/2; ++y) { + //swap block row + memcpy(Temp, Top, LineSize); + memcpy(Top, Bottom, LineSize); + memcpy(Bottom, Temp, LineSize); + + + //swap blocks + FlipBlocks(Top, numXBlocks); + FlipBlocks(Bottom, numXBlocks); + + Top += LineSize; + Bottom -= LineSize; + } + + //middle line + if (numYBlocks % 2 != 0) + FlipBlocks(Top, numXBlocks); + + Runner += LineSize * numYBlocks; + } + + ifree(Temp); +} + +/**********************************************************************/ + +void iInvertDxt3Alpha(ILubyte *data) +{ + ILint i; + + for (i = 0; i < 8; ++i) { + /* + ILubyte b, t1, t2; + b = data[i]; + + t1 = b & 0xf; + t1 = 15 - t1; + t2 = b >> 4; + t2 = 15 - t2; + + data[i] = (t2 << 4) | t1; + */ + //simpler: + data[i] = ~data[i]; + } +} + +void iInvertDxt5Alpha(ILubyte *data) +{ + ILubyte a0, a1; + ILint i, j; + const ILubyte map1[] = { 1, 0, 7, 6, 5, 4, 3, 2 }; + const ILubyte map2[] = { 1, 0, 5, 4, 3, 2, 7, 6 }; + + + a0 = data[0]; + a1 = data[1]; + + //a0 > a1 <=> 255 - a0 < 255 - a1. Because of this, + //a1 and a2 have to be swapped, and the indices + //have to be changed as well. + + //invert and swap alpha + data[0] = 255 - a1; + data[1] = 255 - a0; + data += 2; + + //fix indices + for (i = 0; i < 6; i += 3) { + ILuint in = data[i] | (data[i+1] << 8) | (data[i+2] << 16); + ILuint out = 0; + + for (j = 0; j < 24; j += 3) { + ILubyte b = (in >> j) & 0x7; + + if (a0 > a1) + b = map1[b]; + else + b = map2[b]; + + out |= b << j; + } + + data[i] = out; + data[i+1] = out >> 8; + data[i+2] = out >> 16; + } +} + + +ILAPI ILboolean ILAPIENTRY ilInvertSurfaceDxtcDataAlpha() +{ + ILint i; + ILuint BlockSize; + ILubyte *Runner; + ILint numXBlocks, numYBlocks, numBlocks; + void (*InvertAlpha)(ILubyte* data); + + if (iCurImage == NULL || iCurImage->DxtcData == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + numXBlocks = (iCurImage->Width + 3)/4; + numYBlocks = (iCurImage->Height + 3)/4; + numBlocks = numXBlocks*numYBlocks*iCurImage->Depth; + BlockSize = 16; + + switch (iCurImage->DxtcFormat) + { + case IL_DXT3: + InvertAlpha = iInvertDxt3Alpha; + break; + case IL_DXT5: + InvertAlpha = iInvertDxt5Alpha; + break; + default: + //DXT2/4 are not supported yet because nobody + //uses them anyway and I would have to change + //the color blocks as well... + //DXT1 is not supported because DXT1 alpha is + //seldom used and it's not easily invertable. + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + Runner = iCurImage->DxtcData; + for (i = 0; i < numBlocks; ++i, Runner += BlockSize) { + InvertAlpha(Runner); + } + + return IL_TRUE; +} + + + + +#endif//IL_NO_DDS diff --git a/DevIL/src-IL/src/il_devil.c b/DevIL/src-IL/src/il_devil.c deleted file mode 100644 index fc2f7b7e..00000000 --- a/DevIL/src-IL/src/il_devil.c +++ /dev/null @@ -1,1068 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/01/2009 -// -// Filename: src-IL/src/il_devil.c -// -// Description: Functions for working with the ILimage's and the current image -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include -#include - - -ILAPI ILboolean ILAPIENTRY ilInitImage(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) -{ - ILubyte BpcType = ilGetBpcType(Type); - if (BpcType == 0) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - memset(Image, 0, sizeof(ILimage)); - - //// - if (Width == 0) Width = 1; - if (Height == 0) Height = 1; - if (Depth == 0) Depth = 1; - Image->Width = Width; - Image->Height = Height; - Image->Depth = Depth; - Image->Bpp = Bpp; - Image->Bpc = BpcType; - Image->Bps = Width * Bpp * Image->Bpc; - Image->SizeOfPlane = Image->Bps * Height; - Image->SizeOfData = Image->SizeOfPlane * Depth; - Image->Format = Format; - Image->Type = Type; - Image->Origin = IL_ORIGIN_LOWER_LEFT; - Image->Pal.PalType = IL_PAL_NONE; - Image->DxtcFormat = IL_DXT_NO_COMP; - Image->DxtcData = NULL; - - Image->Data = (ILubyte*)ialloc(Image->SizeOfData); - if (Image->Data == NULL) { - return IL_FALSE; - } - - if (Data != NULL) { - memcpy(Image->Data, Data, Image->SizeOfData); - } - - return IL_TRUE; -} - - - -// Creates a new ILimage based on the specifications given -ILAPI ILimage* ILAPIENTRY ilNewImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc) -{ - ILimage *Image; - - if (Bpp == 0 || Bpp > 4) { - return NULL; - } - - Image = (ILimage*)ialloc(sizeof(ILimage)); - if (Image == NULL) { - return NULL; - } - - if (!ilInitImage(Image, Width, Height, Depth, Bpp, ilGetFormatBpp(Bpp), ilGetTypeBpc(Bpc), NULL)) { - if (Image->Data != NULL) { - ifree(Image->Data); - } - ifree(Image); - return NULL; - } - - return Image; -} - - -// Same as above but allows specification of Format and Type -ILAPI ILimage* ILAPIENTRY ilNewImageFull(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) -{ - ILimage *Image; - - if (Bpp == 0 || Bpp > 4) { - return NULL; - } - - Image = (ILimage*)ialloc(sizeof(ILimage)); - if (Image == NULL) { - return NULL; - } - - if (!ilInitImage(Image, Width, Height, Depth, Bpp, Format, Type, Data)) { - if (Image->Data != NULL) { - ifree(Image->Data); - } - ifree(Image); - return NULL; - } - - return Image; -} - - -//! Changes the current bound image to use these new dimensions (current data is destroyed). -/*! \param Width Specifies the new image width. This cannot be 0. - \param Height Specifies the new image height. This cannot be 0. - \param Depth Specifies the new image depth. This cannot be 0. - \param Bpp Number of channels (ex. 3 for RGB) - \param Format Enum of the desired format. Any format values are accepted. - \param Type Enum of the desired type. Any type values are accepted. - \param Data Specifies data that should be copied to the new image. If this parameter is NULL, no data is copied, and the new image data consists of undefined values. - \exception IL_ILLEGAL_OPERATION No currently bound image. - \exception IL_INVALID_PARAM One of the parameters is incorrect, such as one of the dimensions being 0. - \exception IL_OUT_OF_MEMORY Could not allocate enough memory. - \return Boolean value of failure or success*/ -ILboolean ILAPIENTRY ilTexImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) -{ - return ilTexImage_(iCurImage, Width, Height, Depth, Bpp, Format, Type, Data); -} - - -// Internal version of ilTexImage. -ILAPI ILboolean ILAPIENTRY ilTexImage_(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) -{ - if (Image == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - //// - - // Not sure if we should be getting rid of the palette... - if (Image->Pal.Palette && Image->Pal.PalSize && Image->Pal.PalType != IL_PAL_NONE) { - ifree(Image->Pal.Palette); - } - - ilCloseImage(Image->Mipmaps); - ilCloseImage(Image->Next); - ilCloseImage(Image->Faces); - ilCloseImage(Image->Layers); - - if (Image->AnimList) ifree(Image->AnimList); - if (Image->Profile) ifree(Image->Profile); - if (Image->DxtcData) ifree(Image->DxtcData); - if (Image->Data) ifree(Image->Data); - - //// - - //@TODO: Also check against format? - /*if (Width == 0 || Height == 0 || Depth == 0 || Bpp == 0) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - }*/ - - return ilInitImage(Image, Width, Height, Depth, Bpp, Format, Type, Data); -} - - -//! Uploads Data of the same size to replace the current image's data. -/*! \param Data New image data to update the currently bound image - \exception IL_ILLEGAL_OPERATION No currently bound image - \exception IL_INVALID_PARAM Data was NULL. - \return Boolean value of failure or success -*/ -ILboolean ILAPIENTRY ilSetData(void *Data) -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - return ilTexSubImage_(iCurImage, Data); -} - - -// Internal version of ilTexSubImage. -ILAPI ILboolean ILAPIENTRY ilTexSubImage_(ILimage *Image, void *Data) -{ - if (Image == NULL || Data == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - if (!Image->Data) { - Image->Data = (ILubyte*)ialloc(Image->SizeOfData); - if (Image->Data == NULL) - return IL_FALSE; - } - memcpy(Image->Data, Data, Image->SizeOfData); - return IL_TRUE; -} - - -//! Returns a pointer to the current image's data. -/*! The pointer to the image data returned by this function is only valid until any - operations are done on the image. After any operations, this function should be - called again. The pointer can be cast to other types for images that have more - than one byte per channel for easier access to data. - \exception IL_ILLEGAL_OPERATION No currently bound image - \return ILubyte pointer to image data.*/ -ILubyte* ILAPIENTRY ilGetData(void) -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - - return iCurImage->Data; -} - - -//! Returns a pointer to the current image's palette data. -/*! The pointer to the image palette data returned by this function is only valid until - any operations are done on the image. After any operations, this function should be - called again. - \exception IL_ILLEGAL_OPERATION No currently bound image - \return ILubyte pointer to image palette data.*/ -ILubyte* ILAPIENTRY ilGetPalette(void) -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - - return iCurImage->Pal.Palette; -} - - -//ILfloat ClearRed = 0.0f, ClearGreen = 0.0f, ClearBlue = 0.0f, ClearAlpha = 0.0f; - -// Changed to the colour of the Universe -// (http://www.newscientist.com/news/news.jsp?id=ns99991775) -// *(http://www.space.com/scienceastronomy/universe_color_020308.html)* -//ILfloat ClearRed = 0.269f, ClearGreen = 0.388f, ClearBlue = 0.342f, ClearAlpha = 0.0f; -static ILfloat ClearRed = 1.0f; -static ILfloat ClearGreen = 0.972549f; -static ILfloat ClearBlue = 0.90588f; -static ILfloat ClearAlpha = 0.0f; -static ILfloat ClearLum = 1.0f; - -void ILAPIENTRY ilClearColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha) -{ - // Clamp to 0.0f - 1.0f. - ClearRed = Red < 0.0f ? 0.0f : (Red > 1.0f ? 1.0f : Red); - ClearGreen = Green < 0.0f ? 0.0f : (Green > 1.0f ? 1.0f : Green); - ClearBlue = Blue < 0.0f ? 0.0f : (Blue > 1.0f ? 1.0f : Blue); - ClearAlpha = Alpha < 0.0f ? 0.0f : (Alpha > 1.0f ? 1.0f : Alpha); - - if ((Red == Green) && (Red == Blue) && (Green == Blue)) { - ClearLum = Red < 0.0f ? 0.0f : (Red > 1.0f ? 1.0f : Red); - } - else { - ClearLum = 0.212671f * ClearRed + 0.715160f * ClearGreen + 0.072169f * ClearBlue; - ClearLum = ClearLum < 0.0f ? 0.0f : (ClearLum > 1.0f ? 1.0f : ClearLum); - } - - return; -} - - -ILAPI void ILAPIENTRY ilGetClear(void *Colours, ILenum Format, ILenum Type) -{ - ILubyte *BytePtr; - ILushort *ShortPtr; - ILuint *IntPtr; - ILfloat *FloatPtr; - ILdouble *DblPtr; - - switch (Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - BytePtr = (ILubyte*)Colours; - switch (Format) - { - case IL_RGB: - BytePtr[0] = (ILubyte)(ClearRed * UCHAR_MAX); - BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); - BytePtr[2] = (ILubyte)(ClearBlue * UCHAR_MAX); - break; - - case IL_RGBA: - BytePtr[0] = (ILubyte)(ClearRed * UCHAR_MAX); - BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); - BytePtr[2] = (ILubyte)(ClearBlue * UCHAR_MAX); - BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX); - break; - - case IL_BGR: - BytePtr[2] = (ILubyte)(ClearRed * UCHAR_MAX); - BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); - BytePtr[0] = (ILubyte)(ClearBlue * UCHAR_MAX); - BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX); - break; - - case IL_BGRA: - BytePtr[2] = (ILubyte)(ClearRed * UCHAR_MAX); - BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); - BytePtr[0] = (ILubyte)(ClearBlue * UCHAR_MAX); - BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX); - break; - - case IL_LUMINANCE: - BytePtr[0] = (ILubyte)(ClearAlpha * UCHAR_MAX); - break; - - case IL_LUMINANCE_ALPHA: - BytePtr[0] = (ILubyte)(ClearLum * UCHAR_MAX); - BytePtr[1] = (ILubyte)(ClearAlpha * UCHAR_MAX); - - case IL_COLOUR_INDEX: - BytePtr[0] = (ILubyte)(ClearAlpha * UCHAR_MAX); - break; - - default: - ilSetError(IL_INTERNAL_ERROR); - return; - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - ShortPtr = (ILushort*)Colours; - switch (Format) - { - case IL_RGB: - ShortPtr[0] = (ILushort)(ClearRed * USHRT_MAX); - ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); - ShortPtr[2] = (ILushort)(ClearBlue * USHRT_MAX); - break; - - case IL_RGBA: - ShortPtr[0] = (ILushort)(ClearRed * USHRT_MAX); - ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); - ShortPtr[2] = (ILushort)(ClearBlue * USHRT_MAX); - ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX); - break; - - case IL_BGR: - ShortPtr[2] = (ILushort)(ClearRed * USHRT_MAX); - ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); - ShortPtr[0] = (ILushort)(ClearBlue * USHRT_MAX); - ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX); - break; - - case IL_BGRA: - ShortPtr[2] = (ILushort)(ClearRed * USHRT_MAX); - ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); - ShortPtr[0] = (ILushort)(ClearBlue * USHRT_MAX); - ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX); - break; - - case IL_LUMINANCE: - ShortPtr[0] = (ILushort)(ClearAlpha * USHRT_MAX); - break; - - case IL_LUMINANCE_ALPHA: - ShortPtr[0] = (ILushort)(ClearLum * USHRT_MAX); - ShortPtr[1] = (ILushort)(ClearAlpha * USHRT_MAX); - break; - - case IL_COLOUR_INDEX: - ShortPtr[0] = (ILushort)(ClearAlpha * USHRT_MAX); - break; - - default: - ilSetError(IL_INTERNAL_ERROR); - return; - } - break; - - case IL_INT: - case IL_UNSIGNED_INT: - IntPtr = (ILuint*)Colours; - switch (Format) - { - case IL_RGB: - IntPtr[0] = (ILuint)(ClearRed * UINT_MAX); - IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); - IntPtr[2] = (ILuint)(ClearBlue * UINT_MAX); - break; - - case IL_RGBA: - IntPtr[0] = (ILuint)(ClearRed * UINT_MAX); - IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); - IntPtr[2] = (ILuint)(ClearBlue * UINT_MAX); - IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX); - break; - - case IL_BGR: - IntPtr[2] = (ILuint)(ClearRed * UINT_MAX); - IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); - IntPtr[0] = (ILuint)(ClearBlue * UINT_MAX); - IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX); - break; - - case IL_BGRA: - IntPtr[2] = (ILuint)(ClearRed * UINT_MAX); - IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); - IntPtr[0] = (ILuint)(ClearBlue * UINT_MAX); - IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX); - break; - - case IL_LUMINANCE: - IntPtr[0] = (ILuint)(ClearAlpha * UINT_MAX); - break; - - case IL_LUMINANCE_ALPHA: - IntPtr[0] = (ILuint)(ClearLum * UINT_MAX); - IntPtr[1] = (ILuint)(ClearAlpha * UINT_MAX); - break; - - case IL_COLOUR_INDEX: - IntPtr[0] = (ILuint)(ClearAlpha * UINT_MAX); - break; - - default: - ilSetError(IL_INTERNAL_ERROR); - return; - } - break; - - case IL_FLOAT: - FloatPtr = (ILfloat*)Colours; - switch (Format) - { - case IL_RGB: - FloatPtr[0] = ClearRed; - FloatPtr[1] = ClearGreen; - FloatPtr[2] = ClearBlue; - break; - - case IL_RGBA: - FloatPtr[0] = ClearRed; - FloatPtr[1] = ClearGreen; - FloatPtr[2] = ClearBlue; - FloatPtr[3] = ClearAlpha; - break; - - case IL_BGR: - FloatPtr[2] = ClearRed; - FloatPtr[1] = ClearGreen; - FloatPtr[0] = ClearBlue; - FloatPtr[3] = ClearAlpha; - break; - - case IL_BGRA: - FloatPtr[2] = ClearRed; - FloatPtr[1] = ClearGreen; - FloatPtr[0] = ClearBlue; - FloatPtr[3] = ClearAlpha; - break; - - case IL_LUMINANCE: - FloatPtr[0] = ClearAlpha; - break; - - case IL_LUMINANCE_ALPHA: - FloatPtr[0] = ClearLum; - FloatPtr[0] = ClearAlpha; - break; - - case IL_COLOUR_INDEX: - FloatPtr[0] = ClearAlpha; - break; - - default: - ilSetError(IL_INTERNAL_ERROR); - return; - } - break; - - case IL_DOUBLE: - DblPtr = (ILdouble*)Colours; - switch (Format) - { - case IL_RGB: - DblPtr[0] = ClearRed; - DblPtr[1] = ClearGreen; - DblPtr[2] = ClearBlue; - break; - - case IL_RGBA: - DblPtr[0] = ClearRed; - DblPtr[1] = ClearGreen; - DblPtr[2] = ClearBlue; - DblPtr[3] = ClearAlpha; - break; - - case IL_BGR: - DblPtr[2] = ClearRed; - DblPtr[1] = ClearGreen; - DblPtr[0] = ClearBlue; - DblPtr[3] = ClearAlpha; - break; - - case IL_BGRA: - DblPtr[2] = ClearRed; - DblPtr[1] = ClearGreen; - DblPtr[0] = ClearBlue; - DblPtr[3] = ClearAlpha; - break; - - case IL_LUMINANCE: - DblPtr[0] = ClearAlpha; - break; - - case IL_LUMINANCE_ALPHA: - DblPtr[0] = ClearLum; - DblPtr[1] = ClearAlpha; - break; - - case IL_COLOUR_INDEX: - DblPtr[0] = ClearAlpha; - break; - - default: - ilSetError(IL_INTERNAL_ERROR); - return; - } - break; - - default: - ilSetError(IL_INTERNAL_ERROR); - return; - } - - return; -} - - -//! Clears the current bound image to the values specified in ilClearColour -ILboolean ILAPIENTRY ilClearImage() -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - return ilClearImage_(iCurImage); -} - - -ILAPI ILboolean ILAPIENTRY ilClearImage_(ILimage *Image) -{ - ILuint i, c, NumBytes; - ILubyte Colours[32]; // Maximum is sizeof(double) * 4 = 32 - ILubyte *BytePtr; - ILushort *ShortPtr; - ILuint *IntPtr; - ILfloat *FloatPtr; - ILdouble *DblPtr; - - NumBytes = Image->Bpp * Image->Bpc; - ilGetClear(Colours, Image->Format, Image->Type); - - if (Image->Format != IL_COLOUR_INDEX) { - switch (Image->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - BytePtr = (ILubyte*)Colours; - for (c = 0; c < NumBytes; c += Image->Bpc) { - for (i = c; i < Image->SizeOfData; i += NumBytes) { - Image->Data[i] = BytePtr[c]; - } - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - ShortPtr = (ILushort*)Colours; - for (c = 0; c < NumBytes; c += Image->Bpc) { - for (i = c; i < Image->SizeOfData; i += NumBytes) { - *((ILushort*)(Image->Data + i)) = ShortPtr[c / Image->Bpc]; - } - } - break; - - case IL_INT: - case IL_UNSIGNED_INT: - IntPtr = (ILuint*)Colours; - for (c = 0; c < NumBytes; c += Image->Bpc) { - for (i = c; i < Image->SizeOfData; i += NumBytes) { - *((ILuint*)(Image->Data + i)) = IntPtr[c / Image->Bpc]; - } - } - break; - - case IL_FLOAT: - FloatPtr = (ILfloat*)Colours; - for (c = 0; c < NumBytes; c += Image->Bpc) { - for (i = c; i < Image->SizeOfData; i += NumBytes) { - *((ILfloat*)(Image->Data + i)) = FloatPtr[c / Image->Bpc]; - } - } - break; - - case IL_DOUBLE: - DblPtr = (ILdouble*)Colours; - for (c = 0; c < NumBytes; c += Image->Bpc) { - for (i = c; i < Image->SizeOfData; i += NumBytes) { - *((ILdouble*)(Image->Data + i)) = DblPtr[c / Image->Bpc]; - } - } - break; - } - } - else { - imemclear(Image->Data, Image->SizeOfData); - - if (Image->Pal.Palette) - ifree(Image->Pal.Palette); - Image->Pal.Palette = (ILubyte*)ialloc(4); - if (Image->Pal.Palette == NULL) { - return IL_FALSE; - } - - Image->Pal.PalType = IL_PAL_RGBA32; - Image->Pal.PalSize = 4; - - Image->Pal.Palette[0] = Colours[0] * UCHAR_MAX; - Image->Pal.Palette[1] = Colours[1] * UCHAR_MAX; - Image->Pal.Palette[2] = Colours[2] * UCHAR_MAX; - Image->Pal.Palette[3] = Colours[3] * UCHAR_MAX; - } - - return IL_TRUE; -} - - -//! Overlays the image found in Src on top of the current bound image at the coords specified. -ILboolean ILAPIENTRY ilOverlayImage(ILuint Source, ILint XCoord, ILint YCoord, ILint ZCoord) -{ - ILuint Width, Height, Depth; - ILuint Dest; - - Dest = ilGetCurName(); - ilBindImage(Source); - Width = iCurImage->Width; Height = iCurImage->Height; Depth = iCurImage->Depth; - ilBindImage(Dest); - - return ilBlit(Source, XCoord, YCoord, ZCoord, 0, 0, 0, Width, Height, Depth); -} - -//@NEXT DestX,DestY,DestZ must be set to ILuint -ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX, ILint DestY, ILint DestZ, - ILuint SrcX, ILuint SrcY, ILuint SrcZ, - ILuint Width, ILuint Height, ILuint Depth) -{ - ILuint x, y, z, ConvBps, ConvSizePlane; - ILimage *Dest,*Src; - ILubyte *Converted; - ILuint DestName = ilGetCurName(); - ILuint c; - ILuint StartX, StartY, StartZ; - ILboolean DestFlipped = IL_FALSE; - ILubyte *SrcTemp; - ILfloat Back; - - // Check if the desiination image really exists - if (DestName == 0 || iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - Dest = iCurImage; - - // set the destination image to upper left origin - if (Dest->Origin == IL_ORIGIN_LOWER_LEFT) { // Dest - DestFlipped = IL_TRUE; - ilFlipImage(); - } - //DestOrigin = Dest->Origin; - ilBindImage(Source); - - // Check if the source image really exists - if (iCurImage == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - Src = iCurImage; - - //@TODO test if coordinates are inside the images (hard limit for source) - - // set the source image to upper left origin - if (Src->Origin == IL_ORIGIN_LOWER_LEFT) - { - SrcTemp = iGetFlipped(iCurImage); - if (SrcTemp == NULL) - { - ilBindImage(DestName); - if (DestFlipped) - ilFlipImage(); - return IL_FALSE; - } - } - else - { - SrcTemp = iCurImage->Data; - } - - // convert source image to match the destination image type and format - Converted = (ILubyte*)ilConvertBuffer(Src->SizeOfData, Src->Format, Dest->Format, Src->Type, Dest->Type, NULL, SrcTemp); - if (Converted == NULL) - return IL_FALSE; - - ConvBps = Dest->Bpp * Src->Width; - ConvSizePlane = ConvBps * Src->Height; - - //@NEXT in next version this would have to be removed since Dest* will be unsigned - StartX = DestX >= 0 ? 0 : -DestX; - StartY = DestY >= 0 ? 0 : -DestY; - StartZ = DestZ >= 0 ? 0 : -DestZ; - - // Limit the copy of data inside of the destination image - if (Width + DestX > Dest->Width) Width = Dest->Width - DestX; - if (Height + DestY > Dest->Height) Height = Dest->Height - DestY; - if (Depth + DestZ > Dest->Depth) Depth = Dest->Depth - DestZ; - - //@TODO: non funziona con rgba - if (Src->Format == IL_RGBA || Src->Format == IL_BGRA || Src->Format == IL_LUMINANCE_ALPHA) { - const ILuint bpp_without_alpha = Dest->Bpp - 1; - for (z = 0; z < Depth; z++) { - for (y = 0; y < Height; y++) { - for (x = 0; x < Width; x++) { - const ILuint SrcIndex = (z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp; - const ILuint DestIndex = (z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp; - const ILuint AlphaIdx = SrcIndex + bpp_without_alpha; - ILfloat Front = 0; - - switch (Dest->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - Front = Converted[AlphaIdx]/((float)IL_MAX_UNSIGNED_BYTE); - break; - case IL_SHORT: - case IL_UNSIGNED_SHORT: - Front = ((ILshort*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_SHORT); - break; - case IL_INT: - case IL_UNSIGNED_INT: - Front = ((ILint*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_INT); - break; - case IL_FLOAT: - Front = ((ILfloat*)Converted)[AlphaIdx]; - break; - case IL_DOUBLE: - Front = (ILfloat)(((ILdouble*)Converted)[AlphaIdx]); - break; - } - Back = 1.0f - Front; - // In case of Alpha channel, the data is blended. Keeps the original alpha. - if (ilIsEnabled(IL_BLIT_BLEND)) { - for (c = 0; c < bpp_without_alpha; c++) - { - Dest->Data[DestIndex + c] = - (ILubyte)(Converted[SrcIndex + c] * Front - + Dest->Data[DestIndex + c] * Back); - } - } - else { - for (c = 0; c < Dest->Bpp; c++) - { - Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c]); - } - } - } - } - } - } else { - for( z = 0; z < Depth; z++ ) { - for( y = 0; y < Height; y++ ) { - for( x = 0; x < Width; x++ ) { - for( c = 0; c < Dest->Bpp; c++ ) { - Dest->Data[(z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp + c] = - Converted[(z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp + c]; - } - } - } - } - } - - if (SrcTemp != iCurImage->Data) - ifree(SrcTemp); - - ilBindImage(DestName); - if (DestFlipped) - ilFlipImage(); - - ifree(Converted); - - return IL_TRUE; -} - - -ILboolean iCopySubImage(ILimage *Dest, ILimage *Src) -{ - ILimage *DestTemp, *SrcTemp; - - DestTemp = Dest; - SrcTemp = Src; - - do { - ilCopyImageAttr(DestTemp, SrcTemp); - DestTemp->Data = (ILubyte*)ialloc(SrcTemp->SizeOfData); - if (DestTemp->Data == NULL) { - return IL_FALSE; - } - memcpy(DestTemp->Data, SrcTemp->Data, SrcTemp->SizeOfData); - - if (SrcTemp->Next) { - DestTemp->Next = (ILimage*)icalloc(1, sizeof(ILimage)); - if (!DestTemp->Next) { - return IL_FALSE; - } - } - else { - DestTemp->Next = NULL; - } - - DestTemp = DestTemp->Next; - SrcTemp = SrcTemp->Next; - } while (SrcTemp); - - return IL_TRUE; -} - - -ILboolean iCopySubImages(ILimage *Dest, ILimage *Src) -{ - if (Src->Faces) { - Dest->Faces = (ILimage*)icalloc(1, sizeof(ILimage)); - if (!Dest->Faces) { - return IL_FALSE; - } - if (!iCopySubImage(Dest->Faces, Src->Faces)) - return IL_FALSE; - } - - if (Src->Layers) { - Dest->Layers = (ILimage*)icalloc(1, sizeof(ILimage)); - if (!Dest->Layers) { - return IL_FALSE; - } - if (!iCopySubImage(Dest->Layers, Src->Layers)) - return IL_FALSE; - } - - if (Src->Mipmaps) { - Dest->Mipmaps = (ILimage*)icalloc(1, sizeof(ILimage)); - if (!Dest->Mipmaps) { - return IL_FALSE; - } - if (!iCopySubImage(Dest->Mipmaps, Src->Mipmaps)) - return IL_FALSE; - } - - if (Src->Next) { - Dest->Next = (ILimage*)icalloc(1, sizeof(ILimage)); - if (!Dest->Next) { - return IL_FALSE; - } - if (!iCopySubImage(Dest->Next, Src->Next)) - return IL_FALSE; - } - - return IL_TRUE; -} - - -// Copies everything but the Data from Src to Dest. -ILAPI ILboolean ILAPIENTRY ilCopyImageAttr(ILimage *Dest, ILimage *Src) -{ - if (Dest == NULL || Src == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (Dest->Pal.Palette && Dest->Pal.PalSize && Dest->Pal.PalType != IL_PAL_NONE) { - ifree(Dest->Pal.Palette); - Dest->Pal.Palette = NULL; - } - if (Dest->Faces) { - ilCloseImage(Dest->Faces); - Dest->Faces = NULL; - } - if (Dest->Layers) { - ilCloseImage(Dest->Layers); - Dest->Layers = NULL; - } - if (Dest->Mipmaps) { - ilCloseImage(Dest->Mipmaps); - Dest->Mipmaps = NULL; - } - if (Dest->Next) { - ilCloseImage(Dest->Next); - Dest->Next = NULL; - } - if (Dest->Profile) { - ifree(Dest->Profile); - Dest->Profile = NULL; - Dest->ProfileSize = 0; - } - if (Dest->DxtcData) { - ifree(Dest->DxtcData); - Dest->DxtcData = NULL; - Dest->DxtcFormat = IL_DXT_NO_COMP; - Dest->DxtcSize = 0; - } - - if (Src->AnimList && Src->AnimSize) { - Dest->AnimList = (ILuint*)ialloc(Src->AnimSize * sizeof(ILuint)); - if (Dest->AnimList == NULL) { - return IL_FALSE; - } - memcpy(Dest->AnimList, Src->AnimList, Src->AnimSize * sizeof(ILuint)); - } - if (Src->Profile) { - Dest->Profile = (ILubyte*)ialloc(Src->ProfileSize); - if (Dest->Profile == NULL) { - return IL_FALSE; - } - memcpy(Dest->Profile, Src->Profile, Src->ProfileSize); - Dest->ProfileSize = Src->ProfileSize; - } - if (Src->Pal.Palette) { - Dest->Pal.Palette = (ILubyte*)ialloc(Src->Pal.PalSize); - if (Dest->Pal.Palette == NULL) { - return IL_FALSE; - } - memcpy(Dest->Pal.Palette, Src->Pal.Palette, Src->Pal.PalSize); - } - else { - Dest->Pal.Palette = NULL; - } - - Dest->Pal.PalSize = Src->Pal.PalSize; - Dest->Pal.PalType = Src->Pal.PalType; - Dest->Width = Src->Width; - Dest->Height = Src->Height; - Dest->Depth = Src->Depth; - Dest->Bpp = Src->Bpp; - Dest->Bpc = Src->Bpc; - Dest->Bps = Src->Bps; - Dest->SizeOfPlane = Src->SizeOfPlane; - Dest->SizeOfData = Src->SizeOfData; - Dest->Format = Src->Format; - Dest->Type = Src->Type; - Dest->Origin = Src->Origin; - Dest->Duration = Src->Duration; - Dest->CubeFlags = Src->CubeFlags; - Dest->AnimSize = Src->AnimSize; - Dest->OffX = Src->OffX; - Dest->OffY = Src->OffY; - - return IL_TRUE/*iCopySubImages(Dest, Src)*/; -} - - -//! Copies everything from Src to the current bound image. -ILboolean ILAPIENTRY ilCopyImage(ILuint Src) -{ - ILuint DestName = ilGetCurName(); - ILimage *DestImage = iCurImage, *SrcImage; - - if (iCurImage == NULL || DestName == 0) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - ilBindImage(Src); - SrcImage = iCurImage; - ilBindImage(DestName); - ilTexImage(SrcImage->Width, SrcImage->Height, SrcImage->Depth, SrcImage->Bpp, SrcImage->Format, SrcImage->Type, SrcImage->Data); - ilCopyImageAttr(DestImage, SrcImage); - - return IL_TRUE; -} - - -// Creates a copy of Src and returns it. -ILAPI ILimage* ILAPIENTRY ilCopyImage_(ILimage *Src) -{ - ILimage *Dest; - - if (Src == NULL) { - ilSetError(IL_INVALID_PARAM); - return NULL; - } - - Dest = ilNewImage(Src->Width, Src->Height, Src->Depth, Src->Bpp, Src->Bpc); - if (Dest == NULL) { - return NULL; - } - - if (ilCopyImageAttr(Dest, Src) == IL_FALSE) - return NULL; - - memcpy(Dest->Data, Src->Data, Src->SizeOfData); - - return Dest; -} - - -ILuint ILAPIENTRY ilCloneCurImage() -{ - ILuint Id; - ILimage *CurImage; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return 0; - } - - ilGenImages(1, &Id); - if (Id == 0) - return 0; - - CurImage = iCurImage; - - ilBindImage(Id); - ilTexImage(CurImage->Width, CurImage->Height, CurImage->Depth, CurImage->Bpp, CurImage->Format, CurImage->Type, CurImage->Data); - ilCopyImageAttr(iCurImage, CurImage); - - iCurImage = CurImage; - - return Id; -} - - -// Like ilTexImage but doesn't destroy the palette. -ILAPI ILboolean ILAPIENTRY ilResizeImage(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc) -{ - if (Image == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (Image->Data != NULL) - ifree(Image->Data); - - Image->Depth = Depth; - Image->Width = Width; - Image->Height = Height; - Image->Bpp = Bpp; - Image->Bpc = Bpc; - Image->Bps = Bpp * Bpc * Width; - Image->SizeOfPlane = Image->Bps * Height; - Image->SizeOfData = Image->SizeOfPlane * Depth; - - Image->Data = (ILubyte*)ialloc(Image->SizeOfData); - if (Image->Data == NULL) { - return IL_FALSE; - } - - return IL_TRUE; -} diff --git a/DevIL/src-IL/src/il_devil.cpp b/DevIL/src-IL/src/il_devil.cpp new file mode 100644 index 00000000..fc2f7b7e --- /dev/null +++ b/DevIL/src-IL/src/il_devil.cpp @@ -0,0 +1,1068 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/01/2009 +// +// Filename: src-IL/src/il_devil.c +// +// Description: Functions for working with the ILimage's and the current image +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include +#include + + +ILAPI ILboolean ILAPIENTRY ilInitImage(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) +{ + ILubyte BpcType = ilGetBpcType(Type); + if (BpcType == 0) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + memset(Image, 0, sizeof(ILimage)); + + //// + if (Width == 0) Width = 1; + if (Height == 0) Height = 1; + if (Depth == 0) Depth = 1; + Image->Width = Width; + Image->Height = Height; + Image->Depth = Depth; + Image->Bpp = Bpp; + Image->Bpc = BpcType; + Image->Bps = Width * Bpp * Image->Bpc; + Image->SizeOfPlane = Image->Bps * Height; + Image->SizeOfData = Image->SizeOfPlane * Depth; + Image->Format = Format; + Image->Type = Type; + Image->Origin = IL_ORIGIN_LOWER_LEFT; + Image->Pal.PalType = IL_PAL_NONE; + Image->DxtcFormat = IL_DXT_NO_COMP; + Image->DxtcData = NULL; + + Image->Data = (ILubyte*)ialloc(Image->SizeOfData); + if (Image->Data == NULL) { + return IL_FALSE; + } + + if (Data != NULL) { + memcpy(Image->Data, Data, Image->SizeOfData); + } + + return IL_TRUE; +} + + + +// Creates a new ILimage based on the specifications given +ILAPI ILimage* ILAPIENTRY ilNewImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc) +{ + ILimage *Image; + + if (Bpp == 0 || Bpp > 4) { + return NULL; + } + + Image = (ILimage*)ialloc(sizeof(ILimage)); + if (Image == NULL) { + return NULL; + } + + if (!ilInitImage(Image, Width, Height, Depth, Bpp, ilGetFormatBpp(Bpp), ilGetTypeBpc(Bpc), NULL)) { + if (Image->Data != NULL) { + ifree(Image->Data); + } + ifree(Image); + return NULL; + } + + return Image; +} + + +// Same as above but allows specification of Format and Type +ILAPI ILimage* ILAPIENTRY ilNewImageFull(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) +{ + ILimage *Image; + + if (Bpp == 0 || Bpp > 4) { + return NULL; + } + + Image = (ILimage*)ialloc(sizeof(ILimage)); + if (Image == NULL) { + return NULL; + } + + if (!ilInitImage(Image, Width, Height, Depth, Bpp, Format, Type, Data)) { + if (Image->Data != NULL) { + ifree(Image->Data); + } + ifree(Image); + return NULL; + } + + return Image; +} + + +//! Changes the current bound image to use these new dimensions (current data is destroyed). +/*! \param Width Specifies the new image width. This cannot be 0. + \param Height Specifies the new image height. This cannot be 0. + \param Depth Specifies the new image depth. This cannot be 0. + \param Bpp Number of channels (ex. 3 for RGB) + \param Format Enum of the desired format. Any format values are accepted. + \param Type Enum of the desired type. Any type values are accepted. + \param Data Specifies data that should be copied to the new image. If this parameter is NULL, no data is copied, and the new image data consists of undefined values. + \exception IL_ILLEGAL_OPERATION No currently bound image. + \exception IL_INVALID_PARAM One of the parameters is incorrect, such as one of the dimensions being 0. + \exception IL_OUT_OF_MEMORY Could not allocate enough memory. + \return Boolean value of failure or success*/ +ILboolean ILAPIENTRY ilTexImage(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) +{ + return ilTexImage_(iCurImage, Width, Height, Depth, Bpp, Format, Type, Data); +} + + +// Internal version of ilTexImage. +ILAPI ILboolean ILAPIENTRY ilTexImage_(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILenum Format, ILenum Type, void *Data) +{ + if (Image == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + //// + + // Not sure if we should be getting rid of the palette... + if (Image->Pal.Palette && Image->Pal.PalSize && Image->Pal.PalType != IL_PAL_NONE) { + ifree(Image->Pal.Palette); + } + + ilCloseImage(Image->Mipmaps); + ilCloseImage(Image->Next); + ilCloseImage(Image->Faces); + ilCloseImage(Image->Layers); + + if (Image->AnimList) ifree(Image->AnimList); + if (Image->Profile) ifree(Image->Profile); + if (Image->DxtcData) ifree(Image->DxtcData); + if (Image->Data) ifree(Image->Data); + + //// + + //@TODO: Also check against format? + /*if (Width == 0 || Height == 0 || Depth == 0 || Bpp == 0) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + }*/ + + return ilInitImage(Image, Width, Height, Depth, Bpp, Format, Type, Data); +} + + +//! Uploads Data of the same size to replace the current image's data. +/*! \param Data New image data to update the currently bound image + \exception IL_ILLEGAL_OPERATION No currently bound image + \exception IL_INVALID_PARAM Data was NULL. + \return Boolean value of failure or success +*/ +ILboolean ILAPIENTRY ilSetData(void *Data) +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + return ilTexSubImage_(iCurImage, Data); +} + + +// Internal version of ilTexSubImage. +ILAPI ILboolean ILAPIENTRY ilTexSubImage_(ILimage *Image, void *Data) +{ + if (Image == NULL || Data == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + if (!Image->Data) { + Image->Data = (ILubyte*)ialloc(Image->SizeOfData); + if (Image->Data == NULL) + return IL_FALSE; + } + memcpy(Image->Data, Data, Image->SizeOfData); + return IL_TRUE; +} + + +//! Returns a pointer to the current image's data. +/*! The pointer to the image data returned by this function is only valid until any + operations are done on the image. After any operations, this function should be + called again. The pointer can be cast to other types for images that have more + than one byte per channel for easier access to data. + \exception IL_ILLEGAL_OPERATION No currently bound image + \return ILubyte pointer to image data.*/ +ILubyte* ILAPIENTRY ilGetData(void) +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + + return iCurImage->Data; +} + + +//! Returns a pointer to the current image's palette data. +/*! The pointer to the image palette data returned by this function is only valid until + any operations are done on the image. After any operations, this function should be + called again. + \exception IL_ILLEGAL_OPERATION No currently bound image + \return ILubyte pointer to image palette data.*/ +ILubyte* ILAPIENTRY ilGetPalette(void) +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + + return iCurImage->Pal.Palette; +} + + +//ILfloat ClearRed = 0.0f, ClearGreen = 0.0f, ClearBlue = 0.0f, ClearAlpha = 0.0f; + +// Changed to the colour of the Universe +// (http://www.newscientist.com/news/news.jsp?id=ns99991775) +// *(http://www.space.com/scienceastronomy/universe_color_020308.html)* +//ILfloat ClearRed = 0.269f, ClearGreen = 0.388f, ClearBlue = 0.342f, ClearAlpha = 0.0f; +static ILfloat ClearRed = 1.0f; +static ILfloat ClearGreen = 0.972549f; +static ILfloat ClearBlue = 0.90588f; +static ILfloat ClearAlpha = 0.0f; +static ILfloat ClearLum = 1.0f; + +void ILAPIENTRY ilClearColour(ILclampf Red, ILclampf Green, ILclampf Blue, ILclampf Alpha) +{ + // Clamp to 0.0f - 1.0f. + ClearRed = Red < 0.0f ? 0.0f : (Red > 1.0f ? 1.0f : Red); + ClearGreen = Green < 0.0f ? 0.0f : (Green > 1.0f ? 1.0f : Green); + ClearBlue = Blue < 0.0f ? 0.0f : (Blue > 1.0f ? 1.0f : Blue); + ClearAlpha = Alpha < 0.0f ? 0.0f : (Alpha > 1.0f ? 1.0f : Alpha); + + if ((Red == Green) && (Red == Blue) && (Green == Blue)) { + ClearLum = Red < 0.0f ? 0.0f : (Red > 1.0f ? 1.0f : Red); + } + else { + ClearLum = 0.212671f * ClearRed + 0.715160f * ClearGreen + 0.072169f * ClearBlue; + ClearLum = ClearLum < 0.0f ? 0.0f : (ClearLum > 1.0f ? 1.0f : ClearLum); + } + + return; +} + + +ILAPI void ILAPIENTRY ilGetClear(void *Colours, ILenum Format, ILenum Type) +{ + ILubyte *BytePtr; + ILushort *ShortPtr; + ILuint *IntPtr; + ILfloat *FloatPtr; + ILdouble *DblPtr; + + switch (Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + BytePtr = (ILubyte*)Colours; + switch (Format) + { + case IL_RGB: + BytePtr[0] = (ILubyte)(ClearRed * UCHAR_MAX); + BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); + BytePtr[2] = (ILubyte)(ClearBlue * UCHAR_MAX); + break; + + case IL_RGBA: + BytePtr[0] = (ILubyte)(ClearRed * UCHAR_MAX); + BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); + BytePtr[2] = (ILubyte)(ClearBlue * UCHAR_MAX); + BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX); + break; + + case IL_BGR: + BytePtr[2] = (ILubyte)(ClearRed * UCHAR_MAX); + BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); + BytePtr[0] = (ILubyte)(ClearBlue * UCHAR_MAX); + BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX); + break; + + case IL_BGRA: + BytePtr[2] = (ILubyte)(ClearRed * UCHAR_MAX); + BytePtr[1] = (ILubyte)(ClearGreen * UCHAR_MAX); + BytePtr[0] = (ILubyte)(ClearBlue * UCHAR_MAX); + BytePtr[3] = (ILubyte)(ClearAlpha * UCHAR_MAX); + break; + + case IL_LUMINANCE: + BytePtr[0] = (ILubyte)(ClearAlpha * UCHAR_MAX); + break; + + case IL_LUMINANCE_ALPHA: + BytePtr[0] = (ILubyte)(ClearLum * UCHAR_MAX); + BytePtr[1] = (ILubyte)(ClearAlpha * UCHAR_MAX); + + case IL_COLOUR_INDEX: + BytePtr[0] = (ILubyte)(ClearAlpha * UCHAR_MAX); + break; + + default: + ilSetError(IL_INTERNAL_ERROR); + return; + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + ShortPtr = (ILushort*)Colours; + switch (Format) + { + case IL_RGB: + ShortPtr[0] = (ILushort)(ClearRed * USHRT_MAX); + ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); + ShortPtr[2] = (ILushort)(ClearBlue * USHRT_MAX); + break; + + case IL_RGBA: + ShortPtr[0] = (ILushort)(ClearRed * USHRT_MAX); + ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); + ShortPtr[2] = (ILushort)(ClearBlue * USHRT_MAX); + ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX); + break; + + case IL_BGR: + ShortPtr[2] = (ILushort)(ClearRed * USHRT_MAX); + ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); + ShortPtr[0] = (ILushort)(ClearBlue * USHRT_MAX); + ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX); + break; + + case IL_BGRA: + ShortPtr[2] = (ILushort)(ClearRed * USHRT_MAX); + ShortPtr[1] = (ILushort)(ClearGreen * USHRT_MAX); + ShortPtr[0] = (ILushort)(ClearBlue * USHRT_MAX); + ShortPtr[3] = (ILushort)(ClearAlpha * USHRT_MAX); + break; + + case IL_LUMINANCE: + ShortPtr[0] = (ILushort)(ClearAlpha * USHRT_MAX); + break; + + case IL_LUMINANCE_ALPHA: + ShortPtr[0] = (ILushort)(ClearLum * USHRT_MAX); + ShortPtr[1] = (ILushort)(ClearAlpha * USHRT_MAX); + break; + + case IL_COLOUR_INDEX: + ShortPtr[0] = (ILushort)(ClearAlpha * USHRT_MAX); + break; + + default: + ilSetError(IL_INTERNAL_ERROR); + return; + } + break; + + case IL_INT: + case IL_UNSIGNED_INT: + IntPtr = (ILuint*)Colours; + switch (Format) + { + case IL_RGB: + IntPtr[0] = (ILuint)(ClearRed * UINT_MAX); + IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); + IntPtr[2] = (ILuint)(ClearBlue * UINT_MAX); + break; + + case IL_RGBA: + IntPtr[0] = (ILuint)(ClearRed * UINT_MAX); + IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); + IntPtr[2] = (ILuint)(ClearBlue * UINT_MAX); + IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX); + break; + + case IL_BGR: + IntPtr[2] = (ILuint)(ClearRed * UINT_MAX); + IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); + IntPtr[0] = (ILuint)(ClearBlue * UINT_MAX); + IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX); + break; + + case IL_BGRA: + IntPtr[2] = (ILuint)(ClearRed * UINT_MAX); + IntPtr[1] = (ILuint)(ClearGreen * UINT_MAX); + IntPtr[0] = (ILuint)(ClearBlue * UINT_MAX); + IntPtr[3] = (ILuint)(ClearAlpha * UINT_MAX); + break; + + case IL_LUMINANCE: + IntPtr[0] = (ILuint)(ClearAlpha * UINT_MAX); + break; + + case IL_LUMINANCE_ALPHA: + IntPtr[0] = (ILuint)(ClearLum * UINT_MAX); + IntPtr[1] = (ILuint)(ClearAlpha * UINT_MAX); + break; + + case IL_COLOUR_INDEX: + IntPtr[0] = (ILuint)(ClearAlpha * UINT_MAX); + break; + + default: + ilSetError(IL_INTERNAL_ERROR); + return; + } + break; + + case IL_FLOAT: + FloatPtr = (ILfloat*)Colours; + switch (Format) + { + case IL_RGB: + FloatPtr[0] = ClearRed; + FloatPtr[1] = ClearGreen; + FloatPtr[2] = ClearBlue; + break; + + case IL_RGBA: + FloatPtr[0] = ClearRed; + FloatPtr[1] = ClearGreen; + FloatPtr[2] = ClearBlue; + FloatPtr[3] = ClearAlpha; + break; + + case IL_BGR: + FloatPtr[2] = ClearRed; + FloatPtr[1] = ClearGreen; + FloatPtr[0] = ClearBlue; + FloatPtr[3] = ClearAlpha; + break; + + case IL_BGRA: + FloatPtr[2] = ClearRed; + FloatPtr[1] = ClearGreen; + FloatPtr[0] = ClearBlue; + FloatPtr[3] = ClearAlpha; + break; + + case IL_LUMINANCE: + FloatPtr[0] = ClearAlpha; + break; + + case IL_LUMINANCE_ALPHA: + FloatPtr[0] = ClearLum; + FloatPtr[0] = ClearAlpha; + break; + + case IL_COLOUR_INDEX: + FloatPtr[0] = ClearAlpha; + break; + + default: + ilSetError(IL_INTERNAL_ERROR); + return; + } + break; + + case IL_DOUBLE: + DblPtr = (ILdouble*)Colours; + switch (Format) + { + case IL_RGB: + DblPtr[0] = ClearRed; + DblPtr[1] = ClearGreen; + DblPtr[2] = ClearBlue; + break; + + case IL_RGBA: + DblPtr[0] = ClearRed; + DblPtr[1] = ClearGreen; + DblPtr[2] = ClearBlue; + DblPtr[3] = ClearAlpha; + break; + + case IL_BGR: + DblPtr[2] = ClearRed; + DblPtr[1] = ClearGreen; + DblPtr[0] = ClearBlue; + DblPtr[3] = ClearAlpha; + break; + + case IL_BGRA: + DblPtr[2] = ClearRed; + DblPtr[1] = ClearGreen; + DblPtr[0] = ClearBlue; + DblPtr[3] = ClearAlpha; + break; + + case IL_LUMINANCE: + DblPtr[0] = ClearAlpha; + break; + + case IL_LUMINANCE_ALPHA: + DblPtr[0] = ClearLum; + DblPtr[1] = ClearAlpha; + break; + + case IL_COLOUR_INDEX: + DblPtr[0] = ClearAlpha; + break; + + default: + ilSetError(IL_INTERNAL_ERROR); + return; + } + break; + + default: + ilSetError(IL_INTERNAL_ERROR); + return; + } + + return; +} + + +//! Clears the current bound image to the values specified in ilClearColour +ILboolean ILAPIENTRY ilClearImage() +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + return ilClearImage_(iCurImage); +} + + +ILAPI ILboolean ILAPIENTRY ilClearImage_(ILimage *Image) +{ + ILuint i, c, NumBytes; + ILubyte Colours[32]; // Maximum is sizeof(double) * 4 = 32 + ILubyte *BytePtr; + ILushort *ShortPtr; + ILuint *IntPtr; + ILfloat *FloatPtr; + ILdouble *DblPtr; + + NumBytes = Image->Bpp * Image->Bpc; + ilGetClear(Colours, Image->Format, Image->Type); + + if (Image->Format != IL_COLOUR_INDEX) { + switch (Image->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + BytePtr = (ILubyte*)Colours; + for (c = 0; c < NumBytes; c += Image->Bpc) { + for (i = c; i < Image->SizeOfData; i += NumBytes) { + Image->Data[i] = BytePtr[c]; + } + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + ShortPtr = (ILushort*)Colours; + for (c = 0; c < NumBytes; c += Image->Bpc) { + for (i = c; i < Image->SizeOfData; i += NumBytes) { + *((ILushort*)(Image->Data + i)) = ShortPtr[c / Image->Bpc]; + } + } + break; + + case IL_INT: + case IL_UNSIGNED_INT: + IntPtr = (ILuint*)Colours; + for (c = 0; c < NumBytes; c += Image->Bpc) { + for (i = c; i < Image->SizeOfData; i += NumBytes) { + *((ILuint*)(Image->Data + i)) = IntPtr[c / Image->Bpc]; + } + } + break; + + case IL_FLOAT: + FloatPtr = (ILfloat*)Colours; + for (c = 0; c < NumBytes; c += Image->Bpc) { + for (i = c; i < Image->SizeOfData; i += NumBytes) { + *((ILfloat*)(Image->Data + i)) = FloatPtr[c / Image->Bpc]; + } + } + break; + + case IL_DOUBLE: + DblPtr = (ILdouble*)Colours; + for (c = 0; c < NumBytes; c += Image->Bpc) { + for (i = c; i < Image->SizeOfData; i += NumBytes) { + *((ILdouble*)(Image->Data + i)) = DblPtr[c / Image->Bpc]; + } + } + break; + } + } + else { + imemclear(Image->Data, Image->SizeOfData); + + if (Image->Pal.Palette) + ifree(Image->Pal.Palette); + Image->Pal.Palette = (ILubyte*)ialloc(4); + if (Image->Pal.Palette == NULL) { + return IL_FALSE; + } + + Image->Pal.PalType = IL_PAL_RGBA32; + Image->Pal.PalSize = 4; + + Image->Pal.Palette[0] = Colours[0] * UCHAR_MAX; + Image->Pal.Palette[1] = Colours[1] * UCHAR_MAX; + Image->Pal.Palette[2] = Colours[2] * UCHAR_MAX; + Image->Pal.Palette[3] = Colours[3] * UCHAR_MAX; + } + + return IL_TRUE; +} + + +//! Overlays the image found in Src on top of the current bound image at the coords specified. +ILboolean ILAPIENTRY ilOverlayImage(ILuint Source, ILint XCoord, ILint YCoord, ILint ZCoord) +{ + ILuint Width, Height, Depth; + ILuint Dest; + + Dest = ilGetCurName(); + ilBindImage(Source); + Width = iCurImage->Width; Height = iCurImage->Height; Depth = iCurImage->Depth; + ilBindImage(Dest); + + return ilBlit(Source, XCoord, YCoord, ZCoord, 0, 0, 0, Width, Height, Depth); +} + +//@NEXT DestX,DestY,DestZ must be set to ILuint +ILboolean ILAPIENTRY ilBlit(ILuint Source, ILint DestX, ILint DestY, ILint DestZ, + ILuint SrcX, ILuint SrcY, ILuint SrcZ, + ILuint Width, ILuint Height, ILuint Depth) +{ + ILuint x, y, z, ConvBps, ConvSizePlane; + ILimage *Dest,*Src; + ILubyte *Converted; + ILuint DestName = ilGetCurName(); + ILuint c; + ILuint StartX, StartY, StartZ; + ILboolean DestFlipped = IL_FALSE; + ILubyte *SrcTemp; + ILfloat Back; + + // Check if the desiination image really exists + if (DestName == 0 || iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + Dest = iCurImage; + + // set the destination image to upper left origin + if (Dest->Origin == IL_ORIGIN_LOWER_LEFT) { // Dest + DestFlipped = IL_TRUE; + ilFlipImage(); + } + //DestOrigin = Dest->Origin; + ilBindImage(Source); + + // Check if the source image really exists + if (iCurImage == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + Src = iCurImage; + + //@TODO test if coordinates are inside the images (hard limit for source) + + // set the source image to upper left origin + if (Src->Origin == IL_ORIGIN_LOWER_LEFT) + { + SrcTemp = iGetFlipped(iCurImage); + if (SrcTemp == NULL) + { + ilBindImage(DestName); + if (DestFlipped) + ilFlipImage(); + return IL_FALSE; + } + } + else + { + SrcTemp = iCurImage->Data; + } + + // convert source image to match the destination image type and format + Converted = (ILubyte*)ilConvertBuffer(Src->SizeOfData, Src->Format, Dest->Format, Src->Type, Dest->Type, NULL, SrcTemp); + if (Converted == NULL) + return IL_FALSE; + + ConvBps = Dest->Bpp * Src->Width; + ConvSizePlane = ConvBps * Src->Height; + + //@NEXT in next version this would have to be removed since Dest* will be unsigned + StartX = DestX >= 0 ? 0 : -DestX; + StartY = DestY >= 0 ? 0 : -DestY; + StartZ = DestZ >= 0 ? 0 : -DestZ; + + // Limit the copy of data inside of the destination image + if (Width + DestX > Dest->Width) Width = Dest->Width - DestX; + if (Height + DestY > Dest->Height) Height = Dest->Height - DestY; + if (Depth + DestZ > Dest->Depth) Depth = Dest->Depth - DestZ; + + //@TODO: non funziona con rgba + if (Src->Format == IL_RGBA || Src->Format == IL_BGRA || Src->Format == IL_LUMINANCE_ALPHA) { + const ILuint bpp_without_alpha = Dest->Bpp - 1; + for (z = 0; z < Depth; z++) { + for (y = 0; y < Height; y++) { + for (x = 0; x < Width; x++) { + const ILuint SrcIndex = (z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp; + const ILuint DestIndex = (z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp; + const ILuint AlphaIdx = SrcIndex + bpp_without_alpha; + ILfloat Front = 0; + + switch (Dest->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + Front = Converted[AlphaIdx]/((float)IL_MAX_UNSIGNED_BYTE); + break; + case IL_SHORT: + case IL_UNSIGNED_SHORT: + Front = ((ILshort*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_SHORT); + break; + case IL_INT: + case IL_UNSIGNED_INT: + Front = ((ILint*)Converted)[AlphaIdx]/((float)IL_MAX_UNSIGNED_INT); + break; + case IL_FLOAT: + Front = ((ILfloat*)Converted)[AlphaIdx]; + break; + case IL_DOUBLE: + Front = (ILfloat)(((ILdouble*)Converted)[AlphaIdx]); + break; + } + Back = 1.0f - Front; + // In case of Alpha channel, the data is blended. Keeps the original alpha. + if (ilIsEnabled(IL_BLIT_BLEND)) { + for (c = 0; c < bpp_without_alpha; c++) + { + Dest->Data[DestIndex + c] = + (ILubyte)(Converted[SrcIndex + c] * Front + + Dest->Data[DestIndex + c] * Back); + } + } + else { + for (c = 0; c < Dest->Bpp; c++) + { + Dest->Data[DestIndex + c] = (ILubyte)(Converted[SrcIndex + c]); + } + } + } + } + } + } else { + for( z = 0; z < Depth; z++ ) { + for( y = 0; y < Height; y++ ) { + for( x = 0; x < Width; x++ ) { + for( c = 0; c < Dest->Bpp; c++ ) { + Dest->Data[(z+DestZ)*Dest->SizeOfPlane + (y+DestY)*Dest->Bps + (x+DestX)*Dest->Bpp + c] = + Converted[(z+SrcZ)*ConvSizePlane + (y+SrcY)*ConvBps + (x+SrcX)*Dest->Bpp + c]; + } + } + } + } + } + + if (SrcTemp != iCurImage->Data) + ifree(SrcTemp); + + ilBindImage(DestName); + if (DestFlipped) + ilFlipImage(); + + ifree(Converted); + + return IL_TRUE; +} + + +ILboolean iCopySubImage(ILimage *Dest, ILimage *Src) +{ + ILimage *DestTemp, *SrcTemp; + + DestTemp = Dest; + SrcTemp = Src; + + do { + ilCopyImageAttr(DestTemp, SrcTemp); + DestTemp->Data = (ILubyte*)ialloc(SrcTemp->SizeOfData); + if (DestTemp->Data == NULL) { + return IL_FALSE; + } + memcpy(DestTemp->Data, SrcTemp->Data, SrcTemp->SizeOfData); + + if (SrcTemp->Next) { + DestTemp->Next = (ILimage*)icalloc(1, sizeof(ILimage)); + if (!DestTemp->Next) { + return IL_FALSE; + } + } + else { + DestTemp->Next = NULL; + } + + DestTemp = DestTemp->Next; + SrcTemp = SrcTemp->Next; + } while (SrcTemp); + + return IL_TRUE; +} + + +ILboolean iCopySubImages(ILimage *Dest, ILimage *Src) +{ + if (Src->Faces) { + Dest->Faces = (ILimage*)icalloc(1, sizeof(ILimage)); + if (!Dest->Faces) { + return IL_FALSE; + } + if (!iCopySubImage(Dest->Faces, Src->Faces)) + return IL_FALSE; + } + + if (Src->Layers) { + Dest->Layers = (ILimage*)icalloc(1, sizeof(ILimage)); + if (!Dest->Layers) { + return IL_FALSE; + } + if (!iCopySubImage(Dest->Layers, Src->Layers)) + return IL_FALSE; + } + + if (Src->Mipmaps) { + Dest->Mipmaps = (ILimage*)icalloc(1, sizeof(ILimage)); + if (!Dest->Mipmaps) { + return IL_FALSE; + } + if (!iCopySubImage(Dest->Mipmaps, Src->Mipmaps)) + return IL_FALSE; + } + + if (Src->Next) { + Dest->Next = (ILimage*)icalloc(1, sizeof(ILimage)); + if (!Dest->Next) { + return IL_FALSE; + } + if (!iCopySubImage(Dest->Next, Src->Next)) + return IL_FALSE; + } + + return IL_TRUE; +} + + +// Copies everything but the Data from Src to Dest. +ILAPI ILboolean ILAPIENTRY ilCopyImageAttr(ILimage *Dest, ILimage *Src) +{ + if (Dest == NULL || Src == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (Dest->Pal.Palette && Dest->Pal.PalSize && Dest->Pal.PalType != IL_PAL_NONE) { + ifree(Dest->Pal.Palette); + Dest->Pal.Palette = NULL; + } + if (Dest->Faces) { + ilCloseImage(Dest->Faces); + Dest->Faces = NULL; + } + if (Dest->Layers) { + ilCloseImage(Dest->Layers); + Dest->Layers = NULL; + } + if (Dest->Mipmaps) { + ilCloseImage(Dest->Mipmaps); + Dest->Mipmaps = NULL; + } + if (Dest->Next) { + ilCloseImage(Dest->Next); + Dest->Next = NULL; + } + if (Dest->Profile) { + ifree(Dest->Profile); + Dest->Profile = NULL; + Dest->ProfileSize = 0; + } + if (Dest->DxtcData) { + ifree(Dest->DxtcData); + Dest->DxtcData = NULL; + Dest->DxtcFormat = IL_DXT_NO_COMP; + Dest->DxtcSize = 0; + } + + if (Src->AnimList && Src->AnimSize) { + Dest->AnimList = (ILuint*)ialloc(Src->AnimSize * sizeof(ILuint)); + if (Dest->AnimList == NULL) { + return IL_FALSE; + } + memcpy(Dest->AnimList, Src->AnimList, Src->AnimSize * sizeof(ILuint)); + } + if (Src->Profile) { + Dest->Profile = (ILubyte*)ialloc(Src->ProfileSize); + if (Dest->Profile == NULL) { + return IL_FALSE; + } + memcpy(Dest->Profile, Src->Profile, Src->ProfileSize); + Dest->ProfileSize = Src->ProfileSize; + } + if (Src->Pal.Palette) { + Dest->Pal.Palette = (ILubyte*)ialloc(Src->Pal.PalSize); + if (Dest->Pal.Palette == NULL) { + return IL_FALSE; + } + memcpy(Dest->Pal.Palette, Src->Pal.Palette, Src->Pal.PalSize); + } + else { + Dest->Pal.Palette = NULL; + } + + Dest->Pal.PalSize = Src->Pal.PalSize; + Dest->Pal.PalType = Src->Pal.PalType; + Dest->Width = Src->Width; + Dest->Height = Src->Height; + Dest->Depth = Src->Depth; + Dest->Bpp = Src->Bpp; + Dest->Bpc = Src->Bpc; + Dest->Bps = Src->Bps; + Dest->SizeOfPlane = Src->SizeOfPlane; + Dest->SizeOfData = Src->SizeOfData; + Dest->Format = Src->Format; + Dest->Type = Src->Type; + Dest->Origin = Src->Origin; + Dest->Duration = Src->Duration; + Dest->CubeFlags = Src->CubeFlags; + Dest->AnimSize = Src->AnimSize; + Dest->OffX = Src->OffX; + Dest->OffY = Src->OffY; + + return IL_TRUE/*iCopySubImages(Dest, Src)*/; +} + + +//! Copies everything from Src to the current bound image. +ILboolean ILAPIENTRY ilCopyImage(ILuint Src) +{ + ILuint DestName = ilGetCurName(); + ILimage *DestImage = iCurImage, *SrcImage; + + if (iCurImage == NULL || DestName == 0) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + ilBindImage(Src); + SrcImage = iCurImage; + ilBindImage(DestName); + ilTexImage(SrcImage->Width, SrcImage->Height, SrcImage->Depth, SrcImage->Bpp, SrcImage->Format, SrcImage->Type, SrcImage->Data); + ilCopyImageAttr(DestImage, SrcImage); + + return IL_TRUE; +} + + +// Creates a copy of Src and returns it. +ILAPI ILimage* ILAPIENTRY ilCopyImage_(ILimage *Src) +{ + ILimage *Dest; + + if (Src == NULL) { + ilSetError(IL_INVALID_PARAM); + return NULL; + } + + Dest = ilNewImage(Src->Width, Src->Height, Src->Depth, Src->Bpp, Src->Bpc); + if (Dest == NULL) { + return NULL; + } + + if (ilCopyImageAttr(Dest, Src) == IL_FALSE) + return NULL; + + memcpy(Dest->Data, Src->Data, Src->SizeOfData); + + return Dest; +} + + +ILuint ILAPIENTRY ilCloneCurImage() +{ + ILuint Id; + ILimage *CurImage; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return 0; + } + + ilGenImages(1, &Id); + if (Id == 0) + return 0; + + CurImage = iCurImage; + + ilBindImage(Id); + ilTexImage(CurImage->Width, CurImage->Height, CurImage->Depth, CurImage->Bpp, CurImage->Format, CurImage->Type, CurImage->Data); + ilCopyImageAttr(iCurImage, CurImage); + + iCurImage = CurImage; + + return Id; +} + + +// Like ilTexImage but doesn't destroy the palette. +ILAPI ILboolean ILAPIENTRY ilResizeImage(ILimage *Image, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, ILubyte Bpc) +{ + if (Image == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (Image->Data != NULL) + ifree(Image->Data); + + Image->Depth = Depth; + Image->Width = Width; + Image->Height = Height; + Image->Bpp = Bpp; + Image->Bpc = Bpc; + Image->Bps = Bpp * Bpc * Width; + Image->SizeOfPlane = Image->Bps * Height; + Image->SizeOfData = Image->SizeOfPlane * Depth; + + Image->Data = (ILubyte*)ialloc(Image->SizeOfData); + if (Image->Data == NULL) { + return IL_FALSE; + } + + return IL_TRUE; +} diff --git a/DevIL/src-IL/src/il_dicom.c b/DevIL/src-IL/src/il_dicom.c deleted file mode 100644 index 9fc087de..00000000 --- a/DevIL/src-IL/src/il_dicom.c +++ /dev/null @@ -1,608 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/14/2009 -// -// Filename: src-IL/src/il_dicom.c -// -// Description: Reads from a Digital Imaging and Communications in Medicine -// (DICOM) file. Specifications can be found at -// http://en.wikipedia.org/wiki/Dicom. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_DICOM - -typedef struct DICOMHEAD -{ - ILubyte Signature[4]; - ILuint Version; - ILuint Width; - ILuint Height; - ILuint Depth; - ILuint Samples; - ILuint BitsAllocated; - ILuint BitsStored; - ILuint DataLen; - ILboolean BigEndian; - ILenum Encoding; - - // For DevIL use only - ILenum Format; - ILenum Type; -} DICOMHEAD; - -ILboolean iIsValidDicom(void); -ILboolean iCheckDicom(DICOMHEAD *Header); -ILboolean iLoadDicomInternal(void); -ILboolean iGetDicomHead(DICOMHEAD *Header); -ILboolean SkipElement(DICOMHEAD *Header, ILushort GroupNum, ILushort ElementNum); -ILboolean GetNumericValue(DICOMHEAD *Header, ILushort GroupNum, ILuint *Number); -ILboolean GetUID(ILubyte *UID); -ILuint GetGroupNum(DICOMHEAD *Header); -ILuint GetShort(DICOMHEAD *Header, ILushort GroupNum); -ILuint GetInt(DICOMHEAD *Header, ILushort GroupNum); -ILfloat GetFloat(DICOMHEAD *Header, ILushort GroupNum); - -//! Checks if the file specified in FileName is a valid DICOM file. -ILboolean ilIsValidDicom(ILconst_string FileName) -{ - ILHANDLE DicomFile; - ILboolean bDicom = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("dicom")) && !iCheckExtension(FileName, IL_TEXT("dcm"))) { - ilSetError(IL_INVALID_EXTENSION); - return bDicom; - } - - DicomFile = iopenr(FileName); - if (DicomFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDicom; - } - - bDicom = ilIsValidDicomF(DicomFile); - icloser(DicomFile); - - return bDicom; -} - - -//! Checks if the ILHANDLE contains a valid DICOM file at the current position. -ILboolean ilIsValidDicomF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidDicom(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid DICOM lump. -ILboolean ilIsValidDicomL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidDicom(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidDicom(void) -{ - DICOMHEAD Header; - ILuint Pos = itell(); - - // Clear the header to all 0s to make checks later easier. - memset(&Header, 0, sizeof(DICOMHEAD)); - if (!iGetDicomHead(&Header)) - return IL_FALSE; - // The length of the header varies, so we just go back to the original position. - iseek(Pos, IL_SEEK_CUR); - - return iCheckDicom(&Header); -} - - -// Internal function used to get the DICOM header from the current file. -ILboolean iGetDicomHead(DICOMHEAD *Header) -{ - ILushort GroupNum, ElementNum; - ILboolean ReachedData = IL_FALSE; - ILubyte Var2, UID[65]; - - // Signature should be "DICM" at position 128. - iseek(128, IL_SEEK_SET); - if (iread(Header->Signature, 1, 4) != 4) - return IL_FALSE; - -//@TODO: What about the case when we are reading an image with Big Endian data? - - do { - GroupNum = GetGroupNum(Header); - ElementNum = GetShort(Header, GroupNum);; - - switch (GroupNum) - { - case 0x02: - switch (ElementNum) - { - /*case 0x01: // Version number - if (!GetNumericValue(&Header->Version)) - return IL_FALSE; - if (Header->Version != 0x0100) - return IL_FALSE; - break;*/ - - case 0x10: - //@TODO: Look at pg. 60 of 07_05pu.pdf (PS 3.5) for more UIDs. - if (!GetUID(UID)) - return IL_FALSE; - if (!strncmp(UID, "1.2.840.10008.1.2.2", 64)) // Explicit big endian - Header->BigEndian = IL_TRUE; - else if (!strncmp(UID, "1.2.840.10008.1.2.1", 64)) // Explicit little endian - Header->BigEndian = IL_FALSE; - else if (!strncmp(UID, "1.2.840.10008.1.2", 64)) // Implicit little endian - Header->BigEndian = IL_FALSE; - else - return IL_FALSE; // Unrecognized UID. - break; - - default: - if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. - return IL_FALSE; - } - break; - - case 0x28: - switch (ElementNum) - { - case 0x02: // Samples per pixel - if (!GetNumericValue(Header, GroupNum, &Header->Samples)) - return IL_FALSE; - break; - - case 0x08: // Number of frames, or depth - if (!GetNumericValue(Header, GroupNum, &Header->Depth)) - return IL_FALSE; - break; - - case 0x10: // The number of rows - if (!GetNumericValue(Header, GroupNum, &Header->Height)) - return IL_FALSE; - break; - - case 0x11: // The number of columns - if (!GetNumericValue(Header, GroupNum, &Header->Width)) - return IL_FALSE; - break; - - case 0x100: // Bits allocated per sample - if (!GetNumericValue(Header, GroupNum, &Header->BitsAllocated)) - return IL_FALSE; - break; - - case 0x101: // Bits stored per sample - Do we really need this information? - if (!GetNumericValue(Header, GroupNum, &Header->BitsStored)) - return IL_FALSE; - break; - - default: - if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. - return IL_FALSE; - } - break; - - case 0x7FE0: - switch (ElementNum) - { - case 0x10: // This element is the actual pixel data. We are done with the header here. - if (igetc() != 'O') // @TODO: Can we assume that this is always 'O'? - return IL_FALSE; - Var2 = igetc(); - if (Var2 != 'B' && Var2 != 'W' && Var2 != 'F') // 'OB', 'OW' and 'OF' accepted for this element. - return IL_FALSE; - GetLittleUShort(); // Skip the 2 reserved bytes. - Header->DataLen = GetInt(Header, GroupNum);//GetLittleUInt(); - ReachedData = IL_TRUE; - break; - default: - if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. - return IL_FALSE; - } - break; - - default: - if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. - return IL_FALSE; - } - } while (!ieof() && !ReachedData); - - if (ieof()) - return IL_FALSE; - - // Some DICOM images do not have the depth (number of frames) field. - if (Header->Depth == 0) - Header->Depth = 1; - - switch (Header->BitsAllocated) - { - case 8: - Header->Type = IL_UNSIGNED_BYTE; - break; - case 16: - Header->Type = IL_UNSIGNED_SHORT; - break; - case 32: - Header->Type = IL_FLOAT; //@TODO: Is this ever an integer? - break; - default: //@TODO: Any other types we can deal with? - return IL_FALSE; - } - - // Cannot handle more than 4 channels in an image. - if (Header->Samples > 4) - return IL_FALSE; - Header->Format = ilGetFormatBpp(Header->Samples); - - return IL_TRUE; -} - - -ILboolean SkipElement(DICOMHEAD *Header, ILushort GroupNum, ILushort ElementNum) -{ - ILubyte VR1, VR2; - ILuint ValLen; - - // 2 byte character string telling what type this element is ('OB', 'UI', etc.) - VR1 = igetc(); - VR2 = igetc(); - - if ((VR1 == 'O' && VR2 == 'B') || (VR1 == 'O' && VR2 == 'W') || (VR1 == 'O' && VR2 == 'F') || - (VR1 == 'S' && VR2 == 'Q') || (VR1 == 'U' && VR2 == 'T') || (VR1 == 'U' && VR2 == 'N')) { - // These all have a different format than the other formats, since they can be up to 32 bits long. - GetLittleUShort(); // Values reserved, we do not care about them. - ValLen = GetInt(Header, GroupNum);//GetLittleUInt(); // Length of the rest of the element - if (ValLen % 2) // This length must be even, according to the specs. - return IL_FALSE; - if (ElementNum != 0x00) // Element numbers of 0 tell the size of the full group, so we do not skip this. - // @TODO: We could use this to skip groups that we do not care about. - if (iseek(ValLen, IL_SEEK_CUR)) - return IL_FALSE; - } - else { - // These have a length of 16 bits. - ValLen = GetShort(Header, GroupNum);//GetLittleUShort(); - //if (ValLen % 2) // This length must be even, according to the specs. - // ValLen++; // Add the extra byte to seek. - //if (ElementNum != 0x00) // Element numbers of 0 tell the size of the full group, so we do not skip this. - // @TODO: We could use this to skip groups that we do not care about. - if (iseek(ValLen, IL_SEEK_CUR)) - return IL_FALSE; - } - - return IL_TRUE; -} - - -ILuint GetGroupNum(DICOMHEAD *Header) -{ - ILushort GroupNum; - - iread(&GroupNum, 1, 2); - // The 0x02 group is always little endian. - if (GroupNum == 0x02) { - UShort(&GroupNum); - return GroupNum; - } - // Now we have to swizzle it if it is not 0x02. - if (Header->BigEndian) - BigUShort(&GroupNum); - else - UShort(&GroupNum); - - return GroupNum; -} - - -ILuint GetShort(DICOMHEAD *Header, ILushort GroupNum) -{ - ILushort Num; - - iread(&Num, 1, 2); - // The 0x02 group is always little endian. - if (GroupNum == 0x02) { - UShort(&Num); - return Num; - } - // Now we have to swizzle it if it is not 0x02. - if (Header->BigEndian) - BigUShort(&Num); - else - UShort(&Num); - - return Num; -} - - -ILuint GetInt(DICOMHEAD *Header, ILushort GroupNum) -{ - ILuint Num; - - iread(&Num, 1, 4); - // The 0x02 group is always little endian. - if (GroupNum == 0x02) { - UInt(&Num); - return Num; - } - // Now we have to swizzle it if it is not 0x02. - if (Header->BigEndian) - BigUInt(&Num); - else - UInt(&Num); - - return Num; -} - - -ILfloat GetFloat(DICOMHEAD *Header, ILushort GroupNum) -{ - ILfloat Num; - - iread(&Num, 1, 4); - // The 0x02 group is always little endian. - if (GroupNum == 0x02) { - Float(&Num); - return Num; - } - // Now we have to swizzle it if it is not 0x02. - if (Header->BigEndian) - BigFloat(&Num); - else - Float(&Num); - - return Num; -} - - -ILboolean GetNumericValue(DICOMHEAD *Header, ILushort GroupNum, ILuint *Number) -{ - ILubyte VR1, VR2; - ILushort ValLen; - - // 2 byte character string telling what type this element is ('OB', 'UI', etc.) - VR1 = igetc(); - VR2 = igetc(); - - if (VR1 == 'U' && VR2 == 'S') { // Unsigned short - ValLen = GetShort(Header, GroupNum);//GetLittleUShort(); - if (ValLen != 2) // Must always be 2 for short ('US') - return IL_FALSE; - *((ILushort*)Number) = GetShort(Header, GroupNum);//GetLittleUShort(); - return IL_TRUE; - } - if (VR1 == 'U' && VR2 == 'L') { // Unsigned long - ValLen = GetInt(Header, GroupNum);//GetLittleUInt(); - if (ValLen != 4) // Must always be 4 for long ('UL') - return IL_FALSE; - *Number = GetInt(Header, GroupNum); - return IL_TRUE; - } - if (VR1 == 'S' && VR2 == 'S') { // Signed short - ValLen = GetShort(Header, GroupNum); - if (ValLen != 2) // Must always be 2 for short ('US') - return IL_FALSE; - *((ILshort*)Number) = GetShort(Header, GroupNum); - return IL_TRUE; - } - if (VR1 == 'S' && VR2 == 'L') { // Signed long - ValLen = GetInt(Header, GroupNum); - if (ValLen != 4) // Must always be 4 for long ('UL') - return IL_FALSE; - *((ILint*)Number) = GetInt(Header, GroupNum); - return IL_TRUE; - } - - return IL_FALSE; -} - - -ILboolean GetUID(ILubyte *UID) -{ - ILubyte VR1, VR2; - ILushort ValLen; - - // 2 byte character string telling what type this element is ('OB', 'UI', etc.) - VR1 = igetc(); - VR2 = igetc(); - - if (VR1 != 'U' || VR2 != 'I') // 'UI' == UID - return IL_FALSE; - - ValLen = GetLittleUShort(); - if (ValLen > 64) - return IL_FALSE; - if (iread(UID, ValLen, 1) != 1) - return IL_FALSE; - UID[ValLen] = 0; // Just to make sure that our string is terminated. - - return IL_TRUE; -} - -// Internal function used to check if the HEADER is a valid DICOM header. -ILboolean iCheckDicom(DICOMHEAD *Header) -{ - // Always has the signature "DICM" at position 0x80. - if (strncmp(Header->Signature, "DICM", 4)) - return IL_FALSE; - // Does not make sense to have any dimension = 0. - if (Header->Width == 0 || Header->Height == 0 || Header->Depth == 0) - return IL_FALSE; - // We can only deal with images that have byte-aligned data. - //@TODO: Take care of any others? - if (Header->BitsAllocated % 8) - return IL_FALSE; - // Check for an invalid format being set (or not set at all). - if (ilGetBppFormat(Header->Format) == 0) - return IL_FALSE; - // Check for an invalid type being set (or not set at all). - if (ilGetBpcType(Header->Type) == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Reads a DICOM file -ILboolean ilLoadDicom(ILconst_string FileName) -{ - ILHANDLE DicomFile; - ILboolean bDicom = IL_FALSE; - - DicomFile = iopenr(FileName); - if (DicomFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDicom; - } - - bDicom = ilLoadDicomF(DicomFile); - icloser(DicomFile); - - return bDicom; -} - - -//! Reads an already-opened DICOM file -ILboolean ilLoadDicomF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDicomInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a DICOM -ILboolean ilLoadDicomL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadDicomInternal(); -} - - -// Internal function used to load the DICOM. -ILboolean iLoadDicomInternal(void) -{ - DICOMHEAD Header; - ILuint i; - ILushort TempS, *ShortPtr; - ILfloat TempF, *FloatPtr; - ILboolean Swizzle = IL_FALSE; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - // Clear the header to all 0s to make checks later easier. - memset(&Header, 0, sizeof(DICOMHEAD)); - if (!iGetDicomHead(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - if (!iCheckDicom(&Header)) - return IL_FALSE; - - if (!ilTexImage(Header.Width, Header.Height, Header.Depth, ilGetBppFormat(Header.Format), Header.Format, Header.Type, NULL)) - return IL_FALSE; - //@TODO: Find out if the origin is always in the upper left. - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - // Header.DataLen may be larger than SizeOfData, since it has to be padded with a NULL if it is not an even length, - // so we just test to make sure it is at least large enough. - //@TODO: Do this check before ilTexImage call. - if (Header.DataLen < iCurImage->SizeOfData) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // We may have to swap the order of the data. -#ifdef __BIG_ENDIAN__ - if (!Header.BigEndian) { - if (Header.Format == IL_RGB) - Header.Format = IL_BGR; - else if (Header.Format == IL_RGBA) - Swizzle = IL_TRUE; - } -#else // Little endian - if (Header.BigEndian) { - if (Header.Format == IL_RGB) - Header.Format = IL_BGR; - if (Header.Format == IL_RGBA) - Swizzle = IL_TRUE; - } -#endif - - switch (Header.Type) - { - case IL_UNSIGNED_BYTE: - if (iread(iCurImage->Data, iCurImage->SizeOfData, 1) != 1) - return IL_FALSE; - - // Swizzle the data from ABGR to RGBA. - if (Swizzle) { - for (i = 0; i < iCurImage->SizeOfData; i += 4) { - iSwapUInt((ILuint*)(iCurImage->Data + i)); - } - } - break; - - case IL_UNSIGNED_SHORT: - for (i = 0; i < iCurImage->SizeOfData; i += 2) { - *((ILushort*)(iCurImage->Data + i)) = GetShort(&Header, 0);//GetLittleUShort(); - } - - // Swizzle the data from ABGR to RGBA. - if (Swizzle) { - ShortPtr = (ILushort*)iCurImage->Data; - for (i = 0; i < iCurImage->SizeOfData / 2; i += 4) { - TempS = ShortPtr[i]; - ShortPtr[i] = ShortPtr[i+3]; - ShortPtr[i+3] = TempS; - } - } - break; - - case IL_FLOAT: - for (i = 0; i < iCurImage->SizeOfData; i += 4) { - *((ILfloat*)(iCurImage->Data + i)) = GetFloat(&Header, 0);//GetLittleFloat(); - } - - // Swizzle the data from ABGR to RGBA. - if (Swizzle) { - FloatPtr = (ILfloat*)iCurImage->Data; - for (i = 0; i < iCurImage->SizeOfData / 4; i += 4) { - TempF = FloatPtr[i]; - FloatPtr[i] = FloatPtr[i+3]; - FloatPtr[i+3] = TempF; - } - } - break; - } - - return ilFixImage(); -} - - - -#endif//IL_NO_DICOM diff --git a/DevIL/src-IL/src/il_dicom.cpp b/DevIL/src-IL/src/il_dicom.cpp new file mode 100644 index 00000000..9fc087de --- /dev/null +++ b/DevIL/src-IL/src/il_dicom.cpp @@ -0,0 +1,608 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/14/2009 +// +// Filename: src-IL/src/il_dicom.c +// +// Description: Reads from a Digital Imaging and Communications in Medicine +// (DICOM) file. Specifications can be found at +// http://en.wikipedia.org/wiki/Dicom. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_DICOM + +typedef struct DICOMHEAD +{ + ILubyte Signature[4]; + ILuint Version; + ILuint Width; + ILuint Height; + ILuint Depth; + ILuint Samples; + ILuint BitsAllocated; + ILuint BitsStored; + ILuint DataLen; + ILboolean BigEndian; + ILenum Encoding; + + // For DevIL use only + ILenum Format; + ILenum Type; +} DICOMHEAD; + +ILboolean iIsValidDicom(void); +ILboolean iCheckDicom(DICOMHEAD *Header); +ILboolean iLoadDicomInternal(void); +ILboolean iGetDicomHead(DICOMHEAD *Header); +ILboolean SkipElement(DICOMHEAD *Header, ILushort GroupNum, ILushort ElementNum); +ILboolean GetNumericValue(DICOMHEAD *Header, ILushort GroupNum, ILuint *Number); +ILboolean GetUID(ILubyte *UID); +ILuint GetGroupNum(DICOMHEAD *Header); +ILuint GetShort(DICOMHEAD *Header, ILushort GroupNum); +ILuint GetInt(DICOMHEAD *Header, ILushort GroupNum); +ILfloat GetFloat(DICOMHEAD *Header, ILushort GroupNum); + +//! Checks if the file specified in FileName is a valid DICOM file. +ILboolean ilIsValidDicom(ILconst_string FileName) +{ + ILHANDLE DicomFile; + ILboolean bDicom = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("dicom")) && !iCheckExtension(FileName, IL_TEXT("dcm"))) { + ilSetError(IL_INVALID_EXTENSION); + return bDicom; + } + + DicomFile = iopenr(FileName); + if (DicomFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDicom; + } + + bDicom = ilIsValidDicomF(DicomFile); + icloser(DicomFile); + + return bDicom; +} + + +//! Checks if the ILHANDLE contains a valid DICOM file at the current position. +ILboolean ilIsValidDicomF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidDicom(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid DICOM lump. +ILboolean ilIsValidDicomL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidDicom(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidDicom(void) +{ + DICOMHEAD Header; + ILuint Pos = itell(); + + // Clear the header to all 0s to make checks later easier. + memset(&Header, 0, sizeof(DICOMHEAD)); + if (!iGetDicomHead(&Header)) + return IL_FALSE; + // The length of the header varies, so we just go back to the original position. + iseek(Pos, IL_SEEK_CUR); + + return iCheckDicom(&Header); +} + + +// Internal function used to get the DICOM header from the current file. +ILboolean iGetDicomHead(DICOMHEAD *Header) +{ + ILushort GroupNum, ElementNum; + ILboolean ReachedData = IL_FALSE; + ILubyte Var2, UID[65]; + + // Signature should be "DICM" at position 128. + iseek(128, IL_SEEK_SET); + if (iread(Header->Signature, 1, 4) != 4) + return IL_FALSE; + +//@TODO: What about the case when we are reading an image with Big Endian data? + + do { + GroupNum = GetGroupNum(Header); + ElementNum = GetShort(Header, GroupNum);; + + switch (GroupNum) + { + case 0x02: + switch (ElementNum) + { + /*case 0x01: // Version number + if (!GetNumericValue(&Header->Version)) + return IL_FALSE; + if (Header->Version != 0x0100) + return IL_FALSE; + break;*/ + + case 0x10: + //@TODO: Look at pg. 60 of 07_05pu.pdf (PS 3.5) for more UIDs. + if (!GetUID(UID)) + return IL_FALSE; + if (!strncmp(UID, "1.2.840.10008.1.2.2", 64)) // Explicit big endian + Header->BigEndian = IL_TRUE; + else if (!strncmp(UID, "1.2.840.10008.1.2.1", 64)) // Explicit little endian + Header->BigEndian = IL_FALSE; + else if (!strncmp(UID, "1.2.840.10008.1.2", 64)) // Implicit little endian + Header->BigEndian = IL_FALSE; + else + return IL_FALSE; // Unrecognized UID. + break; + + default: + if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. + return IL_FALSE; + } + break; + + case 0x28: + switch (ElementNum) + { + case 0x02: // Samples per pixel + if (!GetNumericValue(Header, GroupNum, &Header->Samples)) + return IL_FALSE; + break; + + case 0x08: // Number of frames, or depth + if (!GetNumericValue(Header, GroupNum, &Header->Depth)) + return IL_FALSE; + break; + + case 0x10: // The number of rows + if (!GetNumericValue(Header, GroupNum, &Header->Height)) + return IL_FALSE; + break; + + case 0x11: // The number of columns + if (!GetNumericValue(Header, GroupNum, &Header->Width)) + return IL_FALSE; + break; + + case 0x100: // Bits allocated per sample + if (!GetNumericValue(Header, GroupNum, &Header->BitsAllocated)) + return IL_FALSE; + break; + + case 0x101: // Bits stored per sample - Do we really need this information? + if (!GetNumericValue(Header, GroupNum, &Header->BitsStored)) + return IL_FALSE; + break; + + default: + if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. + return IL_FALSE; + } + break; + + case 0x7FE0: + switch (ElementNum) + { + case 0x10: // This element is the actual pixel data. We are done with the header here. + if (igetc() != 'O') // @TODO: Can we assume that this is always 'O'? + return IL_FALSE; + Var2 = igetc(); + if (Var2 != 'B' && Var2 != 'W' && Var2 != 'F') // 'OB', 'OW' and 'OF' accepted for this element. + return IL_FALSE; + GetLittleUShort(); // Skip the 2 reserved bytes. + Header->DataLen = GetInt(Header, GroupNum);//GetLittleUInt(); + ReachedData = IL_TRUE; + break; + default: + if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. + return IL_FALSE; + } + break; + + default: + if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. + return IL_FALSE; + } + } while (!ieof() && !ReachedData); + + if (ieof()) + return IL_FALSE; + + // Some DICOM images do not have the depth (number of frames) field. + if (Header->Depth == 0) + Header->Depth = 1; + + switch (Header->BitsAllocated) + { + case 8: + Header->Type = IL_UNSIGNED_BYTE; + break; + case 16: + Header->Type = IL_UNSIGNED_SHORT; + break; + case 32: + Header->Type = IL_FLOAT; //@TODO: Is this ever an integer? + break; + default: //@TODO: Any other types we can deal with? + return IL_FALSE; + } + + // Cannot handle more than 4 channels in an image. + if (Header->Samples > 4) + return IL_FALSE; + Header->Format = ilGetFormatBpp(Header->Samples); + + return IL_TRUE; +} + + +ILboolean SkipElement(DICOMHEAD *Header, ILushort GroupNum, ILushort ElementNum) +{ + ILubyte VR1, VR2; + ILuint ValLen; + + // 2 byte character string telling what type this element is ('OB', 'UI', etc.) + VR1 = igetc(); + VR2 = igetc(); + + if ((VR1 == 'O' && VR2 == 'B') || (VR1 == 'O' && VR2 == 'W') || (VR1 == 'O' && VR2 == 'F') || + (VR1 == 'S' && VR2 == 'Q') || (VR1 == 'U' && VR2 == 'T') || (VR1 == 'U' && VR2 == 'N')) { + // These all have a different format than the other formats, since they can be up to 32 bits long. + GetLittleUShort(); // Values reserved, we do not care about them. + ValLen = GetInt(Header, GroupNum);//GetLittleUInt(); // Length of the rest of the element + if (ValLen % 2) // This length must be even, according to the specs. + return IL_FALSE; + if (ElementNum != 0x00) // Element numbers of 0 tell the size of the full group, so we do not skip this. + // @TODO: We could use this to skip groups that we do not care about. + if (iseek(ValLen, IL_SEEK_CUR)) + return IL_FALSE; + } + else { + // These have a length of 16 bits. + ValLen = GetShort(Header, GroupNum);//GetLittleUShort(); + //if (ValLen % 2) // This length must be even, according to the specs. + // ValLen++; // Add the extra byte to seek. + //if (ElementNum != 0x00) // Element numbers of 0 tell the size of the full group, so we do not skip this. + // @TODO: We could use this to skip groups that we do not care about. + if (iseek(ValLen, IL_SEEK_CUR)) + return IL_FALSE; + } + + return IL_TRUE; +} + + +ILuint GetGroupNum(DICOMHEAD *Header) +{ + ILushort GroupNum; + + iread(&GroupNum, 1, 2); + // The 0x02 group is always little endian. + if (GroupNum == 0x02) { + UShort(&GroupNum); + return GroupNum; + } + // Now we have to swizzle it if it is not 0x02. + if (Header->BigEndian) + BigUShort(&GroupNum); + else + UShort(&GroupNum); + + return GroupNum; +} + + +ILuint GetShort(DICOMHEAD *Header, ILushort GroupNum) +{ + ILushort Num; + + iread(&Num, 1, 2); + // The 0x02 group is always little endian. + if (GroupNum == 0x02) { + UShort(&Num); + return Num; + } + // Now we have to swizzle it if it is not 0x02. + if (Header->BigEndian) + BigUShort(&Num); + else + UShort(&Num); + + return Num; +} + + +ILuint GetInt(DICOMHEAD *Header, ILushort GroupNum) +{ + ILuint Num; + + iread(&Num, 1, 4); + // The 0x02 group is always little endian. + if (GroupNum == 0x02) { + UInt(&Num); + return Num; + } + // Now we have to swizzle it if it is not 0x02. + if (Header->BigEndian) + BigUInt(&Num); + else + UInt(&Num); + + return Num; +} + + +ILfloat GetFloat(DICOMHEAD *Header, ILushort GroupNum) +{ + ILfloat Num; + + iread(&Num, 1, 4); + // The 0x02 group is always little endian. + if (GroupNum == 0x02) { + Float(&Num); + return Num; + } + // Now we have to swizzle it if it is not 0x02. + if (Header->BigEndian) + BigFloat(&Num); + else + Float(&Num); + + return Num; +} + + +ILboolean GetNumericValue(DICOMHEAD *Header, ILushort GroupNum, ILuint *Number) +{ + ILubyte VR1, VR2; + ILushort ValLen; + + // 2 byte character string telling what type this element is ('OB', 'UI', etc.) + VR1 = igetc(); + VR2 = igetc(); + + if (VR1 == 'U' && VR2 == 'S') { // Unsigned short + ValLen = GetShort(Header, GroupNum);//GetLittleUShort(); + if (ValLen != 2) // Must always be 2 for short ('US') + return IL_FALSE; + *((ILushort*)Number) = GetShort(Header, GroupNum);//GetLittleUShort(); + return IL_TRUE; + } + if (VR1 == 'U' && VR2 == 'L') { // Unsigned long + ValLen = GetInt(Header, GroupNum);//GetLittleUInt(); + if (ValLen != 4) // Must always be 4 for long ('UL') + return IL_FALSE; + *Number = GetInt(Header, GroupNum); + return IL_TRUE; + } + if (VR1 == 'S' && VR2 == 'S') { // Signed short + ValLen = GetShort(Header, GroupNum); + if (ValLen != 2) // Must always be 2 for short ('US') + return IL_FALSE; + *((ILshort*)Number) = GetShort(Header, GroupNum); + return IL_TRUE; + } + if (VR1 == 'S' && VR2 == 'L') { // Signed long + ValLen = GetInt(Header, GroupNum); + if (ValLen != 4) // Must always be 4 for long ('UL') + return IL_FALSE; + *((ILint*)Number) = GetInt(Header, GroupNum); + return IL_TRUE; + } + + return IL_FALSE; +} + + +ILboolean GetUID(ILubyte *UID) +{ + ILubyte VR1, VR2; + ILushort ValLen; + + // 2 byte character string telling what type this element is ('OB', 'UI', etc.) + VR1 = igetc(); + VR2 = igetc(); + + if (VR1 != 'U' || VR2 != 'I') // 'UI' == UID + return IL_FALSE; + + ValLen = GetLittleUShort(); + if (ValLen > 64) + return IL_FALSE; + if (iread(UID, ValLen, 1) != 1) + return IL_FALSE; + UID[ValLen] = 0; // Just to make sure that our string is terminated. + + return IL_TRUE; +} + +// Internal function used to check if the HEADER is a valid DICOM header. +ILboolean iCheckDicom(DICOMHEAD *Header) +{ + // Always has the signature "DICM" at position 0x80. + if (strncmp(Header->Signature, "DICM", 4)) + return IL_FALSE; + // Does not make sense to have any dimension = 0. + if (Header->Width == 0 || Header->Height == 0 || Header->Depth == 0) + return IL_FALSE; + // We can only deal with images that have byte-aligned data. + //@TODO: Take care of any others? + if (Header->BitsAllocated % 8) + return IL_FALSE; + // Check for an invalid format being set (or not set at all). + if (ilGetBppFormat(Header->Format) == 0) + return IL_FALSE; + // Check for an invalid type being set (or not set at all). + if (ilGetBpcType(Header->Type) == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Reads a DICOM file +ILboolean ilLoadDicom(ILconst_string FileName) +{ + ILHANDLE DicomFile; + ILboolean bDicom = IL_FALSE; + + DicomFile = iopenr(FileName); + if (DicomFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDicom; + } + + bDicom = ilLoadDicomF(DicomFile); + icloser(DicomFile); + + return bDicom; +} + + +//! Reads an already-opened DICOM file +ILboolean ilLoadDicomF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDicomInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a DICOM +ILboolean ilLoadDicomL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadDicomInternal(); +} + + +// Internal function used to load the DICOM. +ILboolean iLoadDicomInternal(void) +{ + DICOMHEAD Header; + ILuint i; + ILushort TempS, *ShortPtr; + ILfloat TempF, *FloatPtr; + ILboolean Swizzle = IL_FALSE; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + // Clear the header to all 0s to make checks later easier. + memset(&Header, 0, sizeof(DICOMHEAD)); + if (!iGetDicomHead(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!iCheckDicom(&Header)) + return IL_FALSE; + + if (!ilTexImage(Header.Width, Header.Height, Header.Depth, ilGetBppFormat(Header.Format), Header.Format, Header.Type, NULL)) + return IL_FALSE; + //@TODO: Find out if the origin is always in the upper left. + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + // Header.DataLen may be larger than SizeOfData, since it has to be padded with a NULL if it is not an even length, + // so we just test to make sure it is at least large enough. + //@TODO: Do this check before ilTexImage call. + if (Header.DataLen < iCurImage->SizeOfData) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // We may have to swap the order of the data. +#ifdef __BIG_ENDIAN__ + if (!Header.BigEndian) { + if (Header.Format == IL_RGB) + Header.Format = IL_BGR; + else if (Header.Format == IL_RGBA) + Swizzle = IL_TRUE; + } +#else // Little endian + if (Header.BigEndian) { + if (Header.Format == IL_RGB) + Header.Format = IL_BGR; + if (Header.Format == IL_RGBA) + Swizzle = IL_TRUE; + } +#endif + + switch (Header.Type) + { + case IL_UNSIGNED_BYTE: + if (iread(iCurImage->Data, iCurImage->SizeOfData, 1) != 1) + return IL_FALSE; + + // Swizzle the data from ABGR to RGBA. + if (Swizzle) { + for (i = 0; i < iCurImage->SizeOfData; i += 4) { + iSwapUInt((ILuint*)(iCurImage->Data + i)); + } + } + break; + + case IL_UNSIGNED_SHORT: + for (i = 0; i < iCurImage->SizeOfData; i += 2) { + *((ILushort*)(iCurImage->Data + i)) = GetShort(&Header, 0);//GetLittleUShort(); + } + + // Swizzle the data from ABGR to RGBA. + if (Swizzle) { + ShortPtr = (ILushort*)iCurImage->Data; + for (i = 0; i < iCurImage->SizeOfData / 2; i += 4) { + TempS = ShortPtr[i]; + ShortPtr[i] = ShortPtr[i+3]; + ShortPtr[i+3] = TempS; + } + } + break; + + case IL_FLOAT: + for (i = 0; i < iCurImage->SizeOfData; i += 4) { + *((ILfloat*)(iCurImage->Data + i)) = GetFloat(&Header, 0);//GetLittleFloat(); + } + + // Swizzle the data from ABGR to RGBA. + if (Swizzle) { + FloatPtr = (ILfloat*)iCurImage->Data; + for (i = 0; i < iCurImage->SizeOfData / 4; i += 4) { + TempF = FloatPtr[i]; + FloatPtr[i] = FloatPtr[i+3]; + FloatPtr[i+3] = TempF; + } + } + break; + } + + return ilFixImage(); +} + + + +#endif//IL_NO_DICOM diff --git a/DevIL/src-IL/src/il_doom.c b/DevIL/src-IL/src/il_doom.c deleted file mode 100644 index d032f24d..00000000 --- a/DevIL/src-IL/src/il_doom.c +++ /dev/null @@ -1,271 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_doom.c -// -// Description: Reads Doom textures and flats -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_DOOM -#include "il_pal.h" -#include "il_doompal.h" - - -ILboolean iLoadDoomInternal(void); -ILboolean iLoadDoomFlatInternal(void); - - -// -// READ A DOOM IMAGE -// - -//! Reads a Doom file -ILboolean ilLoadDoom(ILconst_string FileName) -{ - ILHANDLE DoomFile; - ILboolean bDoom = IL_FALSE; - - // Not sure of any kind of specified extension...maybe .lmp? - /*if (!iCheckExtension(FileName, "")) { - ilSetError(IL_INVALID_EXTENSION); - return NULL; - }*/ - - DoomFile = iopenr(FileName); - if (DoomFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDoom; - } - - bDoom = ilLoadDoomF(DoomFile); - icloser(DoomFile); - - return bDoom; -} - - -//! Reads an already-opened Doom file -ILboolean ilLoadDoomF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDoomInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Doom texture -ILboolean ilLoadDoomL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadDoomInternal(); -} - - -// From the DTE sources (mostly by Denton Woods with corrections by Randy Heit) -ILboolean iLoadDoomInternal() -{ - ILshort width, height, graphic_header[2], column_loop, row_loop; - ILint column_offset, pointer_position, first_pos; - ILubyte post, topdelta, length; - ILubyte *NewData; - ILuint i; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - first_pos = itell(); // Needed to go back to the offset table - width = GetLittleShort(); - height = GetLittleShort(); - graphic_header[0] = GetLittleShort(); // Not even used - graphic_header[1] = GetLittleShort(); // Not even used - - if (!ilTexImage(width, height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE; - iCurImage->Pal.PalType = IL_PAL_RGB24; - memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE); - - // 247 is always the transparent colour (usually cyan) - memset(iCurImage->Data, 247, iCurImage->SizeOfData); - - for (column_loop = 0; column_loop < width; column_loop++) { - column_offset = GetLittleInt(); - pointer_position = itell(); - iseek(first_pos + column_offset, IL_SEEK_SET); - - while (1) { - if (iread(&topdelta, 1, 1) != 1) - return IL_FALSE; - if (topdelta == 255) - break; - if (iread(&length, 1, 1) != 1) - return IL_FALSE; - if (iread(&post, 1, 1) != 1) - return IL_FALSE; // Skip extra byte for scaling - - for (row_loop = 0; row_loop < length; row_loop++) { - if (iread(&post, 1, 1) != 1) - return IL_FALSE; - if (row_loop + topdelta < height) - iCurImage->Data[(row_loop+topdelta) * width + column_loop] = post; - } - iread(&post, 1, 1); // Skip extra scaling byte - } - - iseek(pointer_position, IL_SEEK_SET); - } - - // Converts palette entry 247 (cyan) to transparent. - if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { - NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4); - if (NewData == NULL) { - return IL_FALSE; - } - - for (i = 0; i < iCurImage->SizeOfData; i++) { - NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0; - } - - if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, - 4, IL_RGBA, iCurImage->Type, NewData)) { - ifree(NewData); - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - ifree(NewData); - } - - return ilFixImage(); -} - - -// -// READ A DOOM FLAT -// - -//! Reads a Doom flat file -ILboolean ilLoadDoomFlat(ILconst_string FileName) -{ - ILHANDLE FlatFile; - ILboolean bFlat = IL_FALSE; - - // Not sure of any kind of specified extension...maybe .lmp? - /*if (!iCheckExtension(FileName, "")) { - ilSetError(IL_INVALID_EXTENSION); - return NULL; - }*/ - - FlatFile = iopenr(FileName); - if (FlatFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bFlat; - } - - bFlat = ilLoadDoomF(FlatFile); - icloser(FlatFile); - - return bFlat; -} - - -//! Reads an already-opened Doom flat file -ILboolean ilLoadDoomFlatF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDoomFlatInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Doom flat -ILboolean ilLoadDoomFlatL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadDoomFlatInternal(); -} - - -// Basically just ireads 4096 bytes and copies the palette -ILboolean iLoadDoomFlatInternal() -{ - ILubyte *NewData; - ILuint i; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!ilTexImage(64, 64, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE; - iCurImage->Pal.PalType = IL_PAL_RGB24; - memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE); - - if (iread(iCurImage->Data, 1, 4096) != 4096) - return IL_FALSE; - - if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { - NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4); - if (NewData == NULL) { - return IL_FALSE; - } - - for (i = 0; i < iCurImage->SizeOfData; i++) { - NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0; - } - - if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, - 4, IL_RGBA, iCurImage->Type, NewData)) { - ifree(NewData); - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - ifree(NewData); - } - - return ilFixImage(); -} - - -#endif diff --git a/DevIL/src-IL/src/il_doom.cpp b/DevIL/src-IL/src/il_doom.cpp new file mode 100644 index 00000000..d032f24d --- /dev/null +++ b/DevIL/src-IL/src/il_doom.cpp @@ -0,0 +1,271 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_doom.c +// +// Description: Reads Doom textures and flats +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_DOOM +#include "il_pal.h" +#include "il_doompal.h" + + +ILboolean iLoadDoomInternal(void); +ILboolean iLoadDoomFlatInternal(void); + + +// +// READ A DOOM IMAGE +// + +//! Reads a Doom file +ILboolean ilLoadDoom(ILconst_string FileName) +{ + ILHANDLE DoomFile; + ILboolean bDoom = IL_FALSE; + + // Not sure of any kind of specified extension...maybe .lmp? + /*if (!iCheckExtension(FileName, "")) { + ilSetError(IL_INVALID_EXTENSION); + return NULL; + }*/ + + DoomFile = iopenr(FileName); + if (DoomFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDoom; + } + + bDoom = ilLoadDoomF(DoomFile); + icloser(DoomFile); + + return bDoom; +} + + +//! Reads an already-opened Doom file +ILboolean ilLoadDoomF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDoomInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Doom texture +ILboolean ilLoadDoomL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadDoomInternal(); +} + + +// From the DTE sources (mostly by Denton Woods with corrections by Randy Heit) +ILboolean iLoadDoomInternal() +{ + ILshort width, height, graphic_header[2], column_loop, row_loop; + ILint column_offset, pointer_position, first_pos; + ILubyte post, topdelta, length; + ILubyte *NewData; + ILuint i; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + first_pos = itell(); // Needed to go back to the offset table + width = GetLittleShort(); + height = GetLittleShort(); + graphic_header[0] = GetLittleShort(); // Not even used + graphic_header[1] = GetLittleShort(); // Not even used + + if (!ilTexImage(width, height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE; + iCurImage->Pal.PalType = IL_PAL_RGB24; + memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE); + + // 247 is always the transparent colour (usually cyan) + memset(iCurImage->Data, 247, iCurImage->SizeOfData); + + for (column_loop = 0; column_loop < width; column_loop++) { + column_offset = GetLittleInt(); + pointer_position = itell(); + iseek(first_pos + column_offset, IL_SEEK_SET); + + while (1) { + if (iread(&topdelta, 1, 1) != 1) + return IL_FALSE; + if (topdelta == 255) + break; + if (iread(&length, 1, 1) != 1) + return IL_FALSE; + if (iread(&post, 1, 1) != 1) + return IL_FALSE; // Skip extra byte for scaling + + for (row_loop = 0; row_loop < length; row_loop++) { + if (iread(&post, 1, 1) != 1) + return IL_FALSE; + if (row_loop + topdelta < height) + iCurImage->Data[(row_loop+topdelta) * width + column_loop] = post; + } + iread(&post, 1, 1); // Skip extra scaling byte + } + + iseek(pointer_position, IL_SEEK_SET); + } + + // Converts palette entry 247 (cyan) to transparent. + if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { + NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4); + if (NewData == NULL) { + return IL_FALSE; + } + + for (i = 0; i < iCurImage->SizeOfData; i++) { + NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0; + } + + if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, + 4, IL_RGBA, iCurImage->Type, NewData)) { + ifree(NewData); + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ifree(NewData); + } + + return ilFixImage(); +} + + +// +// READ A DOOM FLAT +// + +//! Reads a Doom flat file +ILboolean ilLoadDoomFlat(ILconst_string FileName) +{ + ILHANDLE FlatFile; + ILboolean bFlat = IL_FALSE; + + // Not sure of any kind of specified extension...maybe .lmp? + /*if (!iCheckExtension(FileName, "")) { + ilSetError(IL_INVALID_EXTENSION); + return NULL; + }*/ + + FlatFile = iopenr(FileName); + if (FlatFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bFlat; + } + + bFlat = ilLoadDoomF(FlatFile); + icloser(FlatFile); + + return bFlat; +} + + +//! Reads an already-opened Doom flat file +ILboolean ilLoadDoomFlatF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDoomFlatInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Doom flat +ILboolean ilLoadDoomFlatL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadDoomFlatInternal(); +} + + +// Basically just ireads 4096 bytes and copies the palette +ILboolean iLoadDoomFlatInternal() +{ + ILubyte *NewData; + ILuint i; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!ilTexImage(64, 64, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE; + iCurImage->Pal.PalType = IL_PAL_RGB24; + memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE); + + if (iread(iCurImage->Data, 1, 4096) != 4096) + return IL_FALSE; + + if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { + NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4); + if (NewData == NULL) { + return IL_FALSE; + } + + for (i = 0; i < iCurImage->SizeOfData; i++) { + NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0; + } + + if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, + 4, IL_RGBA, iCurImage->Type, NewData)) { + ifree(NewData); + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ifree(NewData); + } + + return ilFixImage(); +} + + +#endif diff --git a/DevIL/src-IL/src/il_dpx.c b/DevIL/src-IL/src/il_dpx.c deleted file mode 100644 index bcc21035..00000000 --- a/DevIL/src-IL/src/il_dpx.c +++ /dev/null @@ -1,325 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/26/2009 -// -// Filename: src-IL/src/il_dpx.c -// -// Description: Reads from a Digital Picture Exchange (.dpx) file. -// Specifications for this format were found at -// http://www.cineon.com/ff_draft.php and -// http://www.fileformat.info/format/dpx/. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_DPX -#include "il_dpx.h" -#include "il_bits.h" - -ILboolean iLoadDpxInternal(void); - - -//! Reads a DPX file -ILboolean ilLoadDpx(ILconst_string FileName) -{ - ILHANDLE DpxFile; - ILboolean bDpx = IL_FALSE; - - DpxFile = iopenr(FileName); - if (DpxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bDpx; - } - - bDpx = ilLoadDpxF(DpxFile); - icloser(DpxFile); - - return bDpx; -} - - -//! Reads an already-opened DPX file -ILboolean ilLoadDpxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDpxInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a DPX -ILboolean ilLoadDpxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadDpxInternal(); -} - - -ILboolean DpxGetFileInfo(DPX_FILE_INFO *FileInfo) -{ - //if (iread(FileInfo, 768, 1) != 1) - // return IL_FALSE; - - FileInfo->MagicNum = GetBigUInt(); - FileInfo->Offset = GetBigUInt(); - iread(FileInfo->Vers, 8, 1); - FileInfo->FileSize = GetBigUInt(); - FileInfo->DittoKey = GetBigUInt(); - FileInfo->GenHdrSize = GetBigUInt(); - FileInfo->IndHdrSize = GetBigUInt(); - FileInfo->UserDataSize = GetBigUInt(); - iread(FileInfo->FileName, 100, 1); - iread(FileInfo->CreateTime, 24, 1); - iread(FileInfo->Creator, 100, 1); - iread(FileInfo->Project, 200, 1); - if (iread(FileInfo->Copyright, 200, 1) != 1) - return IL_FALSE; - FileInfo->Key = GetBigUInt(); - iseek(104, IL_SEEK_CUR); // Skip reserved section. - - return IL_TRUE; -} - - -ILboolean GetImageElement(DPX_IMAGE_ELEMENT *ImageElement) -{ - ImageElement->DataSign = GetBigUInt(); - ImageElement->RefLowData = GetBigUInt(); - iread(&ImageElement->RefLowQuantity, 1, 4); - ImageElement->RefHighData = GetBigUInt(); - iread(&ImageElement->RefHighQuantity, 1, 4); - ImageElement->Descriptor = igetc(); - ImageElement->Transfer = igetc(); - ImageElement->Colorimetric = igetc(); - ImageElement->BitSize = igetc(); - ImageElement->Packing = GetBigUShort(); - ImageElement->Encoding = GetBigUShort(); - ImageElement->DataOffset = GetBigUInt(); - ImageElement->EolPadding = GetBigUInt(); - ImageElement->EoImagePadding = GetBigUInt(); - if (iread(ImageElement->Description, 32, 1) != 1) - return IL_FALSE; - - return IL_TRUE; -} - - -ILboolean DpxGetImageInfo(DPX_IMAGE_INFO *ImageInfo) -{ - ILuint i; - - //if (iread(ImageInfo, sizeof(DPX_IMAGE_INFO), 1) != 1) - // return IL_FALSE; - ImageInfo->Orientation = GetBigUShort(); - ImageInfo->NumElements = GetBigUShort(); - ImageInfo->Width = GetBigUInt(); - ImageInfo->Height = GetBigUInt(); - - for (i = 0; i < 8; i++) { - GetImageElement(&ImageInfo->ImageElement[i]); - } - - iseek(52, IL_SEEK_CUR); // Skip padding bytes. - - return IL_TRUE; -} - - -ILboolean DpxGetImageOrient(DPX_IMAGE_ORIENT *ImageOrient) -{ - ImageOrient->XOffset = GetBigUInt(); - ImageOrient->YOffset = GetBigUInt(); - iread(&ImageOrient->XCenter, 4, 1); - iread(&ImageOrient->YCenter, 4, 1); - ImageOrient->XOrigSize = GetBigUInt(); - ImageOrient->YOrigSize = GetBigUInt(); - iread(ImageOrient->FileName, 100, 1); - iread(ImageOrient->CreationTime, 24, 1); - iread(ImageOrient->InputDev, 32, 1); - if (iread(ImageOrient->InputSerial, 32, 1) != 1) - return IL_FALSE; - ImageOrient->Border[0] = GetBigUShort(); - ImageOrient->Border[1] = GetBigUShort(); - ImageOrient->Border[2] = GetBigUShort(); - ImageOrient->Border[3] = GetBigUShort(); - ImageOrient->PixelAspect[0] = GetBigUInt(); - ImageOrient->PixelAspect[1] = GetBigUInt(); - iseek(28, IL_SEEK_CUR); // Skip reserved bytes. - - return IL_TRUE; -} - - -// Internal function used to load the DPX. -ILboolean iLoadDpxInternal(void) -{ - DPX_FILE_INFO FileInfo; - DPX_IMAGE_INFO ImageInfo; - DPX_IMAGE_ORIENT ImageOrient; -// BITFILE *File; - ILuint i, NumElements, CurElem = 0; - ILushort Val, *ShortData; - ILubyte Data[8]; - ILenum Format = 0; - ILubyte NumChans = 0; - - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!DpxGetFileInfo(&FileInfo)) - return IL_FALSE; - if (!DpxGetImageInfo(&ImageInfo)) - return IL_FALSE; - if (!DpxGetImageOrient(&ImageOrient)) - return IL_FALSE; - - iseek(ImageInfo.ImageElement[CurElem].DataOffset, IL_SEEK_SET); - -//@TODO: Deal with different origins! - - switch (ImageInfo.ImageElement[CurElem].Descriptor) - { - case 6: // Luminance data - Format = IL_LUMINANCE; - NumChans = 1; - break; - case 50: // RGB data - Format = IL_RGB; - NumChans = 3; - break; - case 51: // RGBA data - Format = IL_RGBA; - NumChans = 4; - break; - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - // These are all on nice word boundaries. - switch (ImageInfo.ImageElement[CurElem].BitSize) - { - case 8: - case 16: - case 32: - if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, NumChans, Format, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - if (iread(iCurImage->Data, iCurImage->SizeOfData, 1) != 1) - return IL_FALSE; - goto finish; - } - - // The rest of these do not end on word boundaries. - if (ImageInfo.ImageElement[CurElem].Packing == 1) { - // Here we have it padded out to a word boundary, so the extra bits are filler. - switch (ImageInfo.ImageElement[CurElem].BitSize) - { - case 10: - //@TODO: Support other formats! - /*if (Format != IL_RGB) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - }*/ - switch (Format) - { - case IL_LUMINANCE: - if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - ShortData = (ILushort*)iCurImage->Data; - NumElements = iCurImage->SizeOfData / 2; - - for (i = 0; i < NumElements;) { - iread(Data, 1, 2); - Val = ((Data[0] << 2) + ((Data[1] & 0xC0) >> 6)) << 6; // Use the first 10 bits of the word-aligned data. - ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. - } - break; - - case IL_RGB: - if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 3, IL_RGB, IL_UNSIGNED_SHORT, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - ShortData = (ILushort*)iCurImage->Data; - NumElements = iCurImage->SizeOfData / 2; - - for (i = 0; i < NumElements;) { - iread(Data, 1, 4); - Val = ((Data[0] << 2) + ((Data[1] & 0xC0) >> 6)) << 6; // Use the first 10 bits of the word-aligned data. - ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. - Val = (((Data[1] & 0x3F) << 4) + ((Data[2] & 0xF0) >> 4)) << 6; // Use the next 10 bits. - ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Same fill - Val = (((Data[2] & 0x0F) << 6) + ((Data[3] & 0xFC) >> 2)) << 6; // And finally use the last 10 bits (ignores the last 2 bits). - ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Same fill - } - break; - - case IL_RGBA: // Is this even a possibility? There is a ton of wasted space here! - if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 4, IL_RGBA, IL_UNSIGNED_SHORT, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - ShortData = (ILushort*)iCurImage->Data; - NumElements = iCurImage->SizeOfData / 2; - - for (i = 0; i < NumElements;) { - iread(Data, 1, 8); - Val = (Data[0] << 2) + ((Data[1] & 0xC0) >> 6); // Use the first 10 bits of the word-aligned data. - ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. - Val = ((Data[1] & 0x3F) << 4) + ((Data[2] & 0xF0) >> 4); // Use the next 10 bits. - ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Same fill - Val = ((Data[2] & 0x0F) << 6) + ((Data[3] & 0xFC) >> 2); // Use the next 10 bits. - ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Same fill - Val = ((Data[3] & 0x03) << 8) + Data[4]; // And finally use the last 10 relevant bits (skips 3 whole bytes worth of padding!). - ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Last fill - } - break; - } - break; - - //case 1: - //case 12: - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - } - else if (ImageInfo.ImageElement[0].Packing == 0) { - // Here we have the data packed so that it is never aligned on a word boundary. - /*File = bfile(iGetFile()); - if (File == NULL) - return IL_FALSE; //@TODO: Error? - ShortData = (ILushort*)iCurImage->Data; - NumElements = iCurImage->SizeOfData / 2; - for (i = 0; i < NumElements; i++) { - //bread(&Val, 1, 10, File); - Val = breadVal(10, File); - ShortData[i] = (Val << 6) | (Val >> 4); - } - bclose(File);*/ - - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - else { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; //@TODO: Take care of this in an iCheckDpx* function. - } - -finish: - return ilFixImage(); -} - -#endif//IL_NO_DPX - diff --git a/DevIL/src-IL/src/il_dpx.cpp b/DevIL/src-IL/src/il_dpx.cpp new file mode 100644 index 00000000..bcc21035 --- /dev/null +++ b/DevIL/src-IL/src/il_dpx.cpp @@ -0,0 +1,325 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/26/2009 +// +// Filename: src-IL/src/il_dpx.c +// +// Description: Reads from a Digital Picture Exchange (.dpx) file. +// Specifications for this format were found at +// http://www.cineon.com/ff_draft.php and +// http://www.fileformat.info/format/dpx/. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_DPX +#include "il_dpx.h" +#include "il_bits.h" + +ILboolean iLoadDpxInternal(void); + + +//! Reads a DPX file +ILboolean ilLoadDpx(ILconst_string FileName) +{ + ILHANDLE DpxFile; + ILboolean bDpx = IL_FALSE; + + DpxFile = iopenr(FileName); + if (DpxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bDpx; + } + + bDpx = ilLoadDpxF(DpxFile); + icloser(DpxFile); + + return bDpx; +} + + +//! Reads an already-opened DPX file +ILboolean ilLoadDpxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDpxInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a DPX +ILboolean ilLoadDpxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadDpxInternal(); +} + + +ILboolean DpxGetFileInfo(DPX_FILE_INFO *FileInfo) +{ + //if (iread(FileInfo, 768, 1) != 1) + // return IL_FALSE; + + FileInfo->MagicNum = GetBigUInt(); + FileInfo->Offset = GetBigUInt(); + iread(FileInfo->Vers, 8, 1); + FileInfo->FileSize = GetBigUInt(); + FileInfo->DittoKey = GetBigUInt(); + FileInfo->GenHdrSize = GetBigUInt(); + FileInfo->IndHdrSize = GetBigUInt(); + FileInfo->UserDataSize = GetBigUInt(); + iread(FileInfo->FileName, 100, 1); + iread(FileInfo->CreateTime, 24, 1); + iread(FileInfo->Creator, 100, 1); + iread(FileInfo->Project, 200, 1); + if (iread(FileInfo->Copyright, 200, 1) != 1) + return IL_FALSE; + FileInfo->Key = GetBigUInt(); + iseek(104, IL_SEEK_CUR); // Skip reserved section. + + return IL_TRUE; +} + + +ILboolean GetImageElement(DPX_IMAGE_ELEMENT *ImageElement) +{ + ImageElement->DataSign = GetBigUInt(); + ImageElement->RefLowData = GetBigUInt(); + iread(&ImageElement->RefLowQuantity, 1, 4); + ImageElement->RefHighData = GetBigUInt(); + iread(&ImageElement->RefHighQuantity, 1, 4); + ImageElement->Descriptor = igetc(); + ImageElement->Transfer = igetc(); + ImageElement->Colorimetric = igetc(); + ImageElement->BitSize = igetc(); + ImageElement->Packing = GetBigUShort(); + ImageElement->Encoding = GetBigUShort(); + ImageElement->DataOffset = GetBigUInt(); + ImageElement->EolPadding = GetBigUInt(); + ImageElement->EoImagePadding = GetBigUInt(); + if (iread(ImageElement->Description, 32, 1) != 1) + return IL_FALSE; + + return IL_TRUE; +} + + +ILboolean DpxGetImageInfo(DPX_IMAGE_INFO *ImageInfo) +{ + ILuint i; + + //if (iread(ImageInfo, sizeof(DPX_IMAGE_INFO), 1) != 1) + // return IL_FALSE; + ImageInfo->Orientation = GetBigUShort(); + ImageInfo->NumElements = GetBigUShort(); + ImageInfo->Width = GetBigUInt(); + ImageInfo->Height = GetBigUInt(); + + for (i = 0; i < 8; i++) { + GetImageElement(&ImageInfo->ImageElement[i]); + } + + iseek(52, IL_SEEK_CUR); // Skip padding bytes. + + return IL_TRUE; +} + + +ILboolean DpxGetImageOrient(DPX_IMAGE_ORIENT *ImageOrient) +{ + ImageOrient->XOffset = GetBigUInt(); + ImageOrient->YOffset = GetBigUInt(); + iread(&ImageOrient->XCenter, 4, 1); + iread(&ImageOrient->YCenter, 4, 1); + ImageOrient->XOrigSize = GetBigUInt(); + ImageOrient->YOrigSize = GetBigUInt(); + iread(ImageOrient->FileName, 100, 1); + iread(ImageOrient->CreationTime, 24, 1); + iread(ImageOrient->InputDev, 32, 1); + if (iread(ImageOrient->InputSerial, 32, 1) != 1) + return IL_FALSE; + ImageOrient->Border[0] = GetBigUShort(); + ImageOrient->Border[1] = GetBigUShort(); + ImageOrient->Border[2] = GetBigUShort(); + ImageOrient->Border[3] = GetBigUShort(); + ImageOrient->PixelAspect[0] = GetBigUInt(); + ImageOrient->PixelAspect[1] = GetBigUInt(); + iseek(28, IL_SEEK_CUR); // Skip reserved bytes. + + return IL_TRUE; +} + + +// Internal function used to load the DPX. +ILboolean iLoadDpxInternal(void) +{ + DPX_FILE_INFO FileInfo; + DPX_IMAGE_INFO ImageInfo; + DPX_IMAGE_ORIENT ImageOrient; +// BITFILE *File; + ILuint i, NumElements, CurElem = 0; + ILushort Val, *ShortData; + ILubyte Data[8]; + ILenum Format = 0; + ILubyte NumChans = 0; + + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!DpxGetFileInfo(&FileInfo)) + return IL_FALSE; + if (!DpxGetImageInfo(&ImageInfo)) + return IL_FALSE; + if (!DpxGetImageOrient(&ImageOrient)) + return IL_FALSE; + + iseek(ImageInfo.ImageElement[CurElem].DataOffset, IL_SEEK_SET); + +//@TODO: Deal with different origins! + + switch (ImageInfo.ImageElement[CurElem].Descriptor) + { + case 6: // Luminance data + Format = IL_LUMINANCE; + NumChans = 1; + break; + case 50: // RGB data + Format = IL_RGB; + NumChans = 3; + break; + case 51: // RGBA data + Format = IL_RGBA; + NumChans = 4; + break; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + // These are all on nice word boundaries. + switch (ImageInfo.ImageElement[CurElem].BitSize) + { + case 8: + case 16: + case 32: + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, NumChans, Format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + if (iread(iCurImage->Data, iCurImage->SizeOfData, 1) != 1) + return IL_FALSE; + goto finish; + } + + // The rest of these do not end on word boundaries. + if (ImageInfo.ImageElement[CurElem].Packing == 1) { + // Here we have it padded out to a word boundary, so the extra bits are filler. + switch (ImageInfo.ImageElement[CurElem].BitSize) + { + case 10: + //@TODO: Support other formats! + /*if (Format != IL_RGB) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + }*/ + switch (Format) + { + case IL_LUMINANCE: + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + + for (i = 0; i < NumElements;) { + iread(Data, 1, 2); + Val = ((Data[0] << 2) + ((Data[1] & 0xC0) >> 6)) << 6; // Use the first 10 bits of the word-aligned data. + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. + } + break; + + case IL_RGB: + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 3, IL_RGB, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + + for (i = 0; i < NumElements;) { + iread(Data, 1, 4); + Val = ((Data[0] << 2) + ((Data[1] & 0xC0) >> 6)) << 6; // Use the first 10 bits of the word-aligned data. + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. + Val = (((Data[1] & 0x3F) << 4) + ((Data[2] & 0xF0) >> 4)) << 6; // Use the next 10 bits. + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Same fill + Val = (((Data[2] & 0x0F) << 6) + ((Data[3] & 0xFC) >> 2)) << 6; // And finally use the last 10 bits (ignores the last 2 bits). + ShortData[i++] = Val | ((Val & 0x3F0) >> 4); // Same fill + } + break; + + case IL_RGBA: // Is this even a possibility? There is a ton of wasted space here! + if (!ilTexImage(ImageInfo.Width, ImageInfo.Height, 1, 4, IL_RGBA, IL_UNSIGNED_SHORT, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + + for (i = 0; i < NumElements;) { + iread(Data, 1, 8); + Val = (Data[0] << 2) + ((Data[1] & 0xC0) >> 6); // Use the first 10 bits of the word-aligned data. + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Fill in the lower 6 bits with a copy of the higher bits. + Val = ((Data[1] & 0x3F) << 4) + ((Data[2] & 0xF0) >> 4); // Use the next 10 bits. + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Same fill + Val = ((Data[2] & 0x0F) << 6) + ((Data[3] & 0xFC) >> 2); // Use the next 10 bits. + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Same fill + Val = ((Data[3] & 0x03) << 8) + Data[4]; // And finally use the last 10 relevant bits (skips 3 whole bytes worth of padding!). + ShortData[i++] = (Val << 6) | ((Val & 0x3F0) >> 4); // Last fill + } + break; + } + break; + + //case 1: + //case 12: + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + } + else if (ImageInfo.ImageElement[0].Packing == 0) { + // Here we have the data packed so that it is never aligned on a word boundary. + /*File = bfile(iGetFile()); + if (File == NULL) + return IL_FALSE; //@TODO: Error? + ShortData = (ILushort*)iCurImage->Data; + NumElements = iCurImage->SizeOfData / 2; + for (i = 0; i < NumElements; i++) { + //bread(&Val, 1, 10, File); + Val = breadVal(10, File); + ShortData[i] = (Val << 6) | (Val >> 4); + } + bclose(File);*/ + + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + else { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; //@TODO: Take care of this in an iCheckDpx* function. + } + +finish: + return ilFixImage(); +} + +#endif//IL_NO_DPX + diff --git a/DevIL/src-IL/src/il_endian.c b/DevIL/src-IL/src/il_endian.c deleted file mode 100644 index 60a42f19..00000000 --- a/DevIL/src-IL/src/il_endian.c +++ /dev/null @@ -1,546 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Last modified: 12/06/2006 -// -// Filename: src-IL/src/il_endian.c -// -// Description: Takes care of endian issues -// -//----------------------------------------------------------------------------- - - -#define IL_ENDIAN_C - -#include "il_endian.h" - -void iSwapUShort(ILushort *s) { - #ifdef USE_WIN32_ASM - __asm { - mov ebx, s - mov al, [ebx+1] - mov ah, [ebx ] - mov [ebx], ax - } - #else - #ifdef GCC_X86_ASM - asm("ror $8,%0" - : "=r" (*s) - : "0" (*s)); - #else - *s = ((*s)>>8) | ((*s)<<8); - #endif //GCC_X86_ASM - #endif //USE_WIN32_ASM -} - -void iSwapShort(ILshort *s) { - iSwapUShort((ILushort*)s); -} - -void iSwapUInt(ILuint *i) { - #ifdef USE_WIN32_ASM - __asm { - mov ebx, i - mov eax, [ebx] - bswap eax - mov [ebx], eax - } - #else - #ifdef GCC_X86_ASM - asm("bswap %0;" - : "+r" (*i)); - #else - *i = ((*i)>>24) | (((*i)>>8) & 0xff00) | (((*i)<<8) & 0xff0000) | ((*i)<<24); - #endif //GCC_X86_ASM - #endif //USE_WIN32_ASM -} - -void iSwapInt(ILint *i) { - iSwapUInt((ILuint*)i); -} - -void iSwapFloat(ILfloat *f) { - iSwapUInt((ILuint*)f); -} - -void iSwapDouble(ILdouble *d) { - #ifdef GCC_X86_ASM - int *t = (int*)d; - asm("bswap %2 \n" - "bswap %3 \n" - "movl %2,%1 \n" - "movl %3,%0 \n" - : "=g" (t[0]), "=g" (t[1]) - : "r" (t[0]), "r" (t[1])); - #else - ILubyte t,*b = (ILubyte*)d; - #define dswap(x,y) t=b[x];b[x]=b[y];b[y]=b[x]; - dswap(0,7); - dswap(1,6); - dswap(2,5); - dswap(3,4); - #undef dswap - #endif -} - - -ILushort GetLittleUShort() { - ILushort s; - iread(&s, sizeof(ILushort), 1); -#ifdef __BIG_ENDIAN__ - iSwapUShort(&s); -#endif - return s; -} - -ILshort GetLittleShort() { - ILshort s; - iread(&s, sizeof(ILshort), 1); -#ifdef __BIG_ENDIAN__ - iSwapShort(&s); -#endif - return s; -} - -ILuint GetLittleUInt() { - ILuint i; - iread(&i, sizeof(ILuint), 1); -#ifdef __BIG_ENDIAN__ - iSwapUInt(&i); -#endif - return i; -} - -ILint GetLittleInt() { - ILint i; - iread(&i, sizeof(ILint), 1); -#ifdef __BIG_ENDIAN__ - iSwapInt(&i); -#endif - return i; -} - -ILfloat GetLittleFloat() { - ILfloat f; - iread(&f, sizeof(ILfloat), 1); -#ifdef __BIG_ENDIAN__ - iSwapFloat(&f); -#endif - return f; -} - -ILdouble GetLittleDouble() { - ILdouble d; - iread(&d, sizeof(ILdouble), 1); -#ifdef __BIG_ENDIAN__ - iSwapDouble(&d); -#endif - return d; -} - -ILushort GetBigUShort() { - ILushort s; - iread(&s, sizeof(ILushort), 1); -#ifdef __LITTLE_ENDIAN__ - iSwapUShort(&s); -#endif - return s; -} - -ILshort GetBigShort() { - ILshort s; - iread(&s, sizeof(ILshort), 1); -#ifdef __LITTLE_ENDIAN__ - iSwapShort(&s); -#endif - return s; -} - -ILuint GetBigUInt() { - ILuint i; - iread(&i, sizeof(ILuint), 1); -#ifdef __LITTLE_ENDIAN__ - iSwapUInt(&i); -#endif - return i; -} - -ILint GetBigInt() { - ILint i; - iread(&i, sizeof(ILint), 1); -#ifdef __LITTLE_ENDIAN__ - iSwapInt(&i); -#endif - return i; -} - -ILfloat GetBigFloat() { - ILfloat f; - iread(&f, sizeof(ILfloat), 1); -#ifdef __LITTLE_ENDIAN__ - iSwapFloat(&f); -#endif - return f; -} - -ILdouble GetBigDouble() { - ILdouble d; - iread(&d, sizeof(ILdouble), 1); -#ifdef __LITTLE_ENDIAN__ - iSwapDouble(&d); -#endif - return d; -} - -ILubyte SaveLittleUShort(ILushort s) { -#ifdef __BIG_ENDIAN__ - iSwapUShort(&s); -#endif - return iwrite(&s, sizeof(ILushort), 1); -} - -ILubyte SaveLittleShort(ILshort s) { -#ifdef __BIG_ENDIAN__ - iSwapShort(&s); -#endif - return iwrite(&s, sizeof(ILshort), 1); -} - -ILubyte SaveLittleUInt(ILuint i) { -#ifdef __BIG_ENDIAN__ - iSwapUInt(&i); -#endif - return iwrite(&i, sizeof(ILuint), 1); -} - -ILubyte SaveLittleInt(ILint i) { -#ifdef __BIG_ENDIAN__ - iSwapInt(&i); -#endif - return iwrite(&i, sizeof(ILint), 1); -} - -ILubyte SaveLittleFloat(ILfloat f) { -#ifdef __BIG_ENDIAN__ - iSwapFloat(&f); -#endif - return iwrite(&f, sizeof(ILfloat), 1); -} - -ILubyte SaveLittleDouble(ILdouble d) { -#ifdef __BIG_ENDIAN__ - iSwapDouble(&d); -#endif - return iwrite(&d, sizeof(ILdouble), 1); -} - - -ILubyte SaveBigUShort(ILushort s) { -#ifdef __LITTLE_ENDIAN__ - iSwapUShort(&s); -#endif - return iwrite(&s, sizeof(ILushort), 1); -} - - -ILubyte SaveBigShort(ILshort s) { -#ifdef __LITTLE_ENDIAN__ - iSwapShort(&s); -#endif - return iwrite(&s, sizeof(ILshort), 1); -} - - -ILubyte SaveBigUInt(ILuint i) { -#ifdef __LITTLE_ENDIAN__ - iSwapUInt(&i); -#endif - return iwrite(&i, sizeof(ILuint), 1); -} - - -ILubyte SaveBigInt(ILint i) { -#ifdef __LITTLE_ENDIAN__ - iSwapInt(&i); -#endif - return iwrite(&i, sizeof(ILint), 1); -} - - -ILubyte SaveBigFloat(ILfloat f) { -#ifdef __LITTLE_ENDIAN__ - iSwapFloat(&f); -#endif - return iwrite(&f, sizeof(ILfloat), 1); -} - - -ILubyte SaveBigDouble(ILdouble d) { -#ifdef __LITTLE_ENDIAN__ - iSwapDouble(&d); -#endif - return iwrite(&d, sizeof(ILdouble), 1); -} - -void EndianSwapData(void *_Image) -{ - ILuint i; - ILubyte *temp, *s, *d; - ILushort *ShortS, *ShortD; - ILuint *IntS, *IntD; - ILfloat *FltS, *FltD; - ILdouble *DblS, *DblD; - - ILimage *Image = (ILimage*)_Image; - - switch (Image->Type) { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - switch (Image->Bpp) { - case 3: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - s = Image->Data; - d = temp; - - for( i = Image->Width * Image->Height; i > 0; i-- ) { - *d++ = *(s+2); - *d++ = *(s+1); - *d++ = *s; - s += 3; - } - - ifree(Image->Data); - Image->Data = temp; - break; - - case 4: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - s = Image->Data; - d = temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *d++ = *(s+3); - *d++ = *(s+2); - *d++ = *(s+1); - *d++ = *s; - s += 4; - } - - ifree(Image->Data); - Image->Data = temp; - break; - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - switch (Image->Bpp) { - case 3: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - ShortS = (ILushort*)Image->Data; - ShortD = (ILushort*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *ShortD = *ShortS++; iSwapUShort(ShortD++); - *ShortD = *ShortS++; iSwapUShort(ShortD++); - *ShortD = *ShortS++; iSwapUShort(ShortD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - - case 4: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - ShortS = (ILushort*)Image->Data; - ShortD = (ILushort*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *ShortD = *ShortS++; iSwapUShort(ShortD++); - *ShortD = *ShortS++; iSwapUShort(ShortD++); - *ShortD = *ShortS++; iSwapUShort(ShortD++); - *ShortD = *ShortS++; iSwapUShort(ShortD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - } - break; - - case IL_INT: - case IL_UNSIGNED_INT: - switch (Image->Bpp) - { - case 3: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - IntS = (ILuint*)Image->Data; - IntD = (ILuint*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *IntD = *IntS++; iSwapUInt(IntD++); - *IntD = *IntS++; iSwapUInt(IntD++); - *IntD = *IntS++; iSwapUInt(IntD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - - case 4: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - IntS = (ILuint*)Image->Data; - IntD = (ILuint*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *IntD = *IntS++; iSwapUInt(IntD++); - *IntD = *IntS++; iSwapUInt(IntD++); - *IntD = *IntS++; iSwapUInt(IntD++); - *IntD = *IntS++; iSwapUInt(IntD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - } - break; - - case IL_FLOAT: - switch (Image->Bpp) - { - case 3: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - FltS = (ILfloat*)Image->Data; - FltD = (ILfloat*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *FltD = *FltS++; iSwapFloat(FltD++); - *FltD = *FltS++; iSwapFloat(FltD++); - *FltD = *FltS++; iSwapFloat(FltD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - - case 4: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - FltS = (ILfloat*)Image->Data; - FltD = (ILfloat*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *FltD = *FltS++; iSwapFloat(FltD++); - *FltD = *FltS++; iSwapFloat(FltD++); - *FltD = *FltS++; iSwapFloat(FltD++); - *FltD = *FltS++; iSwapFloat(FltD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - } - break; - - case IL_DOUBLE: - switch (Image->Bpp) - { - case 3: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - DblS = (ILdouble*)Image->Data; - DblD = (ILdouble*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *DblD = *DblS++; iSwapDouble(DblD++); - *DblD = *DblS++; iSwapDouble(DblD++); - *DblD = *DblS++; iSwapDouble(DblD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - - case 4: - temp = (ILubyte*)ialloc(Image->SizeOfData); - if (temp == NULL) - return; - DblS = (ILdouble*)Image->Data; - DblD = (ILdouble*)temp; - - for (i = Image->Width * Image->Height; i > 0; i--) { - *DblD = *DblS++; iSwapDouble(DblD++); - *DblD = *DblS++; iSwapDouble(DblD++); - *DblD = *DblS++; iSwapDouble(DblD++); - *DblD = *DblS++; iSwapDouble(DblD++); - } - - ifree(Image->Data); - Image->Data = temp; - break; - } - break; - } - - if( iCurImage->Format == IL_COLOUR_INDEX ) { - switch (iCurImage->Pal.PalType) { - case IL_PAL_RGB24: - case IL_PAL_BGR24: - temp = (ILubyte*)ialloc(Image->Pal.PalSize); - if (temp == NULL) - return; - s = Image->Pal.Palette; - d = temp; - - for (i = Image->Pal.PalSize / 3; i > 0; i--) { - *d++ = *(s+2); - *d++ = *(s+1); - *d++ = *s; - s += 3; - } - - ifree(Image->Pal.Palette); - Image->Pal.Palette = temp; - break; - - case IL_PAL_RGBA32: - case IL_PAL_RGB32: - case IL_PAL_BGRA32: - case IL_PAL_BGR32: - temp = (ILubyte*)ialloc(Image->Pal.PalSize); - if (temp == NULL) - return; - s = Image->Pal.Palette; - d = temp; - - for (i = Image->Pal.PalSize / 4; i > 0; i--) { - *d++ = *(s+3); - *d++ = *(s+2); - *d++ = *(s+1); - *d++ = *s; - s += 4; - } - - ifree(Image->Pal.Palette); - Image->Pal.Palette = temp; - break; - } - } - return; -} diff --git a/DevIL/src-IL/src/il_endian.cpp b/DevIL/src-IL/src/il_endian.cpp new file mode 100644 index 00000000..60a42f19 --- /dev/null +++ b/DevIL/src-IL/src/il_endian.cpp @@ -0,0 +1,546 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Last modified: 12/06/2006 +// +// Filename: src-IL/src/il_endian.c +// +// Description: Takes care of endian issues +// +//----------------------------------------------------------------------------- + + +#define IL_ENDIAN_C + +#include "il_endian.h" + +void iSwapUShort(ILushort *s) { + #ifdef USE_WIN32_ASM + __asm { + mov ebx, s + mov al, [ebx+1] + mov ah, [ebx ] + mov [ebx], ax + } + #else + #ifdef GCC_X86_ASM + asm("ror $8,%0" + : "=r" (*s) + : "0" (*s)); + #else + *s = ((*s)>>8) | ((*s)<<8); + #endif //GCC_X86_ASM + #endif //USE_WIN32_ASM +} + +void iSwapShort(ILshort *s) { + iSwapUShort((ILushort*)s); +} + +void iSwapUInt(ILuint *i) { + #ifdef USE_WIN32_ASM + __asm { + mov ebx, i + mov eax, [ebx] + bswap eax + mov [ebx], eax + } + #else + #ifdef GCC_X86_ASM + asm("bswap %0;" + : "+r" (*i)); + #else + *i = ((*i)>>24) | (((*i)>>8) & 0xff00) | (((*i)<<8) & 0xff0000) | ((*i)<<24); + #endif //GCC_X86_ASM + #endif //USE_WIN32_ASM +} + +void iSwapInt(ILint *i) { + iSwapUInt((ILuint*)i); +} + +void iSwapFloat(ILfloat *f) { + iSwapUInt((ILuint*)f); +} + +void iSwapDouble(ILdouble *d) { + #ifdef GCC_X86_ASM + int *t = (int*)d; + asm("bswap %2 \n" + "bswap %3 \n" + "movl %2,%1 \n" + "movl %3,%0 \n" + : "=g" (t[0]), "=g" (t[1]) + : "r" (t[0]), "r" (t[1])); + #else + ILubyte t,*b = (ILubyte*)d; + #define dswap(x,y) t=b[x];b[x]=b[y];b[y]=b[x]; + dswap(0,7); + dswap(1,6); + dswap(2,5); + dswap(3,4); + #undef dswap + #endif +} + + +ILushort GetLittleUShort() { + ILushort s; + iread(&s, sizeof(ILushort), 1); +#ifdef __BIG_ENDIAN__ + iSwapUShort(&s); +#endif + return s; +} + +ILshort GetLittleShort() { + ILshort s; + iread(&s, sizeof(ILshort), 1); +#ifdef __BIG_ENDIAN__ + iSwapShort(&s); +#endif + return s; +} + +ILuint GetLittleUInt() { + ILuint i; + iread(&i, sizeof(ILuint), 1); +#ifdef __BIG_ENDIAN__ + iSwapUInt(&i); +#endif + return i; +} + +ILint GetLittleInt() { + ILint i; + iread(&i, sizeof(ILint), 1); +#ifdef __BIG_ENDIAN__ + iSwapInt(&i); +#endif + return i; +} + +ILfloat GetLittleFloat() { + ILfloat f; + iread(&f, sizeof(ILfloat), 1); +#ifdef __BIG_ENDIAN__ + iSwapFloat(&f); +#endif + return f; +} + +ILdouble GetLittleDouble() { + ILdouble d; + iread(&d, sizeof(ILdouble), 1); +#ifdef __BIG_ENDIAN__ + iSwapDouble(&d); +#endif + return d; +} + +ILushort GetBigUShort() { + ILushort s; + iread(&s, sizeof(ILushort), 1); +#ifdef __LITTLE_ENDIAN__ + iSwapUShort(&s); +#endif + return s; +} + +ILshort GetBigShort() { + ILshort s; + iread(&s, sizeof(ILshort), 1); +#ifdef __LITTLE_ENDIAN__ + iSwapShort(&s); +#endif + return s; +} + +ILuint GetBigUInt() { + ILuint i; + iread(&i, sizeof(ILuint), 1); +#ifdef __LITTLE_ENDIAN__ + iSwapUInt(&i); +#endif + return i; +} + +ILint GetBigInt() { + ILint i; + iread(&i, sizeof(ILint), 1); +#ifdef __LITTLE_ENDIAN__ + iSwapInt(&i); +#endif + return i; +} + +ILfloat GetBigFloat() { + ILfloat f; + iread(&f, sizeof(ILfloat), 1); +#ifdef __LITTLE_ENDIAN__ + iSwapFloat(&f); +#endif + return f; +} + +ILdouble GetBigDouble() { + ILdouble d; + iread(&d, sizeof(ILdouble), 1); +#ifdef __LITTLE_ENDIAN__ + iSwapDouble(&d); +#endif + return d; +} + +ILubyte SaveLittleUShort(ILushort s) { +#ifdef __BIG_ENDIAN__ + iSwapUShort(&s); +#endif + return iwrite(&s, sizeof(ILushort), 1); +} + +ILubyte SaveLittleShort(ILshort s) { +#ifdef __BIG_ENDIAN__ + iSwapShort(&s); +#endif + return iwrite(&s, sizeof(ILshort), 1); +} + +ILubyte SaveLittleUInt(ILuint i) { +#ifdef __BIG_ENDIAN__ + iSwapUInt(&i); +#endif + return iwrite(&i, sizeof(ILuint), 1); +} + +ILubyte SaveLittleInt(ILint i) { +#ifdef __BIG_ENDIAN__ + iSwapInt(&i); +#endif + return iwrite(&i, sizeof(ILint), 1); +} + +ILubyte SaveLittleFloat(ILfloat f) { +#ifdef __BIG_ENDIAN__ + iSwapFloat(&f); +#endif + return iwrite(&f, sizeof(ILfloat), 1); +} + +ILubyte SaveLittleDouble(ILdouble d) { +#ifdef __BIG_ENDIAN__ + iSwapDouble(&d); +#endif + return iwrite(&d, sizeof(ILdouble), 1); +} + + +ILubyte SaveBigUShort(ILushort s) { +#ifdef __LITTLE_ENDIAN__ + iSwapUShort(&s); +#endif + return iwrite(&s, sizeof(ILushort), 1); +} + + +ILubyte SaveBigShort(ILshort s) { +#ifdef __LITTLE_ENDIAN__ + iSwapShort(&s); +#endif + return iwrite(&s, sizeof(ILshort), 1); +} + + +ILubyte SaveBigUInt(ILuint i) { +#ifdef __LITTLE_ENDIAN__ + iSwapUInt(&i); +#endif + return iwrite(&i, sizeof(ILuint), 1); +} + + +ILubyte SaveBigInt(ILint i) { +#ifdef __LITTLE_ENDIAN__ + iSwapInt(&i); +#endif + return iwrite(&i, sizeof(ILint), 1); +} + + +ILubyte SaveBigFloat(ILfloat f) { +#ifdef __LITTLE_ENDIAN__ + iSwapFloat(&f); +#endif + return iwrite(&f, sizeof(ILfloat), 1); +} + + +ILubyte SaveBigDouble(ILdouble d) { +#ifdef __LITTLE_ENDIAN__ + iSwapDouble(&d); +#endif + return iwrite(&d, sizeof(ILdouble), 1); +} + +void EndianSwapData(void *_Image) +{ + ILuint i; + ILubyte *temp, *s, *d; + ILushort *ShortS, *ShortD; + ILuint *IntS, *IntD; + ILfloat *FltS, *FltD; + ILdouble *DblS, *DblD; + + ILimage *Image = (ILimage*)_Image; + + switch (Image->Type) { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + switch (Image->Bpp) { + case 3: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + s = Image->Data; + d = temp; + + for( i = Image->Width * Image->Height; i > 0; i-- ) { + *d++ = *(s+2); + *d++ = *(s+1); + *d++ = *s; + s += 3; + } + + ifree(Image->Data); + Image->Data = temp; + break; + + case 4: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + s = Image->Data; + d = temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *d++ = *(s+3); + *d++ = *(s+2); + *d++ = *(s+1); + *d++ = *s; + s += 4; + } + + ifree(Image->Data); + Image->Data = temp; + break; + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + switch (Image->Bpp) { + case 3: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + ShortS = (ILushort*)Image->Data; + ShortD = (ILushort*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *ShortD = *ShortS++; iSwapUShort(ShortD++); + *ShortD = *ShortS++; iSwapUShort(ShortD++); + *ShortD = *ShortS++; iSwapUShort(ShortD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + + case 4: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + ShortS = (ILushort*)Image->Data; + ShortD = (ILushort*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *ShortD = *ShortS++; iSwapUShort(ShortD++); + *ShortD = *ShortS++; iSwapUShort(ShortD++); + *ShortD = *ShortS++; iSwapUShort(ShortD++); + *ShortD = *ShortS++; iSwapUShort(ShortD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + } + break; + + case IL_INT: + case IL_UNSIGNED_INT: + switch (Image->Bpp) + { + case 3: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + IntS = (ILuint*)Image->Data; + IntD = (ILuint*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *IntD = *IntS++; iSwapUInt(IntD++); + *IntD = *IntS++; iSwapUInt(IntD++); + *IntD = *IntS++; iSwapUInt(IntD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + + case 4: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + IntS = (ILuint*)Image->Data; + IntD = (ILuint*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *IntD = *IntS++; iSwapUInt(IntD++); + *IntD = *IntS++; iSwapUInt(IntD++); + *IntD = *IntS++; iSwapUInt(IntD++); + *IntD = *IntS++; iSwapUInt(IntD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + } + break; + + case IL_FLOAT: + switch (Image->Bpp) + { + case 3: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + FltS = (ILfloat*)Image->Data; + FltD = (ILfloat*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *FltD = *FltS++; iSwapFloat(FltD++); + *FltD = *FltS++; iSwapFloat(FltD++); + *FltD = *FltS++; iSwapFloat(FltD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + + case 4: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + FltS = (ILfloat*)Image->Data; + FltD = (ILfloat*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *FltD = *FltS++; iSwapFloat(FltD++); + *FltD = *FltS++; iSwapFloat(FltD++); + *FltD = *FltS++; iSwapFloat(FltD++); + *FltD = *FltS++; iSwapFloat(FltD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + } + break; + + case IL_DOUBLE: + switch (Image->Bpp) + { + case 3: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + DblS = (ILdouble*)Image->Data; + DblD = (ILdouble*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *DblD = *DblS++; iSwapDouble(DblD++); + *DblD = *DblS++; iSwapDouble(DblD++); + *DblD = *DblS++; iSwapDouble(DblD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + + case 4: + temp = (ILubyte*)ialloc(Image->SizeOfData); + if (temp == NULL) + return; + DblS = (ILdouble*)Image->Data; + DblD = (ILdouble*)temp; + + for (i = Image->Width * Image->Height; i > 0; i--) { + *DblD = *DblS++; iSwapDouble(DblD++); + *DblD = *DblS++; iSwapDouble(DblD++); + *DblD = *DblS++; iSwapDouble(DblD++); + *DblD = *DblS++; iSwapDouble(DblD++); + } + + ifree(Image->Data); + Image->Data = temp; + break; + } + break; + } + + if( iCurImage->Format == IL_COLOUR_INDEX ) { + switch (iCurImage->Pal.PalType) { + case IL_PAL_RGB24: + case IL_PAL_BGR24: + temp = (ILubyte*)ialloc(Image->Pal.PalSize); + if (temp == NULL) + return; + s = Image->Pal.Palette; + d = temp; + + for (i = Image->Pal.PalSize / 3; i > 0; i--) { + *d++ = *(s+2); + *d++ = *(s+1); + *d++ = *s; + s += 3; + } + + ifree(Image->Pal.Palette); + Image->Pal.Palette = temp; + break; + + case IL_PAL_RGBA32: + case IL_PAL_RGB32: + case IL_PAL_BGRA32: + case IL_PAL_BGR32: + temp = (ILubyte*)ialloc(Image->Pal.PalSize); + if (temp == NULL) + return; + s = Image->Pal.Palette; + d = temp; + + for (i = Image->Pal.PalSize / 4; i > 0; i--) { + *d++ = *(s+3); + *d++ = *(s+2); + *d++ = *(s+1); + *d++ = *s; + s += 4; + } + + ifree(Image->Pal.Palette); + Image->Pal.Palette = temp; + break; + } + } + return; +} diff --git a/DevIL/src-IL/src/il_error.c b/DevIL/src-IL/src/il_error.c deleted file mode 100644 index 2519240a..00000000 --- a/DevIL/src-IL/src/il_error.c +++ /dev/null @@ -1,56 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 06/02/2007 -// -// Filename: src-IL/src/il_error.c -// -// Description: The error functions -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" - - -#define IL_ERROR_STACK_SIZE 32 // Needed elsewhere? - - -ILenum ilErrorNum[IL_ERROR_STACK_SIZE]; -ILint ilErrorPlace = (-1); - - -// Sets the current error -// If you go past the stack size for this, it cycles the errors, almost like a LRU algo. -ILAPI void ILAPIENTRY ilSetError(ILenum Error) -{ - ILuint i; - - ilErrorPlace++; - if (ilErrorPlace >= IL_ERROR_STACK_SIZE) { - for (i = 0; i < IL_ERROR_STACK_SIZE - 2; i++) { - ilErrorNum[i] = ilErrorNum[i+1]; - } - ilErrorPlace = IL_ERROR_STACK_SIZE - 1; - } - ilErrorNum[ilErrorPlace] = Error; - - return; -} - - -//! Gets the last error on the error stack -ILenum ILAPIENTRY ilGetError(void) -{ - ILenum ilReturn; - - if (ilErrorPlace >= 0) { - ilReturn = ilErrorNum[ilErrorPlace]; - ilErrorPlace--; - } - else - ilReturn = IL_NO_ERROR; - - return ilReturn; -} diff --git a/DevIL/src-IL/src/il_error.cpp b/DevIL/src-IL/src/il_error.cpp new file mode 100644 index 00000000..2519240a --- /dev/null +++ b/DevIL/src-IL/src/il_error.cpp @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 06/02/2007 +// +// Filename: src-IL/src/il_error.c +// +// Description: The error functions +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" + + +#define IL_ERROR_STACK_SIZE 32 // Needed elsewhere? + + +ILenum ilErrorNum[IL_ERROR_STACK_SIZE]; +ILint ilErrorPlace = (-1); + + +// Sets the current error +// If you go past the stack size for this, it cycles the errors, almost like a LRU algo. +ILAPI void ILAPIENTRY ilSetError(ILenum Error) +{ + ILuint i; + + ilErrorPlace++; + if (ilErrorPlace >= IL_ERROR_STACK_SIZE) { + for (i = 0; i < IL_ERROR_STACK_SIZE - 2; i++) { + ilErrorNum[i] = ilErrorNum[i+1]; + } + ilErrorPlace = IL_ERROR_STACK_SIZE - 1; + } + ilErrorNum[ilErrorPlace] = Error; + + return; +} + + +//! Gets the last error on the error stack +ILenum ILAPIENTRY ilGetError(void) +{ + ILenum ilReturn; + + if (ilErrorPlace >= 0) { + ilReturn = ilErrorNum[ilErrorPlace]; + ilErrorPlace--; + } + else + ilReturn = IL_NO_ERROR; + + return ilReturn; +} diff --git a/DevIL/src-IL/src/il_fastconv.c b/DevIL/src-IL/src/il_fastconv.c deleted file mode 100644 index 1103a878..00000000 --- a/DevIL/src-IL/src/il_fastconv.c +++ /dev/null @@ -1,290 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 07/07/2006 -// -// Filename: src-IL/src/il_fastconv.c -// -// Description: Converts between several image formats -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifdef ALTIVEC_GCC -#include "altivec_typeconversion.h" -#endif - -ILboolean iFastConvert(ILenum DestFormat) -{ - ILubyte *BytePtr = iCurImage->Data; - ILushort *ShortPtr = (ILushort*)iCurImage->Data; - ILuint *IntPtr = (ILuint*)iCurImage->Data; - ILfloat *FloatPtr = (ILfloat*)iCurImage->Data; - ILdouble *DblPtr = (ILdouble*)iCurImage->Data; - -#ifndef ALTIVEC_GCC - ILuint SizeOfData, i=0; - ILubyte TempByte = 0; - ILushort TempShort = 0; - ILuint TempInt = 0; - ILfloat TempFloat = 0; - ILdouble TempDbl = 0; -#endif - - switch (DestFormat) - { - case IL_RGB: - case IL_BGR: - if (iCurImage->Format != IL_RGB && iCurImage->Format != IL_BGR) - return IL_FALSE; - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - #ifdef ALTIVEC_GCC - abc2cba_byte(BytePtr,iCurImage->SizeOfData,BytePtr); - #else - SizeOfData = iCurImage->SizeOfData / 3; - #ifdef USE_WIN32_ASM - __asm - { - mov ebx, BytePtr - mov ecx, SizeOfData - L1: - mov al,[ebx+0] - xchg al,[ebx+2] - mov [ebx+0],al - add ebx,3 - loop L1 - } - #else - for (i = 0; i < SizeOfData; i++) { - TempByte = BytePtr[0]; - BytePtr[0] = BytePtr[2]; - BytePtr[2] = TempByte; - BytePtr += 3; - } - #endif//USE_WIN32_ASM - #endif - return IL_TRUE; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - #ifdef ALTIVEC_GCC - abc2cba_short(ShortPtr,iCurImage->SizeOfData,ShortPtr); - #else - SizeOfData = iCurImage->SizeOfData / 6; // 3*2 - #ifdef USE_WIN32_ASM - __asm - { - mov ebx, ShortPtr - mov ecx, SizeOfData - L2: - mov ax,[ebx+0] - xchg ax,[ebx+4] - mov [ebx+0],ax - add ebx,6 - loop L2 - } - #else - for (i = 0; i < SizeOfData; i++) { - TempShort = ShortPtr[0]; - ShortPtr[0] = ShortPtr[2]; - ShortPtr[2] = TempShort; - ShortPtr += 3; - } - #endif//USE_WIN32_ASM - #endif - return IL_TRUE; - - case IL_INT: - case IL_UNSIGNED_INT: - #ifdef ALTIVEC_GCC - abc2cba_int(IntPtr,iCurImage->SizeOfData,IntPtr); - #else - SizeOfData = iCurImage->SizeOfData / 12; // 3*4 - #ifdef USE_WIN32_ASM - __asm - { - mov ebx, IntPtr - mov ecx, SizeOfData - L3: - mov eax,[ebx+0] - xchg eax,[ebx+8] - mov [ebx+0],ax - add ebx,12 - loop L3 - } - #else - for (i = 0; i < SizeOfData; i++) { - TempInt = IntPtr[0]; - IntPtr[0] = IntPtr[2]; - IntPtr[2] = TempInt; - IntPtr += 3; - } - #endif//USE_WIN32_ASM - #endif - return IL_TRUE; - - case IL_FLOAT: - #ifdef ALTIVEC_GCC - abc2cba_float(FloatPtr,iCurImage->SizeOfData,FloatPtr); - #else - SizeOfData = iCurImage->SizeOfData / 12; // 3*4 - for (i = 0; i < SizeOfData; i++) { - TempFloat = FloatPtr[0]; - FloatPtr[0] = FloatPtr[2]; - FloatPtr[2] = TempFloat; - FloatPtr += 3; - } - #endif - return IL_TRUE; - - case IL_DOUBLE: - #ifdef ALTIVEC_GCC - abc2cba_double(DblPtr,iCurImage->SizeOfData,DblPtr); - #else - SizeOfData = iCurImage->SizeOfData / 24; // 3*8 - for (i = 0; i < SizeOfData; i++) { - TempDbl = DblPtr[0]; - DblPtr[0] = DblPtr[2]; - DblPtr[2] = TempDbl; - DblPtr += 3; - } - #endif - return IL_TRUE; - } - break; - - case IL_RGBA: - case IL_BGRA: - if (iCurImage->Format != IL_RGBA && iCurImage->Format != IL_BGRA) - return IL_FALSE; - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - #ifdef ALTIVEC_GCC - abcd2cbad_byte(BytePtr,iCurImage->SizeOfData,BytePtr); - #else - SizeOfData = iCurImage->SizeOfData / 4; - #ifdef USE_WIN32_ASM - __asm - { - mov ebx, BytePtr - mov ecx, SizeOfData - L4: - mov eax,[ebx] - bswap eax - ror eax,8 - mov [ebx], eax - add ebx,4 - loop L4 - } - #else - for (i = 0; i < SizeOfData; i++) { - TempByte = BytePtr[0]; - BytePtr[0] = BytePtr[2]; - BytePtr[2] = TempByte; - BytePtr += 4; - } - #endif//USE_WIN32_ASM - #endif - return IL_TRUE; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - #ifdef ALTIVEC_GCC - abcd2cbad_short(ShortPtr,iCurImage->SizeOfData,ShortPtr); - #else - SizeOfData = iCurImage->SizeOfData / 8; // 4*2 - #ifdef USE_WIN32_ASM - __asm - { - mov ebx, ShortPtr - mov ecx, SizeOfData - L5: - mov ax,[ebx+0] - xchg ax,[ebx+4] - mov [ebx+0],ax - add ebx,8 - loop L5 - } - #else - for (i = 0; i < SizeOfData; i++) { - TempShort = ShortPtr[0]; - ShortPtr[0] = ShortPtr[2]; - ShortPtr[2] = TempShort; - ShortPtr += 4; - } - #endif//USE_WIN32_ASM - #endif - return IL_TRUE; - - case IL_INT: - case IL_UNSIGNED_INT: - #ifdef ALTIVEC_GCC - abcd2cbad_int(IntPtr,iCurImage->SizeOfData,IntPtr); - #else - SizeOfData = iCurImage->SizeOfData / 16; // 4*4 - #ifdef USE_WIN32_ASM - __asm - { - mov ebx, IntPtr - mov ecx, SizeOfData - L6: - mov eax,[ebx+0] - xchg eax,[ebx+8] - mov [ebx+0],ax - add ebx,16 - loop L6 - } - #else - for (i = 0; i < SizeOfData; i++) { - TempInt = IntPtr[0]; - IntPtr[0] = IntPtr[2]; - IntPtr[2] = TempInt; - IntPtr += 4; - } - #endif//USE_WIN32_ASM - #endif - return IL_TRUE; - - case IL_FLOAT: - #ifdef ALTIVEC_GCC - abcd2cbad_float(FloatPtr,iCurImage->SizeOfData,FloatPtr); - #else - SizeOfData = iCurImage->SizeOfData / 16; // 4*4 - for (i = 0; i < SizeOfData; i++) { - TempFloat = FloatPtr[0]; - FloatPtr[0] = FloatPtr[2]; - FloatPtr[2] = TempFloat; - FloatPtr += 4; - } - #endif - return IL_TRUE; - - case IL_DOUBLE: - #ifdef ALTIVEC_GCC - abcd2cbad_double(DblPtr,iCurImage->SizeOfData,DblPtr); - #else - SizeOfData = iCurImage->SizeOfData / 32; // 4*8 - for (i = 0; i < SizeOfData; i++) { - TempDbl = DblPtr[0]; - DblPtr[0] = DblPtr[2]; - DblPtr[2] = TempDbl; - DblPtr += 4; - } - #endif - return IL_TRUE; - } - } - - - return IL_FALSE; -} - diff --git a/DevIL/src-IL/src/il_fastconv.cpp b/DevIL/src-IL/src/il_fastconv.cpp new file mode 100644 index 00000000..1103a878 --- /dev/null +++ b/DevIL/src-IL/src/il_fastconv.cpp @@ -0,0 +1,290 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 07/07/2006 +// +// Filename: src-IL/src/il_fastconv.c +// +// Description: Converts between several image formats +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifdef ALTIVEC_GCC +#include "altivec_typeconversion.h" +#endif + +ILboolean iFastConvert(ILenum DestFormat) +{ + ILubyte *BytePtr = iCurImage->Data; + ILushort *ShortPtr = (ILushort*)iCurImage->Data; + ILuint *IntPtr = (ILuint*)iCurImage->Data; + ILfloat *FloatPtr = (ILfloat*)iCurImage->Data; + ILdouble *DblPtr = (ILdouble*)iCurImage->Data; + +#ifndef ALTIVEC_GCC + ILuint SizeOfData, i=0; + ILubyte TempByte = 0; + ILushort TempShort = 0; + ILuint TempInt = 0; + ILfloat TempFloat = 0; + ILdouble TempDbl = 0; +#endif + + switch (DestFormat) + { + case IL_RGB: + case IL_BGR: + if (iCurImage->Format != IL_RGB && iCurImage->Format != IL_BGR) + return IL_FALSE; + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + #ifdef ALTIVEC_GCC + abc2cba_byte(BytePtr,iCurImage->SizeOfData,BytePtr); + #else + SizeOfData = iCurImage->SizeOfData / 3; + #ifdef USE_WIN32_ASM + __asm + { + mov ebx, BytePtr + mov ecx, SizeOfData + L1: + mov al,[ebx+0] + xchg al,[ebx+2] + mov [ebx+0],al + add ebx,3 + loop L1 + } + #else + for (i = 0; i < SizeOfData; i++) { + TempByte = BytePtr[0]; + BytePtr[0] = BytePtr[2]; + BytePtr[2] = TempByte; + BytePtr += 3; + } + #endif//USE_WIN32_ASM + #endif + return IL_TRUE; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + #ifdef ALTIVEC_GCC + abc2cba_short(ShortPtr,iCurImage->SizeOfData,ShortPtr); + #else + SizeOfData = iCurImage->SizeOfData / 6; // 3*2 + #ifdef USE_WIN32_ASM + __asm + { + mov ebx, ShortPtr + mov ecx, SizeOfData + L2: + mov ax,[ebx+0] + xchg ax,[ebx+4] + mov [ebx+0],ax + add ebx,6 + loop L2 + } + #else + for (i = 0; i < SizeOfData; i++) { + TempShort = ShortPtr[0]; + ShortPtr[0] = ShortPtr[2]; + ShortPtr[2] = TempShort; + ShortPtr += 3; + } + #endif//USE_WIN32_ASM + #endif + return IL_TRUE; + + case IL_INT: + case IL_UNSIGNED_INT: + #ifdef ALTIVEC_GCC + abc2cba_int(IntPtr,iCurImage->SizeOfData,IntPtr); + #else + SizeOfData = iCurImage->SizeOfData / 12; // 3*4 + #ifdef USE_WIN32_ASM + __asm + { + mov ebx, IntPtr + mov ecx, SizeOfData + L3: + mov eax,[ebx+0] + xchg eax,[ebx+8] + mov [ebx+0],ax + add ebx,12 + loop L3 + } + #else + for (i = 0; i < SizeOfData; i++) { + TempInt = IntPtr[0]; + IntPtr[0] = IntPtr[2]; + IntPtr[2] = TempInt; + IntPtr += 3; + } + #endif//USE_WIN32_ASM + #endif + return IL_TRUE; + + case IL_FLOAT: + #ifdef ALTIVEC_GCC + abc2cba_float(FloatPtr,iCurImage->SizeOfData,FloatPtr); + #else + SizeOfData = iCurImage->SizeOfData / 12; // 3*4 + for (i = 0; i < SizeOfData; i++) { + TempFloat = FloatPtr[0]; + FloatPtr[0] = FloatPtr[2]; + FloatPtr[2] = TempFloat; + FloatPtr += 3; + } + #endif + return IL_TRUE; + + case IL_DOUBLE: + #ifdef ALTIVEC_GCC + abc2cba_double(DblPtr,iCurImage->SizeOfData,DblPtr); + #else + SizeOfData = iCurImage->SizeOfData / 24; // 3*8 + for (i = 0; i < SizeOfData; i++) { + TempDbl = DblPtr[0]; + DblPtr[0] = DblPtr[2]; + DblPtr[2] = TempDbl; + DblPtr += 3; + } + #endif + return IL_TRUE; + } + break; + + case IL_RGBA: + case IL_BGRA: + if (iCurImage->Format != IL_RGBA && iCurImage->Format != IL_BGRA) + return IL_FALSE; + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + #ifdef ALTIVEC_GCC + abcd2cbad_byte(BytePtr,iCurImage->SizeOfData,BytePtr); + #else + SizeOfData = iCurImage->SizeOfData / 4; + #ifdef USE_WIN32_ASM + __asm + { + mov ebx, BytePtr + mov ecx, SizeOfData + L4: + mov eax,[ebx] + bswap eax + ror eax,8 + mov [ebx], eax + add ebx,4 + loop L4 + } + #else + for (i = 0; i < SizeOfData; i++) { + TempByte = BytePtr[0]; + BytePtr[0] = BytePtr[2]; + BytePtr[2] = TempByte; + BytePtr += 4; + } + #endif//USE_WIN32_ASM + #endif + return IL_TRUE; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + #ifdef ALTIVEC_GCC + abcd2cbad_short(ShortPtr,iCurImage->SizeOfData,ShortPtr); + #else + SizeOfData = iCurImage->SizeOfData / 8; // 4*2 + #ifdef USE_WIN32_ASM + __asm + { + mov ebx, ShortPtr + mov ecx, SizeOfData + L5: + mov ax,[ebx+0] + xchg ax,[ebx+4] + mov [ebx+0],ax + add ebx,8 + loop L5 + } + #else + for (i = 0; i < SizeOfData; i++) { + TempShort = ShortPtr[0]; + ShortPtr[0] = ShortPtr[2]; + ShortPtr[2] = TempShort; + ShortPtr += 4; + } + #endif//USE_WIN32_ASM + #endif + return IL_TRUE; + + case IL_INT: + case IL_UNSIGNED_INT: + #ifdef ALTIVEC_GCC + abcd2cbad_int(IntPtr,iCurImage->SizeOfData,IntPtr); + #else + SizeOfData = iCurImage->SizeOfData / 16; // 4*4 + #ifdef USE_WIN32_ASM + __asm + { + mov ebx, IntPtr + mov ecx, SizeOfData + L6: + mov eax,[ebx+0] + xchg eax,[ebx+8] + mov [ebx+0],ax + add ebx,16 + loop L6 + } + #else + for (i = 0; i < SizeOfData; i++) { + TempInt = IntPtr[0]; + IntPtr[0] = IntPtr[2]; + IntPtr[2] = TempInt; + IntPtr += 4; + } + #endif//USE_WIN32_ASM + #endif + return IL_TRUE; + + case IL_FLOAT: + #ifdef ALTIVEC_GCC + abcd2cbad_float(FloatPtr,iCurImage->SizeOfData,FloatPtr); + #else + SizeOfData = iCurImage->SizeOfData / 16; // 4*4 + for (i = 0; i < SizeOfData; i++) { + TempFloat = FloatPtr[0]; + FloatPtr[0] = FloatPtr[2]; + FloatPtr[2] = TempFloat; + FloatPtr += 4; + } + #endif + return IL_TRUE; + + case IL_DOUBLE: + #ifdef ALTIVEC_GCC + abcd2cbad_double(DblPtr,iCurImage->SizeOfData,DblPtr); + #else + SizeOfData = iCurImage->SizeOfData / 32; // 4*8 + for (i = 0; i < SizeOfData; i++) { + TempDbl = DblPtr[0]; + DblPtr[0] = DblPtr[2]; + DblPtr[2] = TempDbl; + DblPtr += 4; + } + #endif + return IL_TRUE; + } + } + + + return IL_FALSE; +} + diff --git a/DevIL/src-IL/src/il_files.c b/DevIL/src-IL/src/il_files.c deleted file mode 100644 index 4c987d5c..00000000 --- a/DevIL/src-IL/src/il_files.c +++ /dev/null @@ -1,773 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 01/04/2009 -// -// Filename: src-IL/src/il_files.c -// -// Description: File handling for DevIL -// -//----------------------------------------------------------------------------- - - -#define __FILES_C -#include "il_internal.h" -#include - - -// All specific to the next set of functions -ILboolean ILAPIENTRY iEofFile(void); -ILboolean ILAPIENTRY iEofLump(void); -ILint ILAPIENTRY iGetcFile(void); -ILint ILAPIENTRY iGetcLump(void); -ILuint ILAPIENTRY iReadFile(void *Buffer, ILuint Size, ILuint Number); -ILuint ILAPIENTRY iReadLump(void *Buffer, const ILuint Size, const ILuint Number); -ILint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode); -ILint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode); -ILint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode); -ILint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode); -ILuint ILAPIENTRY iTellRFile(void); -ILuint ILAPIENTRY iTellRLump(void); -ILuint ILAPIENTRY iTellWFile(void); -ILuint ILAPIENTRY iTellWLump(void); -ILint ILAPIENTRY iPutcFile(ILubyte Char); -ILint ILAPIENTRY iPutcLump(ILubyte Char); -ILint ILAPIENTRY iWriteFile(const void *Buffer, ILuint Size, ILuint Number); -ILint ILAPIENTRY iWriteLump(const void *Buffer, ILuint Size, ILuint Number); -ILHANDLE FileRead = NULL, FileWrite = NULL; -const void *ReadLump = NULL; -void *WriteLump = NULL; -ILuint ReadLumpPos = 0, ReadLumpSize = 0, ReadFileStart = 0, WriteFileStart = 0; -ILuint WriteLumpPos = 0, WriteLumpSize = 0; - -fGetcProc GetcProcCopy; -fReadProc ReadProcCopy; -fSeekRProc SeekProcCopy; -fTellRProc TellProcCopy; -ILHANDLE (ILAPIENTRY *iopenCopy)(ILconst_string); -void (ILAPIENTRY *icloseCopy)(ILHANDLE); - -fPutcProc PutcProcCopy; -fSeekWProc SeekWProcCopy; -fTellWProc TellWProcCopy; -fWriteProc WriteProcCopy; -ILHANDLE (ILAPIENTRY *iopenwCopy)(ILconst_string); -void (ILAPIENTRY *iclosewCopy)(ILHANDLE); - -ILboolean UseCache = IL_FALSE; -ILubyte *Cache = NULL; -ILuint CacheSize, CachePos, CacheStartPos, CacheBytesRead; - -// "Fake" size functions -// Definitions are in il_size.c. -ILint ILAPIENTRY iSizeSeek(ILint Offset, ILuint Mode); -ILuint ILAPIENTRY iSizeTell(void); -ILint ILAPIENTRY iSizePutc(ILubyte Char); -ILint ILAPIENTRY iSizeWrite(const void *Buffer, ILuint Size, ILuint Number); - -// Just preserves the current read functions and replaces -// the current read functions with the default read funcs. -void ILAPIENTRY iPreserveReadFuncs() -{ - // Create backups - GetcProcCopy = GetcProc; - ReadProcCopy = ReadProc; - SeekProcCopy = SeekRProc; - TellProcCopy = TellRProc; - iopenCopy = iopenr; - icloseCopy = icloser; - - // Set the standard procs to read - ilResetRead(); - - return; -} - - -// Restores the read functions - must be used after iPreserveReadFuncs(). -void ILAPIENTRY iRestoreReadFuncs() -{ - GetcProc = GetcProcCopy; - ReadProc = ReadProcCopy; - SeekRProc = SeekProcCopy; - TellRProc = TellProcCopy; - iopenr = iopenCopy; - icloser = icloseCopy; - - return; -} - - -// Just preserves the current read functions and replaces -// the current read functions with the default read funcs. -void ILAPIENTRY iPreserveWriteFuncs() -{ - // Create backups - PutcProcCopy = PutcProc; - SeekWProcCopy = SeekWProc; - TellWProcCopy = TellWProc; - WriteProcCopy = WriteProc; - iopenwCopy = iopenw; - iclosewCopy = iclosew; - - // Set the standard procs to write - ilResetWrite(); - - return; -} - - -// Restores the read functions - must be used after iPreserveReadFuncs(). -void ILAPIENTRY iRestoreWriteFuncs() -{ - PutcProc = PutcProcCopy; - SeekWProc = SeekWProcCopy; - TellWProc = TellWProcCopy; - WriteProc = WriteProcCopy; - iopenw = iopenwCopy; - iclosew = iclosewCopy; - - return; -} - - -// Next 7 functions are the default read functions - -ILHANDLE ILAPIENTRY iDefaultOpenR(ILconst_string FileName) -{ -#ifndef _UNICODE - return (ILHANDLE)fopen((char*)FileName, "rb"); -#else - // Windows has a different function, _wfopen, to open UTF16 files, - // whereas Linux just uses fopen for its UTF8 files. - #ifdef _WIN32 - return (ILHANDLE)_wfopen(FileName, L"rb"); - #else - return (ILHANDLE)fopen((char*)FileName, "rb"); - #endif -#endif//UNICODE -} - - -void ILAPIENTRY iDefaultCloseR(ILHANDLE Handle) -{ - fclose((FILE*)Handle); - return; -} - - -ILboolean ILAPIENTRY iDefaultEof(ILHANDLE Handle) -{ - ILuint OrigPos, FileSize; - - // Find out the filesize for checking for the end of file - OrigPos = itell(); - iseek(0, IL_SEEK_END); - FileSize = itell(); - iseek(OrigPos, IL_SEEK_SET); - - if (itell() >= FileSize) - return IL_TRUE; - return IL_FALSE; -} - - -ILint ILAPIENTRY iDefaultGetc(ILHANDLE Handle) -{ - ILint Val; - - if (!UseCache) { - Val = fgetc((FILE*)Handle); - if (Val == IL_EOF) - ilSetError(IL_FILE_READ_ERROR); - } - else { - Val = 0; - if (iread(&Val, 1, 1) != 1) - return IL_EOF; - } - return Val; -} - - -ILint ILAPIENTRY iDefaultRead(void *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle) -{ - return (ILint)fread(Buffer, Size, Number, (FILE*)Handle); -} - - -ILint ILAPIENTRY iDefaultRSeek(ILHANDLE Handle, ILint Offset, ILint Mode) -{ - return fseek((FILE*)Handle, Offset, Mode); -} - - -ILint ILAPIENTRY iDefaultWSeek(ILHANDLE Handle, ILint Offset, ILint Mode) -{ - return fseek((FILE*)Handle, Offset, Mode); -} - - -ILint ILAPIENTRY iDefaultRTell(ILHANDLE Handle) -{ - return ftell((FILE*)Handle); -} - - -ILint ILAPIENTRY iDefaultWTell(ILHANDLE Handle) -{ - return ftell((FILE*)Handle); -} - - -ILHANDLE ILAPIENTRY iDefaultOpenW(ILconst_string FileName) -{ -#ifndef _UNICODE - return (ILHANDLE)fopen((char*)FileName, "wb"); -#else - // Windows has a different function, _wfopen, to open UTF16 files, - // whereas Linux just uses fopen. - #ifdef _WIN32 - return (ILHANDLE)_wfopen(FileName, L"wb"); - #else - return (ILHANDLE)fopen((char*)FileName, "wb"); - #endif -#endif//UNICODE -} - - -void ILAPIENTRY iDefaultCloseW(ILHANDLE Handle) -{ - fclose((FILE*)Handle); - return; -} - - -ILint ILAPIENTRY iDefaultPutc(ILubyte Char, ILHANDLE Handle) -{ - return fputc(Char, (FILE*)Handle); -} - - -ILint ILAPIENTRY iDefaultWrite(const void *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle) -{ - return (ILint)fwrite(Buffer, Size, Number, (FILE*)Handle); -} - - -void ILAPIENTRY ilResetRead() -{ - ilSetRead(iDefaultOpenR, iDefaultCloseR, iDefaultEof, iDefaultGetc, - iDefaultRead, iDefaultRSeek, iDefaultRTell); - return; -} - - -void ILAPIENTRY ilResetWrite() -{ - ilSetWrite(iDefaultOpenW, iDefaultCloseW, iDefaultPutc, - iDefaultWSeek, iDefaultWTell, iDefaultWrite); - return; -} - - -//! Allows you to override the default file-reading functions. -void ILAPIENTRY ilSetRead(fOpenRProc Open, fCloseRProc Close, fEofProc Eof, fGetcProc Getc, fReadProc Read, fSeekRProc Seek, fTellRProc Tell) -{ - iopenr = Open; - icloser = Close; - EofProc = Eof; - GetcProc = Getc; - ReadProc = Read; - SeekRProc = Seek; - TellRProc = Tell; - - return; -} - - -//! Allows you to override the default file-writing functions. -void ILAPIENTRY ilSetWrite(fOpenRProc Open, fCloseRProc Close, fPutcProc Putc, fSeekWProc Seek, fTellWProc Tell, fWriteProc Write) -{ - iopenw = Open; - iclosew = Close; - PutcProc = Putc; - WriteProc = Write; - SeekWProc = Seek; - TellWProc = Tell; - - return; -} - - -// Tells DevIL that we're reading from a file, not a lump -void iSetInputFile(ILHANDLE File) -{ - ieof = iEofFile; - igetc = iGetcFile; - iread = iReadFile; - iseek = iSeekRFile; - itell = iTellRFile; - FileRead = File; - ReadFileStart = itell(); -} - - -// Tells DevIL that we're reading from a lump, not a file -void iSetInputLump(const void *Lump, ILuint Size) -{ - ieof = iEofLump; - igetc = iGetcLump; - iread = iReadLump; - iseek = iSeekRLump; - itell = iTellRLump; - ReadLump = Lump; - ReadLumpPos = 0; - ReadLumpSize = Size; -} - - -// Tells DevIL that we're writing to a file, not a lump -void iSetOutputFile(ILHANDLE File) -{ - // Helps with ilGetLumpPos(). - WriteLump = NULL; - WriteLumpPos = 0; - WriteLumpSize = 0; - - iputc = iPutcFile; - iseekw = iSeekWFile; - itellw = iTellWFile; - iwrite = iWriteFile; - FileWrite = File; -} - - -// This is only called by ilDetermineSize. Associates iputc, etc. with -// "fake" writing functions in il_size.c. -void iSetOutputFake(void) -{ - iputc = iSizePutc; - iseekw = iSizeSeek; - itellw = iSizeTell; - iwrite = iSizeWrite; - return; -} - - -// Tells DevIL that we're writing to a lump, not a file -void iSetOutputLump(void *Lump, ILuint Size) -{ - // In this case, ilDetermineSize is currently trying to determine the - // output buffer size. It already has the write functions it needs. - if (Lump == NULL) - return; - - iputc = iPutcLump; - iseekw = iSeekWLump; - itellw = iTellWLump; - iwrite = iWriteLump; - WriteLump = Lump; - WriteLumpPos = 0; - WriteLumpSize = Size; -} - - -ILuint ILAPIENTRY ilGetLumpPos() -{ - if (WriteLump) - return WriteLumpPos; - return 0; -} - - -ILuint ILAPIENTRY ilprintf(const char *Line, ...) -{ - char Buffer[2048]; // Hope this is large enough - va_list VaLine; - ILuint i; - - va_start(VaLine, Line); - vsprintf(Buffer, Line, VaLine); - va_end(VaLine); - - i = ilCharStrLen(Buffer); - iwrite(Buffer, 1, i); - - return i; -} - - -// To pad zeros where needed... -void ipad(ILuint NumZeros) -{ - ILuint i = 0; - for (; i < NumZeros; i++) - iputc(0); - return; -} - - -// -// The rest of the functions following in this file are quite -// self-explanatory, except where commented. -// - -// Next 12 functions are the default write functions - -ILboolean ILAPIENTRY iEofFile(void) -{ - return EofProc((FILE*)FileRead); -} - - -ILboolean ILAPIENTRY iEofLump(void) -{ - if (ReadLumpSize) - return (ReadLumpPos >= ReadLumpSize); - return IL_FALSE; -} - - -ILint ILAPIENTRY iGetcFile(void) -{ - if (!UseCache) { - return GetcProc(FileRead); - } - if (CachePos >= CacheSize) { - iPreCache(CacheSize); - } - - CacheBytesRead++; - return Cache[CachePos++]; -} - - -ILint ILAPIENTRY iGetcLump(void) -{ - // If ReadLumpSize is 0, don't even check to see if we've gone past the bounds. - if (ReadLumpSize > 0) { - if (ReadLumpPos + 1 > ReadLumpSize) { - ReadLumpPos--; - ilSetError(IL_FILE_READ_ERROR); - return IL_EOF; - } - } - - return *((ILubyte*)ReadLump + ReadLumpPos++); -} - - -ILuint ILAPIENTRY iReadFile(void *Buffer, ILuint Size, ILuint Number) -{ - ILuint TotalBytes = 0, BytesCopied; - ILuint BuffSize = Size * Number; - ILuint NumRead; - - if (!UseCache) { - NumRead = ReadProc(Buffer, Size, Number, FileRead); - if (NumRead != Number) - ilSetError(IL_FILE_READ_ERROR); - return NumRead; - } - - /*if (Cache == NULL || CacheSize == 0) { // Shouldn't happen, but we check anyway. - return ReadProc(Buffer, Size, Number, FileRead); - }*/ - - if (BuffSize < CacheSize - CachePos) { - memcpy(Buffer, Cache + CachePos, BuffSize); - CachePos += BuffSize; - CacheBytesRead += BuffSize; - if (Size != 0) - BuffSize /= Size; - return BuffSize; - } - else { - while (TotalBytes < BuffSize) { - // If loop through more than once, after first, CachePos is 0. - if (TotalBytes + CacheSize - CachePos > BuffSize) - BytesCopied = BuffSize - TotalBytes; - else - BytesCopied = CacheSize - CachePos; - - memcpy((ILubyte*)Buffer + TotalBytes, Cache + CachePos, BytesCopied); - TotalBytes += BytesCopied; - CachePos += BytesCopied; - if (TotalBytes < BuffSize) { - iPreCache(CacheSize); - } - } - } - - // DW: Changed on 12-27-2008. Was causing the position to go too far if the - // cache was smaller than the buffer. - //CacheBytesRead += TotalBytes; - CacheBytesRead = CachePos; - if (Size != 0) - TotalBytes /= Size; - if (TotalBytes != Number) - ilSetError(IL_FILE_READ_ERROR); - return TotalBytes; -} - - -ILuint ILAPIENTRY iReadLump(void *Buffer, const ILuint Size, const ILuint Number) -{ - ILuint i, ByteSize = IL_MIN( Size*Number, ReadLumpSize-ReadLumpPos); - - for (i = 0; i < ByteSize; i++) { - *((ILubyte*)Buffer + i) = *((ILubyte*)ReadLump + ReadLumpPos + i); - if (ReadLumpSize > 0) { // ReadLumpSize is too large to care about apparently - if (ReadLumpPos + i > ReadLumpSize) { - ReadLumpPos += i; - if (i != Number) - ilSetError(IL_FILE_READ_ERROR); - return i; - } - } - } - - ReadLumpPos += i; - if (Size != 0) - i /= Size; - if (i != Number) - ilSetError(IL_FILE_READ_ERROR); - return i; -} - - -ILboolean iPreCache(ILuint Size) -{ - // Reading from a memory lump, so don't cache. - if (iread == iReadLump) { - //iUnCache(); // DW: Removed 06-10-2002. - return IL_TRUE; - } - - if (Cache) { - ifree(Cache); - } - - if (Size == 0) { - Size = 1; - } - - Cache = (ILubyte*)ialloc(Size); - if (Cache == NULL) { - return IL_FALSE; - } - - UseCache = IL_FALSE; - CacheStartPos = itell(); - CacheSize = iread(Cache, 1, Size); - if (CacheSize != Size) - ilGetError(); // Get rid of the IL_FILE_READ_ERROR. - - //2003-09-09: uncommented the following line to prevent - //an infinite loop in ilPreCache() - CacheSize = Size; - CachePos = 0; - UseCache = IL_TRUE; - CacheBytesRead = 0; - - return IL_TRUE; -} - - -void iUnCache() -{ - //changed 2003-09-01: - //make iUnCache smart enough to return if - //no cache is used - if (!UseCache) - return; - - if (iread == iReadLump) - return; - - CacheSize = 0; - CachePos = 0; - if (Cache) { - ifree(Cache); - Cache = NULL; - } - UseCache = IL_FALSE; - - iseek(CacheStartPos + CacheBytesRead, IL_SEEK_SET); - - return; -} - - -ILint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode) -{ - if (Mode == IL_SEEK_SET) - Offset += ReadFileStart; // This allows us to use IL_SEEK_SET in the middle of a file. - return SeekRProc(FileRead, Offset, Mode); -} - - -// Returns 1 on error, 0 on success -ILint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode) -{ - switch (Mode) - { - case IL_SEEK_SET: - if (Offset > (ILint)ReadLumpSize) - return 1; - ReadLumpPos = Offset; - break; - - case IL_SEEK_CUR: - if (ReadLumpPos + Offset > ReadLumpSize) - return 1; - ReadLumpPos += Offset; - break; - - case IL_SEEK_END: - if (Offset > 0) - return 1; - // Should we use >= instead? - if (abs(Offset) > (ILint)ReadLumpSize) // If ReadLumpSize == 0, too bad - return 1; - ReadLumpPos = ReadLumpSize + Offset; - break; - - default: - return 1; - } - - return 0; -} - - -ILuint ILAPIENTRY iTellRFile(void) -{ - return TellRProc(FileRead); -} - - -ILuint ILAPIENTRY iTellRLump(void) -{ - return ReadLumpPos; -} - - -ILHANDLE ILAPIENTRY iGetFile(void) -{ - return FileRead; -} - - -const ILubyte* ILAPIENTRY iGetLump(void) { - return (ILubyte*)ReadLump; -} - - - -// Next 4 functions are the default write functions - -ILint ILAPIENTRY iPutcFile(ILubyte Char) -{ - return PutcProc(Char, FileWrite); -} - - -ILint ILAPIENTRY iPutcLump(ILubyte Char) -{ - if (WriteLumpPos >= WriteLumpSize) - return IL_EOF; // IL_EOF - *((ILubyte*)(WriteLump) + WriteLumpPos++) = Char; - return Char; -} - - -ILint ILAPIENTRY iWriteFile(const void *Buffer, ILuint Size, ILuint Number) -{ - ILuint NumWritten; - NumWritten = WriteProc(Buffer, Size, Number, FileWrite); - if (NumWritten != Number) { - ilSetError(IL_FILE_WRITE_ERROR); - return 0; - } - return NumWritten; -} - - -ILint ILAPIENTRY iWriteLump(const void *Buffer, ILuint Size, ILuint Number) -{ - ILuint SizeBytes = Size * Number; - ILuint i = 0; - - for (; i < SizeBytes; i++) { - if (WriteLumpSize > 0) { - if (WriteLumpPos + i >= WriteLumpSize) { // Should we use > instead? - ilSetError(IL_FILE_WRITE_ERROR); - WriteLumpPos += i; - return i; - } - } - - *((ILubyte*)WriteLump + WriteLumpPos + i) = *((ILubyte*)Buffer + i); - } - - WriteLumpPos += SizeBytes; - - return SizeBytes; -} - - -ILint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode) -{ - if (Mode == IL_SEEK_SET) - Offset += WriteFileStart; // This allows us to use IL_SEEK_SET in the middle of a file. - return SeekWProc(FileWrite, Offset, Mode); -} - - -// Returns 1 on error, 0 on success -ILint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode) -{ - switch (Mode) - { - case IL_SEEK_SET: - if (Offset > (ILint)WriteLumpSize) - return 1; - WriteLumpPos = Offset; - break; - - case IL_SEEK_CUR: - if (WriteLumpPos + Offset > WriteLumpSize) - return 1; - WriteLumpPos += Offset; - break; - - case IL_SEEK_END: - if (Offset > 0) - return 1; - // Should we use >= instead? - if (abs(Offset) > (ILint)WriteLumpSize) // If WriteLumpSize == 0, too bad - return 1; - WriteLumpPos = WriteLumpSize + Offset; - break; - - default: - return 1; - } - - return 0; -} - - -ILuint ILAPIENTRY iTellWFile(void) -{ - return TellWProc(FileWrite); -} - - -ILuint ILAPIENTRY iTellWLump(void) -{ - return WriteLumpPos; -} diff --git a/DevIL/src-IL/src/il_files.cpp b/DevIL/src-IL/src/il_files.cpp new file mode 100644 index 00000000..4c987d5c --- /dev/null +++ b/DevIL/src-IL/src/il_files.cpp @@ -0,0 +1,773 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 01/04/2009 +// +// Filename: src-IL/src/il_files.c +// +// Description: File handling for DevIL +// +//----------------------------------------------------------------------------- + + +#define __FILES_C +#include "il_internal.h" +#include + + +// All specific to the next set of functions +ILboolean ILAPIENTRY iEofFile(void); +ILboolean ILAPIENTRY iEofLump(void); +ILint ILAPIENTRY iGetcFile(void); +ILint ILAPIENTRY iGetcLump(void); +ILuint ILAPIENTRY iReadFile(void *Buffer, ILuint Size, ILuint Number); +ILuint ILAPIENTRY iReadLump(void *Buffer, const ILuint Size, const ILuint Number); +ILint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode); +ILint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode); +ILint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode); +ILint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode); +ILuint ILAPIENTRY iTellRFile(void); +ILuint ILAPIENTRY iTellRLump(void); +ILuint ILAPIENTRY iTellWFile(void); +ILuint ILAPIENTRY iTellWLump(void); +ILint ILAPIENTRY iPutcFile(ILubyte Char); +ILint ILAPIENTRY iPutcLump(ILubyte Char); +ILint ILAPIENTRY iWriteFile(const void *Buffer, ILuint Size, ILuint Number); +ILint ILAPIENTRY iWriteLump(const void *Buffer, ILuint Size, ILuint Number); +ILHANDLE FileRead = NULL, FileWrite = NULL; +const void *ReadLump = NULL; +void *WriteLump = NULL; +ILuint ReadLumpPos = 0, ReadLumpSize = 0, ReadFileStart = 0, WriteFileStart = 0; +ILuint WriteLumpPos = 0, WriteLumpSize = 0; + +fGetcProc GetcProcCopy; +fReadProc ReadProcCopy; +fSeekRProc SeekProcCopy; +fTellRProc TellProcCopy; +ILHANDLE (ILAPIENTRY *iopenCopy)(ILconst_string); +void (ILAPIENTRY *icloseCopy)(ILHANDLE); + +fPutcProc PutcProcCopy; +fSeekWProc SeekWProcCopy; +fTellWProc TellWProcCopy; +fWriteProc WriteProcCopy; +ILHANDLE (ILAPIENTRY *iopenwCopy)(ILconst_string); +void (ILAPIENTRY *iclosewCopy)(ILHANDLE); + +ILboolean UseCache = IL_FALSE; +ILubyte *Cache = NULL; +ILuint CacheSize, CachePos, CacheStartPos, CacheBytesRead; + +// "Fake" size functions +// Definitions are in il_size.c. +ILint ILAPIENTRY iSizeSeek(ILint Offset, ILuint Mode); +ILuint ILAPIENTRY iSizeTell(void); +ILint ILAPIENTRY iSizePutc(ILubyte Char); +ILint ILAPIENTRY iSizeWrite(const void *Buffer, ILuint Size, ILuint Number); + +// Just preserves the current read functions and replaces +// the current read functions with the default read funcs. +void ILAPIENTRY iPreserveReadFuncs() +{ + // Create backups + GetcProcCopy = GetcProc; + ReadProcCopy = ReadProc; + SeekProcCopy = SeekRProc; + TellProcCopy = TellRProc; + iopenCopy = iopenr; + icloseCopy = icloser; + + // Set the standard procs to read + ilResetRead(); + + return; +} + + +// Restores the read functions - must be used after iPreserveReadFuncs(). +void ILAPIENTRY iRestoreReadFuncs() +{ + GetcProc = GetcProcCopy; + ReadProc = ReadProcCopy; + SeekRProc = SeekProcCopy; + TellRProc = TellProcCopy; + iopenr = iopenCopy; + icloser = icloseCopy; + + return; +} + + +// Just preserves the current read functions and replaces +// the current read functions with the default read funcs. +void ILAPIENTRY iPreserveWriteFuncs() +{ + // Create backups + PutcProcCopy = PutcProc; + SeekWProcCopy = SeekWProc; + TellWProcCopy = TellWProc; + WriteProcCopy = WriteProc; + iopenwCopy = iopenw; + iclosewCopy = iclosew; + + // Set the standard procs to write + ilResetWrite(); + + return; +} + + +// Restores the read functions - must be used after iPreserveReadFuncs(). +void ILAPIENTRY iRestoreWriteFuncs() +{ + PutcProc = PutcProcCopy; + SeekWProc = SeekWProcCopy; + TellWProc = TellWProcCopy; + WriteProc = WriteProcCopy; + iopenw = iopenwCopy; + iclosew = iclosewCopy; + + return; +} + + +// Next 7 functions are the default read functions + +ILHANDLE ILAPIENTRY iDefaultOpenR(ILconst_string FileName) +{ +#ifndef _UNICODE + return (ILHANDLE)fopen((char*)FileName, "rb"); +#else + // Windows has a different function, _wfopen, to open UTF16 files, + // whereas Linux just uses fopen for its UTF8 files. + #ifdef _WIN32 + return (ILHANDLE)_wfopen(FileName, L"rb"); + #else + return (ILHANDLE)fopen((char*)FileName, "rb"); + #endif +#endif//UNICODE +} + + +void ILAPIENTRY iDefaultCloseR(ILHANDLE Handle) +{ + fclose((FILE*)Handle); + return; +} + + +ILboolean ILAPIENTRY iDefaultEof(ILHANDLE Handle) +{ + ILuint OrigPos, FileSize; + + // Find out the filesize for checking for the end of file + OrigPos = itell(); + iseek(0, IL_SEEK_END); + FileSize = itell(); + iseek(OrigPos, IL_SEEK_SET); + + if (itell() >= FileSize) + return IL_TRUE; + return IL_FALSE; +} + + +ILint ILAPIENTRY iDefaultGetc(ILHANDLE Handle) +{ + ILint Val; + + if (!UseCache) { + Val = fgetc((FILE*)Handle); + if (Val == IL_EOF) + ilSetError(IL_FILE_READ_ERROR); + } + else { + Val = 0; + if (iread(&Val, 1, 1) != 1) + return IL_EOF; + } + return Val; +} + + +ILint ILAPIENTRY iDefaultRead(void *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle) +{ + return (ILint)fread(Buffer, Size, Number, (FILE*)Handle); +} + + +ILint ILAPIENTRY iDefaultRSeek(ILHANDLE Handle, ILint Offset, ILint Mode) +{ + return fseek((FILE*)Handle, Offset, Mode); +} + + +ILint ILAPIENTRY iDefaultWSeek(ILHANDLE Handle, ILint Offset, ILint Mode) +{ + return fseek((FILE*)Handle, Offset, Mode); +} + + +ILint ILAPIENTRY iDefaultRTell(ILHANDLE Handle) +{ + return ftell((FILE*)Handle); +} + + +ILint ILAPIENTRY iDefaultWTell(ILHANDLE Handle) +{ + return ftell((FILE*)Handle); +} + + +ILHANDLE ILAPIENTRY iDefaultOpenW(ILconst_string FileName) +{ +#ifndef _UNICODE + return (ILHANDLE)fopen((char*)FileName, "wb"); +#else + // Windows has a different function, _wfopen, to open UTF16 files, + // whereas Linux just uses fopen. + #ifdef _WIN32 + return (ILHANDLE)_wfopen(FileName, L"wb"); + #else + return (ILHANDLE)fopen((char*)FileName, "wb"); + #endif +#endif//UNICODE +} + + +void ILAPIENTRY iDefaultCloseW(ILHANDLE Handle) +{ + fclose((FILE*)Handle); + return; +} + + +ILint ILAPIENTRY iDefaultPutc(ILubyte Char, ILHANDLE Handle) +{ + return fputc(Char, (FILE*)Handle); +} + + +ILint ILAPIENTRY iDefaultWrite(const void *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle) +{ + return (ILint)fwrite(Buffer, Size, Number, (FILE*)Handle); +} + + +void ILAPIENTRY ilResetRead() +{ + ilSetRead(iDefaultOpenR, iDefaultCloseR, iDefaultEof, iDefaultGetc, + iDefaultRead, iDefaultRSeek, iDefaultRTell); + return; +} + + +void ILAPIENTRY ilResetWrite() +{ + ilSetWrite(iDefaultOpenW, iDefaultCloseW, iDefaultPutc, + iDefaultWSeek, iDefaultWTell, iDefaultWrite); + return; +} + + +//! Allows you to override the default file-reading functions. +void ILAPIENTRY ilSetRead(fOpenRProc Open, fCloseRProc Close, fEofProc Eof, fGetcProc Getc, fReadProc Read, fSeekRProc Seek, fTellRProc Tell) +{ + iopenr = Open; + icloser = Close; + EofProc = Eof; + GetcProc = Getc; + ReadProc = Read; + SeekRProc = Seek; + TellRProc = Tell; + + return; +} + + +//! Allows you to override the default file-writing functions. +void ILAPIENTRY ilSetWrite(fOpenRProc Open, fCloseRProc Close, fPutcProc Putc, fSeekWProc Seek, fTellWProc Tell, fWriteProc Write) +{ + iopenw = Open; + iclosew = Close; + PutcProc = Putc; + WriteProc = Write; + SeekWProc = Seek; + TellWProc = Tell; + + return; +} + + +// Tells DevIL that we're reading from a file, not a lump +void iSetInputFile(ILHANDLE File) +{ + ieof = iEofFile; + igetc = iGetcFile; + iread = iReadFile; + iseek = iSeekRFile; + itell = iTellRFile; + FileRead = File; + ReadFileStart = itell(); +} + + +// Tells DevIL that we're reading from a lump, not a file +void iSetInputLump(const void *Lump, ILuint Size) +{ + ieof = iEofLump; + igetc = iGetcLump; + iread = iReadLump; + iseek = iSeekRLump; + itell = iTellRLump; + ReadLump = Lump; + ReadLumpPos = 0; + ReadLumpSize = Size; +} + + +// Tells DevIL that we're writing to a file, not a lump +void iSetOutputFile(ILHANDLE File) +{ + // Helps with ilGetLumpPos(). + WriteLump = NULL; + WriteLumpPos = 0; + WriteLumpSize = 0; + + iputc = iPutcFile; + iseekw = iSeekWFile; + itellw = iTellWFile; + iwrite = iWriteFile; + FileWrite = File; +} + + +// This is only called by ilDetermineSize. Associates iputc, etc. with +// "fake" writing functions in il_size.c. +void iSetOutputFake(void) +{ + iputc = iSizePutc; + iseekw = iSizeSeek; + itellw = iSizeTell; + iwrite = iSizeWrite; + return; +} + + +// Tells DevIL that we're writing to a lump, not a file +void iSetOutputLump(void *Lump, ILuint Size) +{ + // In this case, ilDetermineSize is currently trying to determine the + // output buffer size. It already has the write functions it needs. + if (Lump == NULL) + return; + + iputc = iPutcLump; + iseekw = iSeekWLump; + itellw = iTellWLump; + iwrite = iWriteLump; + WriteLump = Lump; + WriteLumpPos = 0; + WriteLumpSize = Size; +} + + +ILuint ILAPIENTRY ilGetLumpPos() +{ + if (WriteLump) + return WriteLumpPos; + return 0; +} + + +ILuint ILAPIENTRY ilprintf(const char *Line, ...) +{ + char Buffer[2048]; // Hope this is large enough + va_list VaLine; + ILuint i; + + va_start(VaLine, Line); + vsprintf(Buffer, Line, VaLine); + va_end(VaLine); + + i = ilCharStrLen(Buffer); + iwrite(Buffer, 1, i); + + return i; +} + + +// To pad zeros where needed... +void ipad(ILuint NumZeros) +{ + ILuint i = 0; + for (; i < NumZeros; i++) + iputc(0); + return; +} + + +// +// The rest of the functions following in this file are quite +// self-explanatory, except where commented. +// + +// Next 12 functions are the default write functions + +ILboolean ILAPIENTRY iEofFile(void) +{ + return EofProc((FILE*)FileRead); +} + + +ILboolean ILAPIENTRY iEofLump(void) +{ + if (ReadLumpSize) + return (ReadLumpPos >= ReadLumpSize); + return IL_FALSE; +} + + +ILint ILAPIENTRY iGetcFile(void) +{ + if (!UseCache) { + return GetcProc(FileRead); + } + if (CachePos >= CacheSize) { + iPreCache(CacheSize); + } + + CacheBytesRead++; + return Cache[CachePos++]; +} + + +ILint ILAPIENTRY iGetcLump(void) +{ + // If ReadLumpSize is 0, don't even check to see if we've gone past the bounds. + if (ReadLumpSize > 0) { + if (ReadLumpPos + 1 > ReadLumpSize) { + ReadLumpPos--; + ilSetError(IL_FILE_READ_ERROR); + return IL_EOF; + } + } + + return *((ILubyte*)ReadLump + ReadLumpPos++); +} + + +ILuint ILAPIENTRY iReadFile(void *Buffer, ILuint Size, ILuint Number) +{ + ILuint TotalBytes = 0, BytesCopied; + ILuint BuffSize = Size * Number; + ILuint NumRead; + + if (!UseCache) { + NumRead = ReadProc(Buffer, Size, Number, FileRead); + if (NumRead != Number) + ilSetError(IL_FILE_READ_ERROR); + return NumRead; + } + + /*if (Cache == NULL || CacheSize == 0) { // Shouldn't happen, but we check anyway. + return ReadProc(Buffer, Size, Number, FileRead); + }*/ + + if (BuffSize < CacheSize - CachePos) { + memcpy(Buffer, Cache + CachePos, BuffSize); + CachePos += BuffSize; + CacheBytesRead += BuffSize; + if (Size != 0) + BuffSize /= Size; + return BuffSize; + } + else { + while (TotalBytes < BuffSize) { + // If loop through more than once, after first, CachePos is 0. + if (TotalBytes + CacheSize - CachePos > BuffSize) + BytesCopied = BuffSize - TotalBytes; + else + BytesCopied = CacheSize - CachePos; + + memcpy((ILubyte*)Buffer + TotalBytes, Cache + CachePos, BytesCopied); + TotalBytes += BytesCopied; + CachePos += BytesCopied; + if (TotalBytes < BuffSize) { + iPreCache(CacheSize); + } + } + } + + // DW: Changed on 12-27-2008. Was causing the position to go too far if the + // cache was smaller than the buffer. + //CacheBytesRead += TotalBytes; + CacheBytesRead = CachePos; + if (Size != 0) + TotalBytes /= Size; + if (TotalBytes != Number) + ilSetError(IL_FILE_READ_ERROR); + return TotalBytes; +} + + +ILuint ILAPIENTRY iReadLump(void *Buffer, const ILuint Size, const ILuint Number) +{ + ILuint i, ByteSize = IL_MIN( Size*Number, ReadLumpSize-ReadLumpPos); + + for (i = 0; i < ByteSize; i++) { + *((ILubyte*)Buffer + i) = *((ILubyte*)ReadLump + ReadLumpPos + i); + if (ReadLumpSize > 0) { // ReadLumpSize is too large to care about apparently + if (ReadLumpPos + i > ReadLumpSize) { + ReadLumpPos += i; + if (i != Number) + ilSetError(IL_FILE_READ_ERROR); + return i; + } + } + } + + ReadLumpPos += i; + if (Size != 0) + i /= Size; + if (i != Number) + ilSetError(IL_FILE_READ_ERROR); + return i; +} + + +ILboolean iPreCache(ILuint Size) +{ + // Reading from a memory lump, so don't cache. + if (iread == iReadLump) { + //iUnCache(); // DW: Removed 06-10-2002. + return IL_TRUE; + } + + if (Cache) { + ifree(Cache); + } + + if (Size == 0) { + Size = 1; + } + + Cache = (ILubyte*)ialloc(Size); + if (Cache == NULL) { + return IL_FALSE; + } + + UseCache = IL_FALSE; + CacheStartPos = itell(); + CacheSize = iread(Cache, 1, Size); + if (CacheSize != Size) + ilGetError(); // Get rid of the IL_FILE_READ_ERROR. + + //2003-09-09: uncommented the following line to prevent + //an infinite loop in ilPreCache() + CacheSize = Size; + CachePos = 0; + UseCache = IL_TRUE; + CacheBytesRead = 0; + + return IL_TRUE; +} + + +void iUnCache() +{ + //changed 2003-09-01: + //make iUnCache smart enough to return if + //no cache is used + if (!UseCache) + return; + + if (iread == iReadLump) + return; + + CacheSize = 0; + CachePos = 0; + if (Cache) { + ifree(Cache); + Cache = NULL; + } + UseCache = IL_FALSE; + + iseek(CacheStartPos + CacheBytesRead, IL_SEEK_SET); + + return; +} + + +ILint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode) +{ + if (Mode == IL_SEEK_SET) + Offset += ReadFileStart; // This allows us to use IL_SEEK_SET in the middle of a file. + return SeekRProc(FileRead, Offset, Mode); +} + + +// Returns 1 on error, 0 on success +ILint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode) +{ + switch (Mode) + { + case IL_SEEK_SET: + if (Offset > (ILint)ReadLumpSize) + return 1; + ReadLumpPos = Offset; + break; + + case IL_SEEK_CUR: + if (ReadLumpPos + Offset > ReadLumpSize) + return 1; + ReadLumpPos += Offset; + break; + + case IL_SEEK_END: + if (Offset > 0) + return 1; + // Should we use >= instead? + if (abs(Offset) > (ILint)ReadLumpSize) // If ReadLumpSize == 0, too bad + return 1; + ReadLumpPos = ReadLumpSize + Offset; + break; + + default: + return 1; + } + + return 0; +} + + +ILuint ILAPIENTRY iTellRFile(void) +{ + return TellRProc(FileRead); +} + + +ILuint ILAPIENTRY iTellRLump(void) +{ + return ReadLumpPos; +} + + +ILHANDLE ILAPIENTRY iGetFile(void) +{ + return FileRead; +} + + +const ILubyte* ILAPIENTRY iGetLump(void) { + return (ILubyte*)ReadLump; +} + + + +// Next 4 functions are the default write functions + +ILint ILAPIENTRY iPutcFile(ILubyte Char) +{ + return PutcProc(Char, FileWrite); +} + + +ILint ILAPIENTRY iPutcLump(ILubyte Char) +{ + if (WriteLumpPos >= WriteLumpSize) + return IL_EOF; // IL_EOF + *((ILubyte*)(WriteLump) + WriteLumpPos++) = Char; + return Char; +} + + +ILint ILAPIENTRY iWriteFile(const void *Buffer, ILuint Size, ILuint Number) +{ + ILuint NumWritten; + NumWritten = WriteProc(Buffer, Size, Number, FileWrite); + if (NumWritten != Number) { + ilSetError(IL_FILE_WRITE_ERROR); + return 0; + } + return NumWritten; +} + + +ILint ILAPIENTRY iWriteLump(const void *Buffer, ILuint Size, ILuint Number) +{ + ILuint SizeBytes = Size * Number; + ILuint i = 0; + + for (; i < SizeBytes; i++) { + if (WriteLumpSize > 0) { + if (WriteLumpPos + i >= WriteLumpSize) { // Should we use > instead? + ilSetError(IL_FILE_WRITE_ERROR); + WriteLumpPos += i; + return i; + } + } + + *((ILubyte*)WriteLump + WriteLumpPos + i) = *((ILubyte*)Buffer + i); + } + + WriteLumpPos += SizeBytes; + + return SizeBytes; +} + + +ILint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode) +{ + if (Mode == IL_SEEK_SET) + Offset += WriteFileStart; // This allows us to use IL_SEEK_SET in the middle of a file. + return SeekWProc(FileWrite, Offset, Mode); +} + + +// Returns 1 on error, 0 on success +ILint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode) +{ + switch (Mode) + { + case IL_SEEK_SET: + if (Offset > (ILint)WriteLumpSize) + return 1; + WriteLumpPos = Offset; + break; + + case IL_SEEK_CUR: + if (WriteLumpPos + Offset > WriteLumpSize) + return 1; + WriteLumpPos += Offset; + break; + + case IL_SEEK_END: + if (Offset > 0) + return 1; + // Should we use >= instead? + if (abs(Offset) > (ILint)WriteLumpSize) // If WriteLumpSize == 0, too bad + return 1; + WriteLumpPos = WriteLumpSize + Offset; + break; + + default: + return 1; + } + + return 0; +} + + +ILuint ILAPIENTRY iTellWFile(void) +{ + return TellWProc(FileWrite); +} + + +ILuint ILAPIENTRY iTellWLump(void) +{ + return WriteLumpPos; +} diff --git a/DevIL/src-IL/src/il_fits.c b/DevIL/src-IL/src/il_fits.c deleted file mode 100644 index bd3c04a2..00000000 --- a/DevIL/src-IL/src/il_fits.c +++ /dev/null @@ -1,472 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/14/2009 -// -// Filename: src-IL/src/il_fits.c -// -// Description: Reads from a Flexible Image Transport System (.fits) file. -// Specifications were found at -// http://www.fileformat.info/format/fits. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_FITS - -typedef struct FITSHEAD -{ - ILboolean IsSimple; - ILint BitsPixel; - ILint NumAxes; // Number of dimensions / axes - ILint Width; - ILint Height; - ILint Depth; - ILint NumChans; - - // Not in the header, but it keeps everything together. - ILenum Type; - ILenum Format; - -} FITSHEAD; - -enum { - CARD_READ_FAIL = -1, - CARD_END = 1, - CARD_SIMPLE, - CARD_NOT_SIMPLE, - CARD_BITPIX, - CARD_NUMAXES, - CARD_AXIS, - CARD_SKIP -}; - -ILboolean iIsValidFits(void); -ILboolean iCheckFits(FITSHEAD *Header); -ILboolean iLoadFitsInternal(void); -ILenum GetCardImage(FITSHEAD *Header); -ILboolean GetCardInt(char *Buffer, ILint *Val); - -//! Checks if the file specified in FileName is a valid FITS file. -ILboolean ilIsValidFits(ILconst_string FileName) -{ - ILHANDLE FitsFile; - ILboolean bFits = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("fits")) && !iCheckExtension(FileName, IL_TEXT("fit"))) { - ilSetError(IL_INVALID_EXTENSION); - return bFits; - } - - FitsFile = iopenr(FileName); - if (FitsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bFits; - } - - bFits = ilIsValidFitsF(FitsFile); - icloser(FitsFile); - - return bFits; -} - - -//! Checks if the ILHANDLE contains a valid FITS file at the current position. -ILboolean ilIsValidFitsF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidFits(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid FITS lump. -ILboolean ilIsValidFitsL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidFits(); -} - - -// Internal function used to get the FITS header from the current file. -ILboolean iGetFitsHead(FITSHEAD *Header) -{ - ILenum CardKey; - -//@TODO: Use something other than memset? - memset(Header, 0, sizeof(Header)); // Clear the header to all 0s first. - - do { - CardKey = GetCardImage(Header); - if (CardKey == CARD_END) // End of the header - break; - if (CardKey == CARD_READ_FAIL) - return IL_FALSE; - if (CardKey == CARD_NOT_SIMPLE) - return IL_FALSE; - } while (!ieof()); - - // The header should never reach the end of the file. - if (ieof()) - return IL_FALSE; // Error needed? - - // The header must always be a multiple of 2880, so we skip the padding bytes (spaces). - iseek((2880 - (itell() % 2880)) % 2880, IL_SEEK_CUR); - - switch (Header->BitsPixel) - { - case 8: - Header->Type = IL_UNSIGNED_BYTE; - break; - case 16: - Header->Type = IL_SHORT; - break; - case 32: - Header->Type = IL_INT; - break; - case -32: - Header->Type = IL_FLOAT; - break; - case -64: - Header->Type = IL_DOUBLE; - break; - default: - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - switch (Header->NumAxes) - { - case 1: // Just a 1D image - Header->Format = IL_LUMINANCE; - Header->Height = 1; - Header->Depth = 1; - Header->NumChans = 1; - break; - - case 2: // Assuming it is a 2D image (width+height) - Header->Format = IL_LUMINANCE; - Header->Depth = 1; - Header->NumChans = 1; - break; - - case 3: - // We cannot deal with more than 3 channels in an image. - Header->Format = IL_LUMINANCE; - Header->NumChans = 1; - break; - - default: - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidFits(void) -{ - FITSHEAD Header; - ILuint Pos = itell(); - - if (!iGetFitsHead(&Header)) - return IL_FALSE; - // The length of the header varies, so we just go back to the original position. - iseek(Pos, IL_SEEK_CUR); - - return iCheckFits(&Header); -} - - -// Internal function used to check if the HEADER is a valid FITS header. -ILboolean iCheckFits(FITSHEAD *Header) -{ - switch (Header->BitsPixel) - { - case 8: // These are the only values accepted. - case 16: - case 32: - case -32: - case -64: - break; - default: - return IL_FALSE; - } - - switch (Header->NumAxes) - { - case 1: // Just a 1D image - case 2: // Assuming it is a 2D image (width+height) - case 3: // 3D image (with depth) - break; - default: - return IL_FALSE; - } - - // Possibility that one of these values is returned as <= 0 by atoi, which we cannot use. - if (Header->Width <= 0 || Header->Height <= 0 || Header->Depth <= 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - return IL_TRUE; -} - - -//! Reads a FITS file -ILboolean ilLoadFits(ILconst_string FileName) -{ - ILHANDLE FitsFile; - ILboolean bFits = IL_FALSE; - - FitsFile = iopenr(FileName); - if (FitsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bFits; - } - - bFits = ilLoadFitsF(FitsFile); - icloser(FitsFile); - - return bFits; -} - - -//! Reads an already-opened FITS file -ILboolean ilLoadFitsF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadFitsInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a FITS -ILboolean ilLoadFitsL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadFitsInternal(); -} - - -// Internal function used to load the FITS. -ILboolean iLoadFitsInternal(void) -{ - FITSHEAD Header; - ILuint i, NumPix; - ILfloat MaxF = 0.0f; - ILdouble MaxD = 0.0f; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetFitsHead(&Header)) - return IL_FALSE; - if (!iCheckFits(&Header)) - return IL_FALSE; - - if (!ilTexImage(Header.Width, Header.Height, Header.Depth, Header.NumChans, Header.Format, Header.Type, NULL)) - return IL_FALSE; - - /*if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) - return IL_FALSE;*/ - - NumPix = Header.Width * Header.Height * Header.Depth; -//@TODO: Do some checks while reading to see if we have hit the end of the file. - switch (Header.Type) - { - case IL_UNSIGNED_BYTE: - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) - return IL_FALSE; - break; - case IL_SHORT: - for (i = 0; i < NumPix; i++) { - ((ILshort*)iCurImage->Data)[i] = GetBigShort(); - } - break; - case IL_INT: - for (i = 0; i < NumPix; i++) { - ((ILint*)iCurImage->Data)[i] = GetBigInt(); - } - break; - case IL_FLOAT: - for (i = 0; i < NumPix; i++) { - ((ILfloat*)iCurImage->Data)[i] = GetBigFloat(); - if (((ILfloat*)iCurImage->Data)[i] > MaxF) - MaxF = ((ILfloat*)iCurImage->Data)[i]; - } - - // Renormalize to [0..1]. - for (i = 0; i < NumPix; i++) { - // Change all negative numbers to 0. - if (((ILfloat*)iCurImage->Data)[i] < 0.0f) - ((ILfloat*)iCurImage->Data)[i] = 0.0f; - // Do the renormalization now, dividing by the maximum value. - ((ILfloat*)iCurImage->Data)[i] = ((ILfloat*)iCurImage->Data)[i] / MaxF; - } - break; - case IL_DOUBLE: - for (i = 0; i < NumPix; i++) { - ((ILdouble*)iCurImage->Data)[i] = GetBigDouble(); - if (((ILdouble*)iCurImage->Data)[i] > MaxD) - MaxD = ((ILdouble*)iCurImage->Data)[i]; - } - - // Renormalize to [0..1]. - for (i = 0; i < NumPix; i++) { - // Change all negative numbers to 0. - if (((ILdouble*)iCurImage->Data)[i] < 0.0f) - ((ILdouble*)iCurImage->Data)[i] = 0.0f; - // Do the renormalization now, dividing by the maximum value. - ((ILdouble*)iCurImage->Data)[i] = ((ILdouble*)iCurImage->Data)[i] / MaxD; - } break; - } - - return ilFixImage(); -} - - -//@TODO: NAXISx have to come in order. Check this! -ILenum GetCardImage(FITSHEAD *Header) -{ - char Buffer[80]; - - if (iread(Buffer, 1, 80) != 80) // Each card image is exactly 80 bytes long. - return CARD_READ_FAIL; - -//@TODO: Use something other than !strncmp? - if (!strncmp(Buffer, "END ", 4)) - return CARD_END; - - else if (!strncmp(Buffer, "SIMPLE ", 7)) { - // The true value 'T' is always in the 30th position. - if (Buffer[29] != 'T') { - // We cannot support FITS files that do not correspond to the standard. - Header->IsSimple = IL_FALSE; //@TODO: Does this even need to be set? Should exit loading anyway. - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return CARD_NOT_SIMPLE; - } - Header->IsSimple = IL_TRUE; - return CARD_SIMPLE; - } - - else if (!strncmp(Buffer, "BITPIX ", 7)) { - // The specs state that BITPIX has to come after SIMPLE. - if (Header->IsSimple != IL_TRUE) { - ilSetError(IL_INVALID_FILE_HEADER); - return CARD_READ_FAIL; - } - if (GetCardInt(Buffer, &Header->BitsPixel) != IL_TRUE) - return CARD_READ_FAIL; -//@TODO: Should I do this check from the calling function? Does it really matter? - if (Header->BitsPixel == 0) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return CARD_READ_FAIL; - } - return CARD_BITPIX; - } - - // Needs the space after NAXIS so that it does not get this confused with NAXIS1, NAXIS2, etc. - else if (!strncmp(Buffer, "NAXIS ", 6)) { - if (GetCardInt(Buffer, &Header->NumAxes) != IL_TRUE) - return CARD_READ_FAIL; -//@TODO: Should I do this check from the calling function? Does it really matter? - if (Header->NumAxes < 1 || Header->NumAxes > 3) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return CARD_READ_FAIL; - } - return CARD_NUMAXES; - } - - else if (!strncmp(Buffer, "NAXIS1 ", 7)) { - if (Header->NumAxes == 0) { // Has not been initialized, and it has to come first. - ilSetError(IL_INVALID_FILE_HEADER); - return CARD_READ_FAIL; - } - // First one will always be the width. - if (GetCardInt(Buffer, &Header->Width) != IL_TRUE) - return CARD_READ_FAIL; - return CARD_AXIS; - } - - else if (!strncmp(Buffer, "NAXIS2 ", 7)) { - if (Header->NumAxes == 0) { // Has not been initialized, and it has to come first. - ilSetError(IL_INVALID_FILE_HEADER); - return CARD_READ_FAIL; - } - // Cannot have a 2nd axis for 0 or 1. - if (Header->NumAxes == 0 || Header->NumAxes == 1) { - ilSetError(IL_INVALID_FILE_HEADER); - return CARD_READ_FAIL; - } - -//@TODO: We are assuming that this is the height right now. Could it just be a -// 1D image with multiple bytes per pixel? - if (GetCardInt(Buffer, &Header->Height) != IL_TRUE) - return CARD_READ_FAIL; - return CARD_AXIS; - } - - else if (!strncmp(Buffer, "NAXIS3 ", 7)) { - if (Header->NumAxes == 0) { // Has not been initialized, and it has to come first. - ilSetError(IL_INVALID_FILE_HEADER); - return CARD_READ_FAIL; - } - // Cannot have a 3rd axis for 0, 1 and 2. - if (Header->NumAxes < 3) { - ilSetError(IL_INVALID_FILE_HEADER); - return CARD_READ_FAIL; - } - - if (GetCardInt(Buffer, &Header->Depth) != IL_TRUE) - return CARD_READ_FAIL; - return CARD_AXIS; - } - - return CARD_SKIP; // This is a card that we do not recognize, so skip it. -} - - -ILboolean GetCardInt(char *Buffer, ILint *Val) -{ - ILuint i; - char ValString[22]; - - if (Buffer[7] != '=' && Buffer[8] != '=') - return IL_FALSE; - for (i = 9; i < 30; i++) { - if (Buffer[i] != ' ' && Buffer[i] != 0) // Right-aligned with ' ' or 0, so skip. - break; - } - if (i == 30) // Did not find the integer in positions 10 - 30. - return IL_FALSE; - - //@TODO: Safest way to do this? - memcpy(ValString, &Buffer[i], 30-i); - ValString[30-i] = 0; // Terminate the string. - - //@TODO: Check the return somehow? - *Val = atoi(ValString); - - return IL_TRUE; -} - -#endif//IL_NO_FITS diff --git a/DevIL/src-IL/src/il_fits.cpp b/DevIL/src-IL/src/il_fits.cpp new file mode 100644 index 00000000..bd3c04a2 --- /dev/null +++ b/DevIL/src-IL/src/il_fits.cpp @@ -0,0 +1,472 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/14/2009 +// +// Filename: src-IL/src/il_fits.c +// +// Description: Reads from a Flexible Image Transport System (.fits) file. +// Specifications were found at +// http://www.fileformat.info/format/fits. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_FITS + +typedef struct FITSHEAD +{ + ILboolean IsSimple; + ILint BitsPixel; + ILint NumAxes; // Number of dimensions / axes + ILint Width; + ILint Height; + ILint Depth; + ILint NumChans; + + // Not in the header, but it keeps everything together. + ILenum Type; + ILenum Format; + +} FITSHEAD; + +enum { + CARD_READ_FAIL = -1, + CARD_END = 1, + CARD_SIMPLE, + CARD_NOT_SIMPLE, + CARD_BITPIX, + CARD_NUMAXES, + CARD_AXIS, + CARD_SKIP +}; + +ILboolean iIsValidFits(void); +ILboolean iCheckFits(FITSHEAD *Header); +ILboolean iLoadFitsInternal(void); +ILenum GetCardImage(FITSHEAD *Header); +ILboolean GetCardInt(char *Buffer, ILint *Val); + +//! Checks if the file specified in FileName is a valid FITS file. +ILboolean ilIsValidFits(ILconst_string FileName) +{ + ILHANDLE FitsFile; + ILboolean bFits = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("fits")) && !iCheckExtension(FileName, IL_TEXT("fit"))) { + ilSetError(IL_INVALID_EXTENSION); + return bFits; + } + + FitsFile = iopenr(FileName); + if (FitsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bFits; + } + + bFits = ilIsValidFitsF(FitsFile); + icloser(FitsFile); + + return bFits; +} + + +//! Checks if the ILHANDLE contains a valid FITS file at the current position. +ILboolean ilIsValidFitsF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidFits(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid FITS lump. +ILboolean ilIsValidFitsL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidFits(); +} + + +// Internal function used to get the FITS header from the current file. +ILboolean iGetFitsHead(FITSHEAD *Header) +{ + ILenum CardKey; + +//@TODO: Use something other than memset? + memset(Header, 0, sizeof(Header)); // Clear the header to all 0s first. + + do { + CardKey = GetCardImage(Header); + if (CardKey == CARD_END) // End of the header + break; + if (CardKey == CARD_READ_FAIL) + return IL_FALSE; + if (CardKey == CARD_NOT_SIMPLE) + return IL_FALSE; + } while (!ieof()); + + // The header should never reach the end of the file. + if (ieof()) + return IL_FALSE; // Error needed? + + // The header must always be a multiple of 2880, so we skip the padding bytes (spaces). + iseek((2880 - (itell() % 2880)) % 2880, IL_SEEK_CUR); + + switch (Header->BitsPixel) + { + case 8: + Header->Type = IL_UNSIGNED_BYTE; + break; + case 16: + Header->Type = IL_SHORT; + break; + case 32: + Header->Type = IL_INT; + break; + case -32: + Header->Type = IL_FLOAT; + break; + case -64: + Header->Type = IL_DOUBLE; + break; + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + switch (Header->NumAxes) + { + case 1: // Just a 1D image + Header->Format = IL_LUMINANCE; + Header->Height = 1; + Header->Depth = 1; + Header->NumChans = 1; + break; + + case 2: // Assuming it is a 2D image (width+height) + Header->Format = IL_LUMINANCE; + Header->Depth = 1; + Header->NumChans = 1; + break; + + case 3: + // We cannot deal with more than 3 channels in an image. + Header->Format = IL_LUMINANCE; + Header->NumChans = 1; + break; + + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidFits(void) +{ + FITSHEAD Header; + ILuint Pos = itell(); + + if (!iGetFitsHead(&Header)) + return IL_FALSE; + // The length of the header varies, so we just go back to the original position. + iseek(Pos, IL_SEEK_CUR); + + return iCheckFits(&Header); +} + + +// Internal function used to check if the HEADER is a valid FITS header. +ILboolean iCheckFits(FITSHEAD *Header) +{ + switch (Header->BitsPixel) + { + case 8: // These are the only values accepted. + case 16: + case 32: + case -32: + case -64: + break; + default: + return IL_FALSE; + } + + switch (Header->NumAxes) + { + case 1: // Just a 1D image + case 2: // Assuming it is a 2D image (width+height) + case 3: // 3D image (with depth) + break; + default: + return IL_FALSE; + } + + // Possibility that one of these values is returned as <= 0 by atoi, which we cannot use. + if (Header->Width <= 0 || Header->Height <= 0 || Header->Depth <= 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + return IL_TRUE; +} + + +//! Reads a FITS file +ILboolean ilLoadFits(ILconst_string FileName) +{ + ILHANDLE FitsFile; + ILboolean bFits = IL_FALSE; + + FitsFile = iopenr(FileName); + if (FitsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bFits; + } + + bFits = ilLoadFitsF(FitsFile); + icloser(FitsFile); + + return bFits; +} + + +//! Reads an already-opened FITS file +ILboolean ilLoadFitsF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadFitsInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a FITS +ILboolean ilLoadFitsL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadFitsInternal(); +} + + +// Internal function used to load the FITS. +ILboolean iLoadFitsInternal(void) +{ + FITSHEAD Header; + ILuint i, NumPix; + ILfloat MaxF = 0.0f; + ILdouble MaxD = 0.0f; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetFitsHead(&Header)) + return IL_FALSE; + if (!iCheckFits(&Header)) + return IL_FALSE; + + if (!ilTexImage(Header.Width, Header.Height, Header.Depth, Header.NumChans, Header.Format, Header.Type, NULL)) + return IL_FALSE; + + /*if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) + return IL_FALSE;*/ + + NumPix = Header.Width * Header.Height * Header.Depth; +//@TODO: Do some checks while reading to see if we have hit the end of the file. + switch (Header.Type) + { + case IL_UNSIGNED_BYTE: + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) + return IL_FALSE; + break; + case IL_SHORT: + for (i = 0; i < NumPix; i++) { + ((ILshort*)iCurImage->Data)[i] = GetBigShort(); + } + break; + case IL_INT: + for (i = 0; i < NumPix; i++) { + ((ILint*)iCurImage->Data)[i] = GetBigInt(); + } + break; + case IL_FLOAT: + for (i = 0; i < NumPix; i++) { + ((ILfloat*)iCurImage->Data)[i] = GetBigFloat(); + if (((ILfloat*)iCurImage->Data)[i] > MaxF) + MaxF = ((ILfloat*)iCurImage->Data)[i]; + } + + // Renormalize to [0..1]. + for (i = 0; i < NumPix; i++) { + // Change all negative numbers to 0. + if (((ILfloat*)iCurImage->Data)[i] < 0.0f) + ((ILfloat*)iCurImage->Data)[i] = 0.0f; + // Do the renormalization now, dividing by the maximum value. + ((ILfloat*)iCurImage->Data)[i] = ((ILfloat*)iCurImage->Data)[i] / MaxF; + } + break; + case IL_DOUBLE: + for (i = 0; i < NumPix; i++) { + ((ILdouble*)iCurImage->Data)[i] = GetBigDouble(); + if (((ILdouble*)iCurImage->Data)[i] > MaxD) + MaxD = ((ILdouble*)iCurImage->Data)[i]; + } + + // Renormalize to [0..1]. + for (i = 0; i < NumPix; i++) { + // Change all negative numbers to 0. + if (((ILdouble*)iCurImage->Data)[i] < 0.0f) + ((ILdouble*)iCurImage->Data)[i] = 0.0f; + // Do the renormalization now, dividing by the maximum value. + ((ILdouble*)iCurImage->Data)[i] = ((ILdouble*)iCurImage->Data)[i] / MaxD; + } break; + } + + return ilFixImage(); +} + + +//@TODO: NAXISx have to come in order. Check this! +ILenum GetCardImage(FITSHEAD *Header) +{ + char Buffer[80]; + + if (iread(Buffer, 1, 80) != 80) // Each card image is exactly 80 bytes long. + return CARD_READ_FAIL; + +//@TODO: Use something other than !strncmp? + if (!strncmp(Buffer, "END ", 4)) + return CARD_END; + + else if (!strncmp(Buffer, "SIMPLE ", 7)) { + // The true value 'T' is always in the 30th position. + if (Buffer[29] != 'T') { + // We cannot support FITS files that do not correspond to the standard. + Header->IsSimple = IL_FALSE; //@TODO: Does this even need to be set? Should exit loading anyway. + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return CARD_NOT_SIMPLE; + } + Header->IsSimple = IL_TRUE; + return CARD_SIMPLE; + } + + else if (!strncmp(Buffer, "BITPIX ", 7)) { + // The specs state that BITPIX has to come after SIMPLE. + if (Header->IsSimple != IL_TRUE) { + ilSetError(IL_INVALID_FILE_HEADER); + return CARD_READ_FAIL; + } + if (GetCardInt(Buffer, &Header->BitsPixel) != IL_TRUE) + return CARD_READ_FAIL; +//@TODO: Should I do this check from the calling function? Does it really matter? + if (Header->BitsPixel == 0) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return CARD_READ_FAIL; + } + return CARD_BITPIX; + } + + // Needs the space after NAXIS so that it does not get this confused with NAXIS1, NAXIS2, etc. + else if (!strncmp(Buffer, "NAXIS ", 6)) { + if (GetCardInt(Buffer, &Header->NumAxes) != IL_TRUE) + return CARD_READ_FAIL; +//@TODO: Should I do this check from the calling function? Does it really matter? + if (Header->NumAxes < 1 || Header->NumAxes > 3) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return CARD_READ_FAIL; + } + return CARD_NUMAXES; + } + + else if (!strncmp(Buffer, "NAXIS1 ", 7)) { + if (Header->NumAxes == 0) { // Has not been initialized, and it has to come first. + ilSetError(IL_INVALID_FILE_HEADER); + return CARD_READ_FAIL; + } + // First one will always be the width. + if (GetCardInt(Buffer, &Header->Width) != IL_TRUE) + return CARD_READ_FAIL; + return CARD_AXIS; + } + + else if (!strncmp(Buffer, "NAXIS2 ", 7)) { + if (Header->NumAxes == 0) { // Has not been initialized, and it has to come first. + ilSetError(IL_INVALID_FILE_HEADER); + return CARD_READ_FAIL; + } + // Cannot have a 2nd axis for 0 or 1. + if (Header->NumAxes == 0 || Header->NumAxes == 1) { + ilSetError(IL_INVALID_FILE_HEADER); + return CARD_READ_FAIL; + } + +//@TODO: We are assuming that this is the height right now. Could it just be a +// 1D image with multiple bytes per pixel? + if (GetCardInt(Buffer, &Header->Height) != IL_TRUE) + return CARD_READ_FAIL; + return CARD_AXIS; + } + + else if (!strncmp(Buffer, "NAXIS3 ", 7)) { + if (Header->NumAxes == 0) { // Has not been initialized, and it has to come first. + ilSetError(IL_INVALID_FILE_HEADER); + return CARD_READ_FAIL; + } + // Cannot have a 3rd axis for 0, 1 and 2. + if (Header->NumAxes < 3) { + ilSetError(IL_INVALID_FILE_HEADER); + return CARD_READ_FAIL; + } + + if (GetCardInt(Buffer, &Header->Depth) != IL_TRUE) + return CARD_READ_FAIL; + return CARD_AXIS; + } + + return CARD_SKIP; // This is a card that we do not recognize, so skip it. +} + + +ILboolean GetCardInt(char *Buffer, ILint *Val) +{ + ILuint i; + char ValString[22]; + + if (Buffer[7] != '=' && Buffer[8] != '=') + return IL_FALSE; + for (i = 9; i < 30; i++) { + if (Buffer[i] != ' ' && Buffer[i] != 0) // Right-aligned with ' ' or 0, so skip. + break; + } + if (i == 30) // Did not find the integer in positions 10 - 30. + return IL_FALSE; + + //@TODO: Safest way to do this? + memcpy(ValString, &Buffer[i], 30-i); + ValString[30-i] = 0; // Terminate the string. + + //@TODO: Check the return somehow? + *Val = atoi(ValString); + + return IL_TRUE; +} + +#endif//IL_NO_FITS diff --git a/DevIL/src-IL/src/il_ftx.c b/DevIL/src-IL/src/il_ftx.c deleted file mode 100644 index 3de00c02..00000000 --- a/DevIL/src-IL/src/il_ftx.c +++ /dev/null @@ -1,101 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/12/2009 -// -// Filename: src-IL/src/il_ftx.c -// -// Description: Reads from a Heavy Metal: FAKK2 (.ftx) file. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_FTX - -ILboolean iLoadFtxInternal(void); - - -//! Reads a FTX file -ILboolean ilLoadFtx(ILconst_string FileName) -{ - ILHANDLE FtxFile; - ILboolean bFtx = IL_FALSE; - - FtxFile = iopenr(FileName); - if (FtxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bFtx; - } - - bFtx = ilLoadFtxF(FtxFile); - icloser(FtxFile); - - return bFtx; -} - - -//! Reads an already-opened FTX file -ILboolean ilLoadFtxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadFtxInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a FTX -ILboolean ilLoadFtxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadFtxInternal(); -} - - -// Internal function used to load the FTX. -ILboolean iLoadFtxInternal(void) -{ - ILuint Width, Height, HasAlpha; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Width = GetLittleUInt(); - Height = GetLittleUInt(); - HasAlpha = GetLittleUInt(); // Kind of backwards from what I would think... - - //@TODO: Right now, it appears that all images are in RGBA format. See if I can find specs otherwise - // or images that load incorrectly like this. - //if (HasAlpha == 0) { // RGBA format - if (!ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - //} - //else if (HasAlpha == 1) { // RGB format - // if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - // return IL_FALSE; - //} - //else { // Unknown format - // ilSetError(IL_INVALID_FILE_HEADER); - // return IL_FALSE; - //} - - // The origin will always be in the upper left. - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - // All we have to do for this format is read the raw, uncompressed data. - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) - return IL_FALSE; - - return ilFixImage(); -} - -#endif//IL_NO_FTX - diff --git a/DevIL/src-IL/src/il_ftx.cpp b/DevIL/src-IL/src/il_ftx.cpp new file mode 100644 index 00000000..3de00c02 --- /dev/null +++ b/DevIL/src-IL/src/il_ftx.cpp @@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/12/2009 +// +// Filename: src-IL/src/il_ftx.c +// +// Description: Reads from a Heavy Metal: FAKK2 (.ftx) file. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_FTX + +ILboolean iLoadFtxInternal(void); + + +//! Reads a FTX file +ILboolean ilLoadFtx(ILconst_string FileName) +{ + ILHANDLE FtxFile; + ILboolean bFtx = IL_FALSE; + + FtxFile = iopenr(FileName); + if (FtxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bFtx; + } + + bFtx = ilLoadFtxF(FtxFile); + icloser(FtxFile); + + return bFtx; +} + + +//! Reads an already-opened FTX file +ILboolean ilLoadFtxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadFtxInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a FTX +ILboolean ilLoadFtxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadFtxInternal(); +} + + +// Internal function used to load the FTX. +ILboolean iLoadFtxInternal(void) +{ + ILuint Width, Height, HasAlpha; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Width = GetLittleUInt(); + Height = GetLittleUInt(); + HasAlpha = GetLittleUInt(); // Kind of backwards from what I would think... + + //@TODO: Right now, it appears that all images are in RGBA format. See if I can find specs otherwise + // or images that load incorrectly like this. + //if (HasAlpha == 0) { // RGBA format + if (!ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + //} + //else if (HasAlpha == 1) { // RGB format + // if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + // return IL_FALSE; + //} + //else { // Unknown format + // ilSetError(IL_INVALID_FILE_HEADER); + // return IL_FALSE; + //} + + // The origin will always be in the upper left. + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + // All we have to do for this format is read the raw, uncompressed data. + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) + return IL_FALSE; + + return ilFixImage(); +} + +#endif//IL_NO_FTX + diff --git a/DevIL/src-IL/src/il_gif.c b/DevIL/src-IL/src/il_gif.c deleted file mode 100644 index 1ba78885..00000000 --- a/DevIL/src-IL/src/il_gif.c +++ /dev/null @@ -1,755 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_gif.c -// -// Description: Reads from a Graphics Interchange Format (.gif) file. -// -// The LZW decompression code is based on code released to the public domain -// by Javier Arevalo and can be found at -// http://www.programmersheaven.com/zone10/cat452 -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_GIF - -#include "il_gif.h" - - -ILenum GifType; - -//! Checks if the file specified in FileName is a valid Gif file. -ILboolean ilIsValidGif(ILconst_string FileName) -{ - ILHANDLE GifFile; - ILboolean bGif = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("gif"))) { - ilSetError(IL_INVALID_EXTENSION); - return bGif; - } - - GifFile = iopenr(FileName); - if (GifFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bGif; - } - - bGif = ilIsValidGifF(GifFile); - icloser(GifFile); - - return bGif; -} - - -//! Checks if the ILHANDLE contains a valid Gif file at the current position. -ILboolean ilIsValidGifF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidGif(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid Gif lump. -ILboolean ilIsValidGifL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidGif(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidGif() -{ - char Header[6]; - - if (iread(Header, 1, 6) != 6) - return IL_FALSE; - iseek(-6, IL_SEEK_CUR); - - if (!strnicmp(Header, "GIF87A", 6)) - return IL_TRUE; - if (!strnicmp(Header, "GIF89A", 6)) - return IL_TRUE; - - return IL_FALSE; -} - - -//! Reads a Gif file -ILboolean ilLoadGif(ILconst_string FileName) -{ - ILHANDLE GifFile; - ILboolean bGif = IL_FALSE; - - GifFile = iopenr(FileName); - if (GifFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bGif; - } - - bGif = ilLoadGifF(GifFile); - icloser(GifFile); - - return bGif; -} - - -//! Reads an already-opened Gif file -ILboolean ilLoadGifF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadGifInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Gif -ILboolean ilLoadGifL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadGifInternal(); -} - - -// Internal function used to load the Gif. -ILboolean iLoadGifInternal() -{ - GIFHEAD Header; - ILpal GlobalPal; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - GlobalPal.Palette = NULL; - GlobalPal.PalSize = 0; - - //read header - iread(&Header.Sig, 1, 6); - Header.Width = GetLittleUShort(); - Header.Height = GetLittleUShort(); - Header.ColourInfo = igetc(); - Header.Background = igetc(); - Header.Aspect = igetc(); - - if (!strnicmp(Header.Sig, "GIF87A", 6)) { - GifType = GIF87A; - } - else if (!strnicmp(Header.Sig, "GIF89A", 6)) { - GifType = GIF89A; - } - else { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - // Check for a global colour map. - if (Header.ColourInfo & (1 << 7)) { - if (!iGetPalette(Header.ColourInfo, &GlobalPal, IL_FALSE, NULL)) { - return IL_FALSE; - } - } - - if (!GetImages(&GlobalPal, &Header)) - return IL_FALSE; - - if (GlobalPal.Palette && GlobalPal.PalSize) - ifree(GlobalPal.Palette); - GlobalPal.Palette = NULL; - GlobalPal.PalSize = 0; - - return ilFixImage(); -} - - -ILboolean iGetPalette(ILubyte Info, ILpal *Pal, ILboolean UsePrevPal, ILimage *PrevImage) -{ - ILuint PalSize, PalOffset = 0; - - // If we have a local palette and have to use the previous frame as well, - // we have to copy the palette from the previous frame, in addition - // to the data, which we copy in GetImages. - - // The ld(palettes bpp - 1) is stored in the lower - // 3 bits of Info (weird gif format ... :) ) - PalSize = (1 << ((Info & 0x7) + 1)) * 3; - if (UsePrevPal) { - if (PrevImage == NULL) { // Cannot use the previous palette if it does not exist. - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - PalSize = PalSize + PrevImage->Pal.PalSize; - PalOffset = PrevImage->Pal.PalSize; - } - if (PalSize > 256 * 3) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - Pal->PalSize = PalSize; - - Pal->PalType = IL_PAL_RGB24; - //Pal->Palette = (ILubyte*)ialloc(Pal->PalSize); - Pal->Palette = (ILubyte*)ialloc(256 * 3); - if (Pal->Palette == NULL) - return IL_FALSE; - if (UsePrevPal) - memcpy(Pal->Palette, PrevImage->Pal.Palette, PrevImage->Pal.PalSize); // Copy the old palette over. - if (iread(Pal->Palette + PalOffset, 1, Pal->PalSize) != Pal->PalSize) { // Read the new palette. - ifree(Pal->Palette); - Pal->Palette = NULL; - return IL_FALSE; - } - - return IL_TRUE; -} - - -ILboolean GetImages(ILpal *GlobalPal, GIFHEAD *GifHead) -{ - IMAGEDESC ImageDesc, OldImageDesc; - GFXCONTROL Gfx; - ILboolean BaseImage = IL_TRUE; - ILimage *Image = iCurImage, *TempImage = NULL, *PrevImage = NULL; - ILuint NumImages = 0, i; - ILint input; - ILuint PalOffset; - - OldImageDesc.ImageInfo = 0; // to initialize the data with an harmless value - Gfx.Used = IL_TRUE; - - while (!ieof()) { - ILubyte DisposalMethod = 1; - - i = itell(); - if (!SkipExtensions(&Gfx)) - goto error_clean; - i = itell(); - - if (!Gfx.Used) - DisposalMethod = (Gfx.Packed & 0x1C) >> 2; - - //read image descriptor - ImageDesc.Separator = igetc(); - if (ImageDesc.Separator != 0x2C) //end of image - break; - ImageDesc.OffX = GetLittleUShort(); - ImageDesc.OffY = GetLittleUShort(); - ImageDesc.Width = GetLittleUShort(); - ImageDesc.Height = GetLittleUShort(); - ImageDesc.ImageInfo = igetc(); - - if (ieof()) { - ilGetError(); // Gets rid of the IL_FILE_READ_ERROR that inevitably results. - break; - } - - - if (!BaseImage) { - NumImages++; - Image->Next = ilNewImage(iCurImage->Width, iCurImage->Height, 1, 1, 1); - if (Image->Next == NULL) - goto error_clean; - //20040612: DisposalMethod controls how the new images data is to be combined - //with the old image. 0 means that it doesn't matter how they are combined, - //1 means keep the old image, 2 means set to background color, 3 is - //load the image that was in place before the current (this is not implemented - //here! (TODO?)) - if (DisposalMethod == 2 || DisposalMethod == 3) - //Note that this is actually wrong, too: If the image has a local - //color table, we should really search for the best fit of the - //background color table and use that index (?). Furthermore, - //we should only memset the part of the image that is not read - //later (if we are sure that no parts of the read image are transparent). - if (!Gfx.Used && Gfx.Packed & 0x1) - memset(Image->Next->Data, Gfx.Transparent, Image->SizeOfData); - else - memset(Image->Next->Data, GifHead->Background, Image->SizeOfData); - else if (DisposalMethod == 1 || DisposalMethod == 0) - memcpy(Image->Next->Data, Image->Data, Image->SizeOfData); - //Interlacing has to be removed after the image was copied (line above) - if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. - if (!RemoveInterlace(Image)) - goto error_clean; - } - - PrevImage = Image; - Image = Image->Next; - Image->Format = IL_COLOUR_INDEX; - Image->Origin = IL_ORIGIN_UPPER_LEFT; - } else { - BaseImage = IL_FALSE; - if (!Gfx.Used && Gfx.Packed & 0x1) - memset(Image->Data, Gfx.Transparent, Image->SizeOfData); - else - memset(Image->Data, GifHead->Background, Image->SizeOfData); - } - - Image->OffX = ImageDesc.OffX; - Image->OffY = ImageDesc.OffY; - PalOffset = 0; - - // Check to see if the image has its own palette. - if (ImageDesc.ImageInfo & (1 << 7)) { - ILboolean UsePrevPal = IL_FALSE; - if (DisposalMethod == 1 && NumImages != 0) { // Cannot be the first image for this. - PalOffset = PrevImage->Pal.PalSize; - UsePrevPal = IL_TRUE; - } - if (!iGetPalette(ImageDesc.ImageInfo, &Image->Pal, UsePrevPal, PrevImage)) { - goto error_clean; - } - } else { - if (!iCopyPalette(&Image->Pal, GlobalPal)) { - goto error_clean; - } - } - - if (!GifGetData(Image, Image->Data + ImageDesc.OffX + ImageDesc.OffY*Image->Width, Image->SizeOfData, - ImageDesc.Width, ImageDesc.Height, Image->Width, PalOffset, &Gfx)) { - memset(Image->Data, 0, Image->SizeOfData); //@TODO: Remove this. For debugging purposes right now. - ilSetError(IL_ILLEGAL_FILE_VALUE); - goto error_clean; - } - - // See if there was a valid graphics control extension. - if (!Gfx.Used) { - Gfx.Used = IL_TRUE; - Image->Duration = Gfx.Delay * 10; // We want it in milliseconds. - - // See if a transparent colour is defined. - if (Gfx.Packed & 1) { - if (!ConvertTransparent(Image, Gfx.Transparent)) { - goto error_clean; - } - } - } - i = itell(); - // Terminates each block. - if((input = igetc()) == IL_EOF) - goto error_clean; - - if (input != 0x00) - iseek(-1, IL_SEEK_CUR); - // break; - - OldImageDesc = ImageDesc; - } - - //Deinterlace last image - if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. - if (!RemoveInterlace(Image)) - goto error_clean; - } - - if (BaseImage) // Was not able to load any images in... - return IL_FALSE; - - return IL_TRUE; - -error_clean: - Image = iCurImage->Next; - /* while (Image) { - TempImage = Image; - Image = Image->Next; - ilCloseImage(TempImage); - }*/ - return IL_FALSE; -} - - -ILboolean SkipExtensions(GFXCONTROL *Gfx) -{ - ILint Code; - ILint Label; - ILint Size; - - // DW (06-03-2002): Apparently there can be... - //if (GifType == GIF87A) - // return IL_TRUE; // No extensions in the GIF87a format. - - do { - if((Code = igetc()) == IL_EOF) - return IL_FALSE; - - if (Code != 0x21) { - iseek(-1, IL_SEEK_CUR); - return IL_TRUE; - } - - if((Label = igetc()) == IL_EOF) - return IL_FALSE; - - switch (Label) - { - case 0xF9: - Gfx->Size = igetc(); - Gfx->Packed = igetc(); - Gfx->Delay = GetLittleUShort(); - Gfx->Transparent = igetc(); - Gfx->Terminator = igetc(); - if (ieof()) - return IL_FALSE; - Gfx->Used = IL_FALSE; - break; - /*case 0xFE: - break; - - case 0x01: - break;*/ - default: - do { - if((Size = igetc()) == IL_EOF) - return IL_FALSE; - iseek(Size, IL_SEEK_CUR); - } while (!ieof() && Size != 0); - } - - // @TODO: Handle this better. - if (ieof()) { - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; - } - } while (1); - - return IL_TRUE; -} - - -#define MAX_CODES 4096 - -ILint curr_size, clear, ending, newcodes, top_slot, slot, navail_bytes = 0, nbits_left = 0; -ILubyte b1; -ILubyte byte_buff[257]; -ILubyte *pbytes; -ILubyte *stack; -ILubyte *suffix; -ILshort *prefix; - -ILboolean success; - -ILuint code_mask[13] = -{ - 0L, - 0x0001L, 0x0003L, - 0x0007L, 0x000FL, - 0x001FL, 0x003FL, - 0x007FL, 0x00FFL, - 0x01FFL, 0x03FFL, - 0x07FFL, 0x0FFFL -}; - - -ILint get_next_code(void) { - ILint i, t; - ILuint ret; - - //20050102: Tests for IL_EOF were added because this function - //crashed sometimes if igetc() returned IL_EOF - //(for example "table-add-column-before-active.gif" included in the - //mozilla source package) - - if (!nbits_left) { - if (navail_bytes <= 0) { - pbytes = byte_buff; - navail_bytes = igetc(); - - if(navail_bytes == IL_EOF) { - success = IL_FALSE; - return ending; - } - - if (navail_bytes) { - for (i = 0; i < navail_bytes; i++) { - if((t = igetc()) == IL_EOF) { - success = IL_FALSE; - return ending; - } - byte_buff[i] = t; - } - } - } - b1 = *pbytes++; - nbits_left = 8; - navail_bytes--; - } - - ret = b1 >> (8 - nbits_left); - while (curr_size > nbits_left) { - if (navail_bytes <= 0) { - pbytes = byte_buff; - navail_bytes = igetc(); - - if(navail_bytes == IL_EOF) { - success = IL_FALSE; - return ending; - } - - if (navail_bytes) { - for (i = 0; i < navail_bytes; i++) { - if((t = igetc()) == IL_EOF) { - success = IL_FALSE; - return ending; - } - byte_buff[i] = t; - } - } - } - b1 = *pbytes++; - ret |= b1 << nbits_left; - nbits_left += 8; - navail_bytes--; - } - nbits_left -= curr_size; - - return (ret & code_mask[curr_size]); -} - -static void cleanUpGifLoadState() -{ - ifree(stack); - ifree(suffix); - ifree(prefix); - -} - -ILboolean GifGetData(ILimage *Image, ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, ILuint PalOffset, GFXCONTROL *Gfx) -{ - ILubyte *sp; - ILint code, fc, oc; - ILubyte DisposalMethod = 0; - ILint c, size; - ILuint i = 0, Read = 0, j = 0; - ILubyte *DataPtr = Data; - - if (!Gfx->Used) - DisposalMethod = (Gfx->Packed & 0x1C) >> 2; - if((size = igetc()) == IL_EOF) - return IL_FALSE; - - if (size < 2 || 9 < size) { - return IL_FALSE; - } - - stack = (ILubyte*)ialloc(MAX_CODES + 1); - suffix = (ILubyte*)ialloc(MAX_CODES + 1); - prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1)); - if (!stack || !suffix || !prefix) - { - cleanUpGifLoadState(); - return IL_FALSE; - } - - curr_size = size + 1; - top_slot = 1 << curr_size; - clear = 1 << size; - ending = clear + 1; - slot = newcodes = ending + 1; - navail_bytes = nbits_left = 0; - oc = fc = 0; - sp = stack; - - while ((c = get_next_code()) != ending && Read < Height) { - if (c == clear) - { - curr_size = size + 1; - slot = newcodes; - top_slot = 1 << curr_size; - while ((c = get_next_code()) == clear); - if (c == ending) - break; - if (c >= slot) - c = 0; - oc = fc = c; - - if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0) - i++; - else if (i < Width) - DataPtr[i++] = c + PalOffset; - - if (i == Width) - { - DataPtr += Stride; - i = 0; - Read += 1; - ++j; - if (j >= Height) { - cleanUpGifLoadState(); - return IL_FALSE; - } - } - } - else - { - code = c; - //BG-2007-01-10: several fixes for incomplete GIFs - if (code >= slot) - { - code = oc; - if (sp >= stack + MAX_CODES) { - cleanUpGifLoadState(); - return IL_FALSE; - } - *sp++ = fc; - } - - if (code >= MAX_CODES) - return IL_FALSE; - while (code >= newcodes) - { - if (sp >= stack + MAX_CODES) - { - cleanUpGifLoadState(); - return IL_FALSE; - } - *sp++ = suffix[code]; - code = prefix[code]; - } - - if (sp >= stack + MAX_CODES) { - cleanUpGifLoadState(); - return IL_FALSE; - } - - *sp++ = (ILbyte)code; - if (slot < top_slot) - { - fc = code; - suffix[slot] = fc; - prefix[slot++] = oc; - oc = c; - } - if (slot >= top_slot && curr_size < 12) - { - top_slot <<= 1; - curr_size++; - } - while (sp > stack) - { - sp--; - if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0) - i++; - else if (i < Width) - DataPtr[i++] = *sp + PalOffset; - - if (i == Width) - { - i = 0; - Read += 1; - j = (j+1) % Height; - // Needs to start from Data, not Image->Data. - DataPtr = Data + j * Stride; - } - } - } - } - cleanUpGifLoadState(); - return IL_TRUE; -} - - -/*From the GIF spec: - - The rows of an Interlaced images are arranged in the following order: - - Group 1 : Every 8th. row, starting with row 0. (Pass 1) - Group 2 : Every 8th. row, starting with row 4. (Pass 2) - Group 3 : Every 4th. row, starting with row 2. (Pass 3) - Group 4 : Every 2nd. row, starting with row 1. (Pass 4) -*/ - -ILboolean RemoveInterlace(ILimage *image) -{ - ILubyte *NewData; - ILuint i, j = 0; - - NewData = (ILubyte*)ialloc(image->SizeOfData); - if (NewData == NULL) - return IL_FALSE; - - //changed 20041230: images with offsety != 0 were not - //deinterlaced correctly before... - for (i = 0; i < image->OffY; i++, j++) { - memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); - } - - for (i = 0 + image->OffY; i < image->Height; i += 8, j++) { - memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); - } - - for (i = 4 + image->OffY; i < image->Height; i += 8, j++) { - memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); - } - - for (i = 2 + image->OffY; i < image->Height; i += 4, j++) { - memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); - } - - for (i = 1 + image->OffY; i < image->Height; i += 2, j++) { - memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); - } - - ifree(image->Data); - image->Data = NewData; - - return IL_TRUE; -} - - -// Uses the transparent colour index to make an alpha channel. -ILboolean ConvertTransparent(ILimage *Image, ILubyte TransColour) -{ - ILubyte *Palette; - ILuint i, j; - - if (!Image->Pal.Palette || !Image->Pal.PalSize) { - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - Palette = (ILubyte*)ialloc(Image->Pal.PalSize / 3 * 4); - if (Palette == NULL) - return IL_FALSE; - - for (i = 0, j = 0; i < Image->Pal.PalSize; i += 3, j += 4) { - Palette[j ] = Image->Pal.Palette[i ]; - Palette[j+1] = Image->Pal.Palette[i+1]; - Palette[j+2] = Image->Pal.Palette[i+2]; - if (j/4 == TransColour) - Palette[j+3] = 0x00; - else - Palette[j+3] = 0xFF; - } - - ifree(Image->Pal.Palette); - Image->Pal.Palette = Palette; - Image->Pal.PalSize = Image->Pal.PalSize / 3 * 4; - Image->Pal.PalType = IL_PAL_RGBA32; - - return IL_TRUE; -} - -#endif //IL_NO_GIF diff --git a/DevIL/src-IL/src/il_gif.cpp b/DevIL/src-IL/src/il_gif.cpp new file mode 100644 index 00000000..1ba78885 --- /dev/null +++ b/DevIL/src-IL/src/il_gif.cpp @@ -0,0 +1,755 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_gif.c +// +// Description: Reads from a Graphics Interchange Format (.gif) file. +// +// The LZW decompression code is based on code released to the public domain +// by Javier Arevalo and can be found at +// http://www.programmersheaven.com/zone10/cat452 +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_GIF + +#include "il_gif.h" + + +ILenum GifType; + +//! Checks if the file specified in FileName is a valid Gif file. +ILboolean ilIsValidGif(ILconst_string FileName) +{ + ILHANDLE GifFile; + ILboolean bGif = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("gif"))) { + ilSetError(IL_INVALID_EXTENSION); + return bGif; + } + + GifFile = iopenr(FileName); + if (GifFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bGif; + } + + bGif = ilIsValidGifF(GifFile); + icloser(GifFile); + + return bGif; +} + + +//! Checks if the ILHANDLE contains a valid Gif file at the current position. +ILboolean ilIsValidGifF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidGif(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid Gif lump. +ILboolean ilIsValidGifL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidGif(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidGif() +{ + char Header[6]; + + if (iread(Header, 1, 6) != 6) + return IL_FALSE; + iseek(-6, IL_SEEK_CUR); + + if (!strnicmp(Header, "GIF87A", 6)) + return IL_TRUE; + if (!strnicmp(Header, "GIF89A", 6)) + return IL_TRUE; + + return IL_FALSE; +} + + +//! Reads a Gif file +ILboolean ilLoadGif(ILconst_string FileName) +{ + ILHANDLE GifFile; + ILboolean bGif = IL_FALSE; + + GifFile = iopenr(FileName); + if (GifFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bGif; + } + + bGif = ilLoadGifF(GifFile); + icloser(GifFile); + + return bGif; +} + + +//! Reads an already-opened Gif file +ILboolean ilLoadGifF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadGifInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Gif +ILboolean ilLoadGifL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadGifInternal(); +} + + +// Internal function used to load the Gif. +ILboolean iLoadGifInternal() +{ + GIFHEAD Header; + ILpal GlobalPal; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + GlobalPal.Palette = NULL; + GlobalPal.PalSize = 0; + + //read header + iread(&Header.Sig, 1, 6); + Header.Width = GetLittleUShort(); + Header.Height = GetLittleUShort(); + Header.ColourInfo = igetc(); + Header.Background = igetc(); + Header.Aspect = igetc(); + + if (!strnicmp(Header.Sig, "GIF87A", 6)) { + GifType = GIF87A; + } + else if (!strnicmp(Header.Sig, "GIF89A", 6)) { + GifType = GIF89A; + } + else { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + // Check for a global colour map. + if (Header.ColourInfo & (1 << 7)) { + if (!iGetPalette(Header.ColourInfo, &GlobalPal, IL_FALSE, NULL)) { + return IL_FALSE; + } + } + + if (!GetImages(&GlobalPal, &Header)) + return IL_FALSE; + + if (GlobalPal.Palette && GlobalPal.PalSize) + ifree(GlobalPal.Palette); + GlobalPal.Palette = NULL; + GlobalPal.PalSize = 0; + + return ilFixImage(); +} + + +ILboolean iGetPalette(ILubyte Info, ILpal *Pal, ILboolean UsePrevPal, ILimage *PrevImage) +{ + ILuint PalSize, PalOffset = 0; + + // If we have a local palette and have to use the previous frame as well, + // we have to copy the palette from the previous frame, in addition + // to the data, which we copy in GetImages. + + // The ld(palettes bpp - 1) is stored in the lower + // 3 bits of Info (weird gif format ... :) ) + PalSize = (1 << ((Info & 0x7) + 1)) * 3; + if (UsePrevPal) { + if (PrevImage == NULL) { // Cannot use the previous palette if it does not exist. + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + PalSize = PalSize + PrevImage->Pal.PalSize; + PalOffset = PrevImage->Pal.PalSize; + } + if (PalSize > 256 * 3) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + Pal->PalSize = PalSize; + + Pal->PalType = IL_PAL_RGB24; + //Pal->Palette = (ILubyte*)ialloc(Pal->PalSize); + Pal->Palette = (ILubyte*)ialloc(256 * 3); + if (Pal->Palette == NULL) + return IL_FALSE; + if (UsePrevPal) + memcpy(Pal->Palette, PrevImage->Pal.Palette, PrevImage->Pal.PalSize); // Copy the old palette over. + if (iread(Pal->Palette + PalOffset, 1, Pal->PalSize) != Pal->PalSize) { // Read the new palette. + ifree(Pal->Palette); + Pal->Palette = NULL; + return IL_FALSE; + } + + return IL_TRUE; +} + + +ILboolean GetImages(ILpal *GlobalPal, GIFHEAD *GifHead) +{ + IMAGEDESC ImageDesc, OldImageDesc; + GFXCONTROL Gfx; + ILboolean BaseImage = IL_TRUE; + ILimage *Image = iCurImage, *TempImage = NULL, *PrevImage = NULL; + ILuint NumImages = 0, i; + ILint input; + ILuint PalOffset; + + OldImageDesc.ImageInfo = 0; // to initialize the data with an harmless value + Gfx.Used = IL_TRUE; + + while (!ieof()) { + ILubyte DisposalMethod = 1; + + i = itell(); + if (!SkipExtensions(&Gfx)) + goto error_clean; + i = itell(); + + if (!Gfx.Used) + DisposalMethod = (Gfx.Packed & 0x1C) >> 2; + + //read image descriptor + ImageDesc.Separator = igetc(); + if (ImageDesc.Separator != 0x2C) //end of image + break; + ImageDesc.OffX = GetLittleUShort(); + ImageDesc.OffY = GetLittleUShort(); + ImageDesc.Width = GetLittleUShort(); + ImageDesc.Height = GetLittleUShort(); + ImageDesc.ImageInfo = igetc(); + + if (ieof()) { + ilGetError(); // Gets rid of the IL_FILE_READ_ERROR that inevitably results. + break; + } + + + if (!BaseImage) { + NumImages++; + Image->Next = ilNewImage(iCurImage->Width, iCurImage->Height, 1, 1, 1); + if (Image->Next == NULL) + goto error_clean; + //20040612: DisposalMethod controls how the new images data is to be combined + //with the old image. 0 means that it doesn't matter how they are combined, + //1 means keep the old image, 2 means set to background color, 3 is + //load the image that was in place before the current (this is not implemented + //here! (TODO?)) + if (DisposalMethod == 2 || DisposalMethod == 3) + //Note that this is actually wrong, too: If the image has a local + //color table, we should really search for the best fit of the + //background color table and use that index (?). Furthermore, + //we should only memset the part of the image that is not read + //later (if we are sure that no parts of the read image are transparent). + if (!Gfx.Used && Gfx.Packed & 0x1) + memset(Image->Next->Data, Gfx.Transparent, Image->SizeOfData); + else + memset(Image->Next->Data, GifHead->Background, Image->SizeOfData); + else if (DisposalMethod == 1 || DisposalMethod == 0) + memcpy(Image->Next->Data, Image->Data, Image->SizeOfData); + //Interlacing has to be removed after the image was copied (line above) + if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. + if (!RemoveInterlace(Image)) + goto error_clean; + } + + PrevImage = Image; + Image = Image->Next; + Image->Format = IL_COLOUR_INDEX; + Image->Origin = IL_ORIGIN_UPPER_LEFT; + } else { + BaseImage = IL_FALSE; + if (!Gfx.Used && Gfx.Packed & 0x1) + memset(Image->Data, Gfx.Transparent, Image->SizeOfData); + else + memset(Image->Data, GifHead->Background, Image->SizeOfData); + } + + Image->OffX = ImageDesc.OffX; + Image->OffY = ImageDesc.OffY; + PalOffset = 0; + + // Check to see if the image has its own palette. + if (ImageDesc.ImageInfo & (1 << 7)) { + ILboolean UsePrevPal = IL_FALSE; + if (DisposalMethod == 1 && NumImages != 0) { // Cannot be the first image for this. + PalOffset = PrevImage->Pal.PalSize; + UsePrevPal = IL_TRUE; + } + if (!iGetPalette(ImageDesc.ImageInfo, &Image->Pal, UsePrevPal, PrevImage)) { + goto error_clean; + } + } else { + if (!iCopyPalette(&Image->Pal, GlobalPal)) { + goto error_clean; + } + } + + if (!GifGetData(Image, Image->Data + ImageDesc.OffX + ImageDesc.OffY*Image->Width, Image->SizeOfData, + ImageDesc.Width, ImageDesc.Height, Image->Width, PalOffset, &Gfx)) { + memset(Image->Data, 0, Image->SizeOfData); //@TODO: Remove this. For debugging purposes right now. + ilSetError(IL_ILLEGAL_FILE_VALUE); + goto error_clean; + } + + // See if there was a valid graphics control extension. + if (!Gfx.Used) { + Gfx.Used = IL_TRUE; + Image->Duration = Gfx.Delay * 10; // We want it in milliseconds. + + // See if a transparent colour is defined. + if (Gfx.Packed & 1) { + if (!ConvertTransparent(Image, Gfx.Transparent)) { + goto error_clean; + } + } + } + i = itell(); + // Terminates each block. + if((input = igetc()) == IL_EOF) + goto error_clean; + + if (input != 0x00) + iseek(-1, IL_SEEK_CUR); + // break; + + OldImageDesc = ImageDesc; + } + + //Deinterlace last image + if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. + if (!RemoveInterlace(Image)) + goto error_clean; + } + + if (BaseImage) // Was not able to load any images in... + return IL_FALSE; + + return IL_TRUE; + +error_clean: + Image = iCurImage->Next; + /* while (Image) { + TempImage = Image; + Image = Image->Next; + ilCloseImage(TempImage); + }*/ + return IL_FALSE; +} + + +ILboolean SkipExtensions(GFXCONTROL *Gfx) +{ + ILint Code; + ILint Label; + ILint Size; + + // DW (06-03-2002): Apparently there can be... + //if (GifType == GIF87A) + // return IL_TRUE; // No extensions in the GIF87a format. + + do { + if((Code = igetc()) == IL_EOF) + return IL_FALSE; + + if (Code != 0x21) { + iseek(-1, IL_SEEK_CUR); + return IL_TRUE; + } + + if((Label = igetc()) == IL_EOF) + return IL_FALSE; + + switch (Label) + { + case 0xF9: + Gfx->Size = igetc(); + Gfx->Packed = igetc(); + Gfx->Delay = GetLittleUShort(); + Gfx->Transparent = igetc(); + Gfx->Terminator = igetc(); + if (ieof()) + return IL_FALSE; + Gfx->Used = IL_FALSE; + break; + /*case 0xFE: + break; + + case 0x01: + break;*/ + default: + do { + if((Size = igetc()) == IL_EOF) + return IL_FALSE; + iseek(Size, IL_SEEK_CUR); + } while (!ieof() && Size != 0); + } + + // @TODO: Handle this better. + if (ieof()) { + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; + } + } while (1); + + return IL_TRUE; +} + + +#define MAX_CODES 4096 + +ILint curr_size, clear, ending, newcodes, top_slot, slot, navail_bytes = 0, nbits_left = 0; +ILubyte b1; +ILubyte byte_buff[257]; +ILubyte *pbytes; +ILubyte *stack; +ILubyte *suffix; +ILshort *prefix; + +ILboolean success; + +ILuint code_mask[13] = +{ + 0L, + 0x0001L, 0x0003L, + 0x0007L, 0x000FL, + 0x001FL, 0x003FL, + 0x007FL, 0x00FFL, + 0x01FFL, 0x03FFL, + 0x07FFL, 0x0FFFL +}; + + +ILint get_next_code(void) { + ILint i, t; + ILuint ret; + + //20050102: Tests for IL_EOF were added because this function + //crashed sometimes if igetc() returned IL_EOF + //(for example "table-add-column-before-active.gif" included in the + //mozilla source package) + + if (!nbits_left) { + if (navail_bytes <= 0) { + pbytes = byte_buff; + navail_bytes = igetc(); + + if(navail_bytes == IL_EOF) { + success = IL_FALSE; + return ending; + } + + if (navail_bytes) { + for (i = 0; i < navail_bytes; i++) { + if((t = igetc()) == IL_EOF) { + success = IL_FALSE; + return ending; + } + byte_buff[i] = t; + } + } + } + b1 = *pbytes++; + nbits_left = 8; + navail_bytes--; + } + + ret = b1 >> (8 - nbits_left); + while (curr_size > nbits_left) { + if (navail_bytes <= 0) { + pbytes = byte_buff; + navail_bytes = igetc(); + + if(navail_bytes == IL_EOF) { + success = IL_FALSE; + return ending; + } + + if (navail_bytes) { + for (i = 0; i < navail_bytes; i++) { + if((t = igetc()) == IL_EOF) { + success = IL_FALSE; + return ending; + } + byte_buff[i] = t; + } + } + } + b1 = *pbytes++; + ret |= b1 << nbits_left; + nbits_left += 8; + navail_bytes--; + } + nbits_left -= curr_size; + + return (ret & code_mask[curr_size]); +} + +static void cleanUpGifLoadState() +{ + ifree(stack); + ifree(suffix); + ifree(prefix); + +} + +ILboolean GifGetData(ILimage *Image, ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, ILuint PalOffset, GFXCONTROL *Gfx) +{ + ILubyte *sp; + ILint code, fc, oc; + ILubyte DisposalMethod = 0; + ILint c, size; + ILuint i = 0, Read = 0, j = 0; + ILubyte *DataPtr = Data; + + if (!Gfx->Used) + DisposalMethod = (Gfx->Packed & 0x1C) >> 2; + if((size = igetc()) == IL_EOF) + return IL_FALSE; + + if (size < 2 || 9 < size) { + return IL_FALSE; + } + + stack = (ILubyte*)ialloc(MAX_CODES + 1); + suffix = (ILubyte*)ialloc(MAX_CODES + 1); + prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1)); + if (!stack || !suffix || !prefix) + { + cleanUpGifLoadState(); + return IL_FALSE; + } + + curr_size = size + 1; + top_slot = 1 << curr_size; + clear = 1 << size; + ending = clear + 1; + slot = newcodes = ending + 1; + navail_bytes = nbits_left = 0; + oc = fc = 0; + sp = stack; + + while ((c = get_next_code()) != ending && Read < Height) { + if (c == clear) + { + curr_size = size + 1; + slot = newcodes; + top_slot = 1 << curr_size; + while ((c = get_next_code()) == clear); + if (c == ending) + break; + if (c >= slot) + c = 0; + oc = fc = c; + + if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0) + i++; + else if (i < Width) + DataPtr[i++] = c + PalOffset; + + if (i == Width) + { + DataPtr += Stride; + i = 0; + Read += 1; + ++j; + if (j >= Height) { + cleanUpGifLoadState(); + return IL_FALSE; + } + } + } + else + { + code = c; + //BG-2007-01-10: several fixes for incomplete GIFs + if (code >= slot) + { + code = oc; + if (sp >= stack + MAX_CODES) { + cleanUpGifLoadState(); + return IL_FALSE; + } + *sp++ = fc; + } + + if (code >= MAX_CODES) + return IL_FALSE; + while (code >= newcodes) + { + if (sp >= stack + MAX_CODES) + { + cleanUpGifLoadState(); + return IL_FALSE; + } + *sp++ = suffix[code]; + code = prefix[code]; + } + + if (sp >= stack + MAX_CODES) { + cleanUpGifLoadState(); + return IL_FALSE; + } + + *sp++ = (ILbyte)code; + if (slot < top_slot) + { + fc = code; + suffix[slot] = fc; + prefix[slot++] = oc; + oc = c; + } + if (slot >= top_slot && curr_size < 12) + { + top_slot <<= 1; + curr_size++; + } + while (sp > stack) + { + sp--; + if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0) + i++; + else if (i < Width) + DataPtr[i++] = *sp + PalOffset; + + if (i == Width) + { + i = 0; + Read += 1; + j = (j+1) % Height; + // Needs to start from Data, not Image->Data. + DataPtr = Data + j * Stride; + } + } + } + } + cleanUpGifLoadState(); + return IL_TRUE; +} + + +/*From the GIF spec: + + The rows of an Interlaced images are arranged in the following order: + + Group 1 : Every 8th. row, starting with row 0. (Pass 1) + Group 2 : Every 8th. row, starting with row 4. (Pass 2) + Group 3 : Every 4th. row, starting with row 2. (Pass 3) + Group 4 : Every 2nd. row, starting with row 1. (Pass 4) +*/ + +ILboolean RemoveInterlace(ILimage *image) +{ + ILubyte *NewData; + ILuint i, j = 0; + + NewData = (ILubyte*)ialloc(image->SizeOfData); + if (NewData == NULL) + return IL_FALSE; + + //changed 20041230: images with offsety != 0 were not + //deinterlaced correctly before... + for (i = 0; i < image->OffY; i++, j++) { + memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); + } + + for (i = 0 + image->OffY; i < image->Height; i += 8, j++) { + memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); + } + + for (i = 4 + image->OffY; i < image->Height; i += 8, j++) { + memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); + } + + for (i = 2 + image->OffY; i < image->Height; i += 4, j++) { + memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); + } + + for (i = 1 + image->OffY; i < image->Height; i += 2, j++) { + memcpy(&NewData[i * image->Bps], &image->Data[j * image->Bps], image->Bps); + } + + ifree(image->Data); + image->Data = NewData; + + return IL_TRUE; +} + + +// Uses the transparent colour index to make an alpha channel. +ILboolean ConvertTransparent(ILimage *Image, ILubyte TransColour) +{ + ILubyte *Palette; + ILuint i, j; + + if (!Image->Pal.Palette || !Image->Pal.PalSize) { + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + Palette = (ILubyte*)ialloc(Image->Pal.PalSize / 3 * 4); + if (Palette == NULL) + return IL_FALSE; + + for (i = 0, j = 0; i < Image->Pal.PalSize; i += 3, j += 4) { + Palette[j ] = Image->Pal.Palette[i ]; + Palette[j+1] = Image->Pal.Palette[i+1]; + Palette[j+2] = Image->Pal.Palette[i+2]; + if (j/4 == TransColour) + Palette[j+3] = 0x00; + else + Palette[j+3] = 0xFF; + } + + ifree(Image->Pal.Palette); + Image->Pal.Palette = Palette; + Image->Pal.PalSize = Image->Pal.PalSize / 3 * 4; + Image->Pal.PalType = IL_PAL_RGBA32; + + return IL_TRUE; +} + +#endif //IL_NO_GIF diff --git a/DevIL/src-IL/src/il_hdr.c b/DevIL/src-IL/src/il_hdr.c deleted file mode 100644 index 55b9bd16..00000000 --- a/DevIL/src-IL/src/il_hdr.c +++ /dev/null @@ -1,659 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods (this file by thakis / Denton) -// Last modified: 02/09/2009 -// -// Filename: src-IL/src/il_hdr.c -// -// Description: Reads/writes a RADIANCE High Dynamic Range Image -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_HDR -#include "il_hdr.h" -#include "il_endian.h" - - -//! Checks if the file specified in FileName is a valid .hdr file. -ILboolean ilIsValidHdr(ILconst_string FileName) -{ - ILHANDLE HdrFile; - ILboolean bHdr = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("hdr"))) { - ilSetError(IL_INVALID_EXTENSION); - return bHdr; - } - - HdrFile = iopenr(FileName); - if (HdrFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bHdr; - } - - bHdr = ilIsValidHdrF(HdrFile); - icloser(HdrFile); - - return bHdr; -} - - -//! Checks if the ILHANDLE contains a valid .hdr file at the current position. -ILboolean ilIsValidHdrF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidHdr(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .hdr lump. -ILboolean ilIsValidHdrL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidHdr(); -} - - -// Internal function used to get the .hdr header from the current file. -ILboolean iGetHdrHead(HDRHEADER *Header) -{ - ILboolean done = IL_FALSE; - char a, b; - char x[3], y[3]; //changed 20050217: added space for the '\0' char - char buff[81]; // 01-19-2009: Added space for the '\0'. - ILuint count = 0; - - iread(Header->Signature, 1, 10); - - //skip lines until an empty line is found. - //this marks the end of header information, - //the next line contains the image's dimension. - - //TODO: read header contents into variables - //(EXPOSURE, orientation, xyz correction, ...) - - if (iread(&a, 1, 1) != 1) - return IL_FALSE; - - while (!done) { - if (iread(&b, 1, 1) != 1) - return IL_FALSE; - if (b == '\n' && a == '\n') - done = IL_TRUE; - else - a = b; - } - - //read dimensions (note that this assumes a somewhat valid image) - if (iread(&a, 1, 1) != 1) - return IL_FALSE; - while (a != '\n') { - if (count >= 80) { // Line shouldn't be this long at all. - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - buff[count] = a; - if (iread(&a, 1, 1) != 1) - return IL_FALSE; - ++count; - } - buff[count] = '\0'; - - //note that this is not the 100% correct way to load hdr images: - //in a perfect world we would check if there's a +/- X/Y in front - //of width and heigth and mirror + rotate the image after decoding - //according to that. But HDRShop doesn't do that either (and that's - //my reference program :) ) and it's just a rotate and a mirror, - //nothing that really changes the appearance of the loaded image... - //(The code as it is now assumes that y contains "-Y" and x contains - //"+X" after the following line) - - // The 2 has to be in the %s format specifier to prevent buffer overruns. - sscanf(buff, "%2s %d %2s %d", y, &Header->Height, x, &Header->Width); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidHdr() -{ - char Head[10]; - ILint Read; - - Read = iread(Head, 1, 10); - iseek(-Read, IL_SEEK_CUR); // Go ahead and restore to previous state - if (Read != 10) - return IL_FALSE; - - return - strnicmp(Head, "#?RADIANCE", 10) == 0 - || strnicmp(Head, "#?RGBE", 6) == 0; -} - - -// Internal function used to check if the HEADER is a valid .hdr header. -ILboolean iCheckHdr(HDRHEADER *Header) -{ - return - strnicmp(Header->Signature, "#?RADIANCE", 10) == 0 - || strnicmp(Header->Signature, "#?RGBE", 6) == 0; -} - - -//! Reads a .hdr file -ILboolean ilLoadHdr(ILconst_string FileName) -{ - ILHANDLE HdrFile; - ILboolean bHdr = IL_FALSE; - - HdrFile = iopenr(FileName); - if (HdrFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bHdr; - } - - bHdr = ilLoadHdrF(HdrFile); - icloser(HdrFile); - - return bHdr; -} - - -//! Reads an already-opened .hdr file -ILboolean ilLoadHdrF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadHdrInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .hdr -ILboolean ilLoadHdrL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadHdrInternal(); -} - - -// Internal function used to load the .hdr. -ILboolean iLoadHdrInternal() -{ - HDRHEADER Header; - ILfloat *data; - ILubyte *scanline; - ILuint i, j, e, r, g, b; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetHdrHead(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - if (!iCheckHdr(&Header)) { - //iseek(-(ILint)sizeof(HDRHEAD), IL_SEEK_CUR); - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Update the current image with the new dimensions - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_FLOAT, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - //read image data - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->Width / 8 * iCurImage->Height); - - data = (ILfloat*)iCurImage->Data; - scanline = (ILubyte*)ialloc(Header.Width*4); - for (i = 0; i < Header.Height; ++i) { - ReadScanline(scanline, Header.Width); - - //convert hdrs internal format to floats - for (j = 0; j < 4*Header.Width; j += 4) { - ILuint *ee; - ILfloat t, *ff; - e = scanline[j + 3]; - r = scanline[j + 0]; - g = scanline[j + 1]; - b = scanline[j + 2]; - - //t = (float)pow(2.f, ((ILint)e) - 128); - if (e != 0) - e = (e - 1) << 23; - - // All this just to avoid stric-aliasing warnings... - // was: t = *(ILfloat*)&e - ee = &e; - ff = (ILfloat*)ee; - t = *ff; - - data[0] = (r/255.0f)*t; - data[1] = (g/255.0f)*t; - data[2] = (b/255.0f)*t; - data += 3; - } - } - iUnCache(); - ifree(scanline); - - return ilFixImage(); -} - -void ReadScanline(ILubyte *scanline, ILuint w) { - ILubyte *runner; - ILuint r, g, b, e, read, shift; - - r = igetc(); - g = igetc(); - b = igetc(); - e = igetc(); - - //check if the scanline is in the new format - //if so, e, r, g, g are stored separated and are - //rle-compressed independently. - if (r == 2 && g == 2) { - ILuint length = (b << 8) | e; - ILuint j, t, k; - if (length > w) - length = w; //fix broken files - for (k = 0; k < 4; ++k) { - runner = scanline + k; - j = 0; - while (j < length) { - t = igetc(); - if (t > 128) { //Run? - ILubyte val = igetc(); - t &= 127; - //copy current byte - while (t > 0 && j < length) { - *runner = val; - runner += 4; - --t; - ++j; - } - } - else { //No Run. - //read new bytes - while (t > 0 && j < length) { - *runner = igetc(); - runner += 4; - --t; - ++j; - } - } - } - } - return; //done decoding a scanline in separated format - } - - //if we come here, we are dealing with old-style scanlines - shift = 0; - read = 0; - runner = scanline; - while (read < w) { - if (read != 0) { - r = igetc(); - g = igetc(); - b = igetc(); - e = igetc(); - } - - //if all three mantissas are 1, then this is a rle - //count dword - if (r == 1 && g == 1 && b == 1) { - ILuint length = e; - ILuint j; - for (j = length << shift; j > 0 && read < w; --j) { - memcpy(runner, runner - 4, 4); - runner += 4; - ++read; - } - //if more than one rle count dword is read - //consecutively, they are higher order bytes - //of the first read value. shift keeps track of - //that. - shift += 8; - } - else { - runner[0] = r; - runner[1] = g; - runner[2] = b; - runner[3] = e; - - shift = 0; - runner += 4; - ++read; - } - } -} - - - -//! Writes a Hdr file -ILboolean ilSaveHdr(const ILstring FileName) -{ - ILHANDLE HdrFile; - ILuint HdrSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - HdrFile = iopenw(FileName); - if (HdrFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - HdrSize = ilSaveHdrF(HdrFile); - iclosew(HdrFile); - - if (HdrSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Hdr to an already-opened file -ILuint ilSaveHdrF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveHdrInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Hdr to a memory "lump" -ILuint ilSaveHdrL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveHdrInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// -// Much of the saving code is based on the code by Bruce Walter, -// available at http://www.graphics.cornell.edu/online/formats/rgbe/. -// -// The actual source code file is -// http://www.graphics.cornell.edu/online/formats/rgbe/rgbe.c -// - - -/* standard conversion from float pixels to rgbe pixels */ -/* note: you can remove the "inline"s if your compiler complains about it */ -//static INLINE void -static void -float2rgbe(unsigned char rgbe[4], float red, float green, float blue) -{ - float v; - int e; - - v = red; - if (green > v) v = green; - if (blue > v) v = blue; - if (v < 1e-32) { - rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; - } - else { - v = (float)(frexp(v,&e) * 256.0/v); - rgbe[0] = (unsigned char) (red * v); - rgbe[1] = (unsigned char) (green * v); - rgbe[2] = (unsigned char) (blue * v); - rgbe[3] = (unsigned char) (e + 128); - } -} - - -typedef struct { - ILuint valid; /* indicate which fields are valid */ - ILbyte programtype[16]; /* listed at beginning of file to identify it - * after "#?". defaults to "RGBE" */ - ILfloat gamma; /* image has already been gamma corrected with - * given gamma. defaults to 1.0 (no correction) */ - ILfloat exposure; /* a value of 1.0 in an image corresponds to - * watts/steradian/m^2. - * defaults to 1.0 */ -} rgbe_header_info; - -/* flags indicating which fields in an rgbe_header_info are valid */ -#define RGBE_VALID_PROGRAMTYPE 0x01 -#define RGBE_VALID_GAMMA 0x02 -#define RGBE_VALID_EXPOSURE 0x04 - -/* offsets to red, green, and blue components in a data (float) pixel */ -#define RGBE_DATA_RED 0 -#define RGBE_DATA_GREEN 1 -#define RGBE_DATA_BLUE 2 -/* number of floats per pixel */ -#define RGBE_DATA_SIZE 3 - - -/* default minimal header. modify if you want more information in header */ -ILboolean RGBE_WriteHeader(ILuint width, ILuint height, rgbe_header_info *info) -{ - char *programtype = "RGBE"; - - if (info && (info->valid & RGBE_VALID_PROGRAMTYPE)) - programtype = info->programtype; - if (ilprintf("#?%s\n",programtype) < 0) - return IL_FALSE; - /* The #? is to identify file type, the programtype is optional. */ - if (info && (info->valid & RGBE_VALID_GAMMA)) { - if (ilprintf("GAMMA=%g\n",info->gamma) < 0) - return IL_FALSE; - } - if (info && (info->valid & RGBE_VALID_EXPOSURE)) { - if (ilprintf("EXPOSURE=%g\n",info->exposure) < 0) - return IL_FALSE; - } - if (ilprintf("FORMAT=32-bit_rle_rgbe\n\n") < 0) - return IL_FALSE; - if (ilprintf("-Y %d +X %d\n", height, width) < 0) - return IL_FALSE; - return IL_TRUE; -} - - -/* simple write routine that does not use run length encoding */ -/* These routines can be made faster by allocating a larger buffer and - fread-ing and iwrite-ing the data in larger chunks */ -int RGBE_WritePixels(float *data, int numpixels) -{ - unsigned char rgbe[4]; - - while (numpixels-- > 0) { - float2rgbe(rgbe,data[RGBE_DATA_RED],data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]); - data += RGBE_DATA_SIZE; - if (iwrite(rgbe, sizeof(rgbe), 1) < 1) - return IL_FALSE; - } - return IL_TRUE; -} - - -/* The code below is only needed for the run-length encoded files. */ -/* Run length encoding adds considerable complexity but does */ -/* save some space. For each scanline, each channel (r,g,b,e) is */ -/* encoded separately for better compression. */ - -ILboolean RGBE_WriteBytes_RLE(ILubyte *data, ILuint numbytes) -{ -#define MINRUNLENGTH 4 - ILuint cur, beg_run, run_count, old_run_count, nonrun_count; - ILubyte buf[2]; - - cur = 0; - while (cur < numbytes) { - beg_run = cur; - /* find next run of length at least 4 if one exists */ - run_count = old_run_count = 0; - while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) { - beg_run += run_count; - old_run_count = run_count; - run_count = 1; - // 01-25-2009: Moved test for beg_run + run_count first so that it is - // tested first. This keeps it from going out of bounds by 1. - while((beg_run + run_count < numbytes) && (run_count < 127) && - (data[beg_run] == data[beg_run + run_count])) - run_count++; - } - /* if data before next big run is a short run then write it as such */ - if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) { - buf[0] = 128 + old_run_count; /*write short run*/ - buf[1] = data[cur]; - if (iwrite(buf,sizeof(buf[0])*2,1) < 1) - return IL_FALSE; - cur = beg_run; - } - /* write out bytes until we reach the start of the next run */ - while(cur < beg_run) { - nonrun_count = beg_run - cur; - if (nonrun_count > 128) - nonrun_count = 128; - buf[0] = nonrun_count; - if (iwrite(buf,sizeof(buf[0]),1) < 1) - return IL_FALSE; - if (iwrite(&data[cur],sizeof(data[0])*nonrun_count,1) < 1) - return IL_FALSE; - cur += nonrun_count; - } - /* write out next run if one was found */ - if (run_count >= MINRUNLENGTH) { - buf[0] = 128 + run_count; - buf[1] = data[beg_run]; - if (iwrite(buf,sizeof(buf[0])*2,1) < 1) - return IL_FALSE; - cur += run_count; - } - } - return IL_TRUE; -#undef MINRUNLENGTH -} - - -// Internal function used to save the Hdr. -ILboolean iSaveHdrInternal() -{ - ILimage *TempImage; - rgbe_header_info stHeader; - unsigned char rgbe[4]; - ILubyte *buffer; - ILfloat *data; - ILuint i; - ILboolean bRet; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - stHeader.exposure = 0; - stHeader.gamma = 0; - stHeader.programtype[0] = 0; - stHeader.valid = 0; - - if (iCurImage->Format != IL_UNSIGNED_BYTE) { - TempImage = iConvertImage(iCurImage, IL_RGB, IL_FLOAT); - if (TempImage == NULL) - return IL_FALSE; - } - else - TempImage = iCurImage; - - if (!RGBE_WriteHeader(TempImage->Width, TempImage->Height, &stHeader)) - return IL_FALSE; - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) - iFlipBuffer(TempImage->Data, TempImage->Depth, TempImage->Bps, TempImage->Height); - data = (ILfloat*)TempImage->Data; - - if ((TempImage->Width < 8)||(TempImage->Width > 0x7fff)) { - /* run length encoding is not allowed so write flat*/ - bRet = RGBE_WritePixels(data,TempImage->Width*TempImage->Height); - if (iCurImage != TempImage) - ilCloseImage(TempImage); - return bRet; - } - buffer = (ILubyte*)ialloc(sizeof(ILubyte)*4*TempImage->Width); - if (buffer == NULL) { - /* no buffer space so write flat */ - bRet = RGBE_WritePixels(data,TempImage->Width*TempImage->Height); - if (iCurImage != TempImage) - ilCloseImage(TempImage); - return bRet; - } - - while(TempImage->Height-- > 0) { - rgbe[0] = 2; - rgbe[1] = 2; - rgbe[2] = TempImage->Width >> 8; - rgbe[3] = TempImage->Width & 0xFF; - if (iwrite(rgbe, sizeof(rgbe), 1) < 1) { - free(buffer); - if (iCurImage != TempImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - - for(i=0;iWidth;i++) { - float2rgbe(rgbe,data[RGBE_DATA_RED],data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]); - buffer[i] = rgbe[0]; - buffer[i+TempImage->Width] = rgbe[1]; - buffer[i+2*TempImage->Width] = rgbe[2]; - buffer[i+3*TempImage->Width] = rgbe[3]; - data += RGBE_DATA_SIZE; - } - /* write out each of the four channels separately run length encoded */ - /* first red, then green, then blue, then exponent */ - for(i=0;i<4;i++) { - if (RGBE_WriteBytes_RLE(&buffer[i*TempImage->Width],TempImage->Width) != IL_TRUE) { - ifree(buffer); - if (iCurImage != TempImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - } - } - ifree(buffer); - - if (iCurImage != TempImage) - ilCloseImage(TempImage); - return IL_TRUE; -} - - -#endif//IL_NO_HDR diff --git a/DevIL/src-IL/src/il_hdr.cpp b/DevIL/src-IL/src/il_hdr.cpp new file mode 100644 index 00000000..55b9bd16 --- /dev/null +++ b/DevIL/src-IL/src/il_hdr.cpp @@ -0,0 +1,659 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods (this file by thakis / Denton) +// Last modified: 02/09/2009 +// +// Filename: src-IL/src/il_hdr.c +// +// Description: Reads/writes a RADIANCE High Dynamic Range Image +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_HDR +#include "il_hdr.h" +#include "il_endian.h" + + +//! Checks if the file specified in FileName is a valid .hdr file. +ILboolean ilIsValidHdr(ILconst_string FileName) +{ + ILHANDLE HdrFile; + ILboolean bHdr = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("hdr"))) { + ilSetError(IL_INVALID_EXTENSION); + return bHdr; + } + + HdrFile = iopenr(FileName); + if (HdrFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bHdr; + } + + bHdr = ilIsValidHdrF(HdrFile); + icloser(HdrFile); + + return bHdr; +} + + +//! Checks if the ILHANDLE contains a valid .hdr file at the current position. +ILboolean ilIsValidHdrF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidHdr(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .hdr lump. +ILboolean ilIsValidHdrL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidHdr(); +} + + +// Internal function used to get the .hdr header from the current file. +ILboolean iGetHdrHead(HDRHEADER *Header) +{ + ILboolean done = IL_FALSE; + char a, b; + char x[3], y[3]; //changed 20050217: added space for the '\0' char + char buff[81]; // 01-19-2009: Added space for the '\0'. + ILuint count = 0; + + iread(Header->Signature, 1, 10); + + //skip lines until an empty line is found. + //this marks the end of header information, + //the next line contains the image's dimension. + + //TODO: read header contents into variables + //(EXPOSURE, orientation, xyz correction, ...) + + if (iread(&a, 1, 1) != 1) + return IL_FALSE; + + while (!done) { + if (iread(&b, 1, 1) != 1) + return IL_FALSE; + if (b == '\n' && a == '\n') + done = IL_TRUE; + else + a = b; + } + + //read dimensions (note that this assumes a somewhat valid image) + if (iread(&a, 1, 1) != 1) + return IL_FALSE; + while (a != '\n') { + if (count >= 80) { // Line shouldn't be this long at all. + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + buff[count] = a; + if (iread(&a, 1, 1) != 1) + return IL_FALSE; + ++count; + } + buff[count] = '\0'; + + //note that this is not the 100% correct way to load hdr images: + //in a perfect world we would check if there's a +/- X/Y in front + //of width and heigth and mirror + rotate the image after decoding + //according to that. But HDRShop doesn't do that either (and that's + //my reference program :) ) and it's just a rotate and a mirror, + //nothing that really changes the appearance of the loaded image... + //(The code as it is now assumes that y contains "-Y" and x contains + //"+X" after the following line) + + // The 2 has to be in the %s format specifier to prevent buffer overruns. + sscanf(buff, "%2s %d %2s %d", y, &Header->Height, x, &Header->Width); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidHdr() +{ + char Head[10]; + ILint Read; + + Read = iread(Head, 1, 10); + iseek(-Read, IL_SEEK_CUR); // Go ahead and restore to previous state + if (Read != 10) + return IL_FALSE; + + return + strnicmp(Head, "#?RADIANCE", 10) == 0 + || strnicmp(Head, "#?RGBE", 6) == 0; +} + + +// Internal function used to check if the HEADER is a valid .hdr header. +ILboolean iCheckHdr(HDRHEADER *Header) +{ + return + strnicmp(Header->Signature, "#?RADIANCE", 10) == 0 + || strnicmp(Header->Signature, "#?RGBE", 6) == 0; +} + + +//! Reads a .hdr file +ILboolean ilLoadHdr(ILconst_string FileName) +{ + ILHANDLE HdrFile; + ILboolean bHdr = IL_FALSE; + + HdrFile = iopenr(FileName); + if (HdrFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bHdr; + } + + bHdr = ilLoadHdrF(HdrFile); + icloser(HdrFile); + + return bHdr; +} + + +//! Reads an already-opened .hdr file +ILboolean ilLoadHdrF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadHdrInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .hdr +ILboolean ilLoadHdrL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadHdrInternal(); +} + + +// Internal function used to load the .hdr. +ILboolean iLoadHdrInternal() +{ + HDRHEADER Header; + ILfloat *data; + ILubyte *scanline; + ILuint i, j, e, r, g, b; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetHdrHead(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (!iCheckHdr(&Header)) { + //iseek(-(ILint)sizeof(HDRHEAD), IL_SEEK_CUR); + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Update the current image with the new dimensions + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_FLOAT, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + //read image data + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->Width / 8 * iCurImage->Height); + + data = (ILfloat*)iCurImage->Data; + scanline = (ILubyte*)ialloc(Header.Width*4); + for (i = 0; i < Header.Height; ++i) { + ReadScanline(scanline, Header.Width); + + //convert hdrs internal format to floats + for (j = 0; j < 4*Header.Width; j += 4) { + ILuint *ee; + ILfloat t, *ff; + e = scanline[j + 3]; + r = scanline[j + 0]; + g = scanline[j + 1]; + b = scanline[j + 2]; + + //t = (float)pow(2.f, ((ILint)e) - 128); + if (e != 0) + e = (e - 1) << 23; + + // All this just to avoid stric-aliasing warnings... + // was: t = *(ILfloat*)&e + ee = &e; + ff = (ILfloat*)ee; + t = *ff; + + data[0] = (r/255.0f)*t; + data[1] = (g/255.0f)*t; + data[2] = (b/255.0f)*t; + data += 3; + } + } + iUnCache(); + ifree(scanline); + + return ilFixImage(); +} + +void ReadScanline(ILubyte *scanline, ILuint w) { + ILubyte *runner; + ILuint r, g, b, e, read, shift; + + r = igetc(); + g = igetc(); + b = igetc(); + e = igetc(); + + //check if the scanline is in the new format + //if so, e, r, g, g are stored separated and are + //rle-compressed independently. + if (r == 2 && g == 2) { + ILuint length = (b << 8) | e; + ILuint j, t, k; + if (length > w) + length = w; //fix broken files + for (k = 0; k < 4; ++k) { + runner = scanline + k; + j = 0; + while (j < length) { + t = igetc(); + if (t > 128) { //Run? + ILubyte val = igetc(); + t &= 127; + //copy current byte + while (t > 0 && j < length) { + *runner = val; + runner += 4; + --t; + ++j; + } + } + else { //No Run. + //read new bytes + while (t > 0 && j < length) { + *runner = igetc(); + runner += 4; + --t; + ++j; + } + } + } + } + return; //done decoding a scanline in separated format + } + + //if we come here, we are dealing with old-style scanlines + shift = 0; + read = 0; + runner = scanline; + while (read < w) { + if (read != 0) { + r = igetc(); + g = igetc(); + b = igetc(); + e = igetc(); + } + + //if all three mantissas are 1, then this is a rle + //count dword + if (r == 1 && g == 1 && b == 1) { + ILuint length = e; + ILuint j; + for (j = length << shift; j > 0 && read < w; --j) { + memcpy(runner, runner - 4, 4); + runner += 4; + ++read; + } + //if more than one rle count dword is read + //consecutively, they are higher order bytes + //of the first read value. shift keeps track of + //that. + shift += 8; + } + else { + runner[0] = r; + runner[1] = g; + runner[2] = b; + runner[3] = e; + + shift = 0; + runner += 4; + ++read; + } + } +} + + + +//! Writes a Hdr file +ILboolean ilSaveHdr(const ILstring FileName) +{ + ILHANDLE HdrFile; + ILuint HdrSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + HdrFile = iopenw(FileName); + if (HdrFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + HdrSize = ilSaveHdrF(HdrFile); + iclosew(HdrFile); + + if (HdrSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Hdr to an already-opened file +ILuint ilSaveHdrF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveHdrInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Hdr to a memory "lump" +ILuint ilSaveHdrL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveHdrInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// +// Much of the saving code is based on the code by Bruce Walter, +// available at http://www.graphics.cornell.edu/online/formats/rgbe/. +// +// The actual source code file is +// http://www.graphics.cornell.edu/online/formats/rgbe/rgbe.c +// + + +/* standard conversion from float pixels to rgbe pixels */ +/* note: you can remove the "inline"s if your compiler complains about it */ +//static INLINE void +static void +float2rgbe(unsigned char rgbe[4], float red, float green, float blue) +{ + float v; + int e; + + v = red; + if (green > v) v = green; + if (blue > v) v = blue; + if (v < 1e-32) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } + else { + v = (float)(frexp(v,&e) * 256.0/v); + rgbe[0] = (unsigned char) (red * v); + rgbe[1] = (unsigned char) (green * v); + rgbe[2] = (unsigned char) (blue * v); + rgbe[3] = (unsigned char) (e + 128); + } +} + + +typedef struct { + ILuint valid; /* indicate which fields are valid */ + ILbyte programtype[16]; /* listed at beginning of file to identify it + * after "#?". defaults to "RGBE" */ + ILfloat gamma; /* image has already been gamma corrected with + * given gamma. defaults to 1.0 (no correction) */ + ILfloat exposure; /* a value of 1.0 in an image corresponds to + * watts/steradian/m^2. + * defaults to 1.0 */ +} rgbe_header_info; + +/* flags indicating which fields in an rgbe_header_info are valid */ +#define RGBE_VALID_PROGRAMTYPE 0x01 +#define RGBE_VALID_GAMMA 0x02 +#define RGBE_VALID_EXPOSURE 0x04 + +/* offsets to red, green, and blue components in a data (float) pixel */ +#define RGBE_DATA_RED 0 +#define RGBE_DATA_GREEN 1 +#define RGBE_DATA_BLUE 2 +/* number of floats per pixel */ +#define RGBE_DATA_SIZE 3 + + +/* default minimal header. modify if you want more information in header */ +ILboolean RGBE_WriteHeader(ILuint width, ILuint height, rgbe_header_info *info) +{ + char *programtype = "RGBE"; + + if (info && (info->valid & RGBE_VALID_PROGRAMTYPE)) + programtype = info->programtype; + if (ilprintf("#?%s\n",programtype) < 0) + return IL_FALSE; + /* The #? is to identify file type, the programtype is optional. */ + if (info && (info->valid & RGBE_VALID_GAMMA)) { + if (ilprintf("GAMMA=%g\n",info->gamma) < 0) + return IL_FALSE; + } + if (info && (info->valid & RGBE_VALID_EXPOSURE)) { + if (ilprintf("EXPOSURE=%g\n",info->exposure) < 0) + return IL_FALSE; + } + if (ilprintf("FORMAT=32-bit_rle_rgbe\n\n") < 0) + return IL_FALSE; + if (ilprintf("-Y %d +X %d\n", height, width) < 0) + return IL_FALSE; + return IL_TRUE; +} + + +/* simple write routine that does not use run length encoding */ +/* These routines can be made faster by allocating a larger buffer and + fread-ing and iwrite-ing the data in larger chunks */ +int RGBE_WritePixels(float *data, int numpixels) +{ + unsigned char rgbe[4]; + + while (numpixels-- > 0) { + float2rgbe(rgbe,data[RGBE_DATA_RED],data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]); + data += RGBE_DATA_SIZE; + if (iwrite(rgbe, sizeof(rgbe), 1) < 1) + return IL_FALSE; + } + return IL_TRUE; +} + + +/* The code below is only needed for the run-length encoded files. */ +/* Run length encoding adds considerable complexity but does */ +/* save some space. For each scanline, each channel (r,g,b,e) is */ +/* encoded separately for better compression. */ + +ILboolean RGBE_WriteBytes_RLE(ILubyte *data, ILuint numbytes) +{ +#define MINRUNLENGTH 4 + ILuint cur, beg_run, run_count, old_run_count, nonrun_count; + ILubyte buf[2]; + + cur = 0; + while (cur < numbytes) { + beg_run = cur; + /* find next run of length at least 4 if one exists */ + run_count = old_run_count = 0; + while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) { + beg_run += run_count; + old_run_count = run_count; + run_count = 1; + // 01-25-2009: Moved test for beg_run + run_count first so that it is + // tested first. This keeps it from going out of bounds by 1. + while((beg_run + run_count < numbytes) && (run_count < 127) && + (data[beg_run] == data[beg_run + run_count])) + run_count++; + } + /* if data before next big run is a short run then write it as such */ + if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) { + buf[0] = 128 + old_run_count; /*write short run*/ + buf[1] = data[cur]; + if (iwrite(buf,sizeof(buf[0])*2,1) < 1) + return IL_FALSE; + cur = beg_run; + } + /* write out bytes until we reach the start of the next run */ + while(cur < beg_run) { + nonrun_count = beg_run - cur; + if (nonrun_count > 128) + nonrun_count = 128; + buf[0] = nonrun_count; + if (iwrite(buf,sizeof(buf[0]),1) < 1) + return IL_FALSE; + if (iwrite(&data[cur],sizeof(data[0])*nonrun_count,1) < 1) + return IL_FALSE; + cur += nonrun_count; + } + /* write out next run if one was found */ + if (run_count >= MINRUNLENGTH) { + buf[0] = 128 + run_count; + buf[1] = data[beg_run]; + if (iwrite(buf,sizeof(buf[0])*2,1) < 1) + return IL_FALSE; + cur += run_count; + } + } + return IL_TRUE; +#undef MINRUNLENGTH +} + + +// Internal function used to save the Hdr. +ILboolean iSaveHdrInternal() +{ + ILimage *TempImage; + rgbe_header_info stHeader; + unsigned char rgbe[4]; + ILubyte *buffer; + ILfloat *data; + ILuint i; + ILboolean bRet; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + stHeader.exposure = 0; + stHeader.gamma = 0; + stHeader.programtype[0] = 0; + stHeader.valid = 0; + + if (iCurImage->Format != IL_UNSIGNED_BYTE) { + TempImage = iConvertImage(iCurImage, IL_RGB, IL_FLOAT); + if (TempImage == NULL) + return IL_FALSE; + } + else + TempImage = iCurImage; + + if (!RGBE_WriteHeader(TempImage->Width, TempImage->Height, &stHeader)) + return IL_FALSE; + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) + iFlipBuffer(TempImage->Data, TempImage->Depth, TempImage->Bps, TempImage->Height); + data = (ILfloat*)TempImage->Data; + + if ((TempImage->Width < 8)||(TempImage->Width > 0x7fff)) { + /* run length encoding is not allowed so write flat*/ + bRet = RGBE_WritePixels(data,TempImage->Width*TempImage->Height); + if (iCurImage != TempImage) + ilCloseImage(TempImage); + return bRet; + } + buffer = (ILubyte*)ialloc(sizeof(ILubyte)*4*TempImage->Width); + if (buffer == NULL) { + /* no buffer space so write flat */ + bRet = RGBE_WritePixels(data,TempImage->Width*TempImage->Height); + if (iCurImage != TempImage) + ilCloseImage(TempImage); + return bRet; + } + + while(TempImage->Height-- > 0) { + rgbe[0] = 2; + rgbe[1] = 2; + rgbe[2] = TempImage->Width >> 8; + rgbe[3] = TempImage->Width & 0xFF; + if (iwrite(rgbe, sizeof(rgbe), 1) < 1) { + free(buffer); + if (iCurImage != TempImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + + for(i=0;iWidth;i++) { + float2rgbe(rgbe,data[RGBE_DATA_RED],data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]); + buffer[i] = rgbe[0]; + buffer[i+TempImage->Width] = rgbe[1]; + buffer[i+2*TempImage->Width] = rgbe[2]; + buffer[i+3*TempImage->Width] = rgbe[3]; + data += RGBE_DATA_SIZE; + } + /* write out each of the four channels separately run length encoded */ + /* first red, then green, then blue, then exponent */ + for(i=0;i<4;i++) { + if (RGBE_WriteBytes_RLE(&buffer[i*TempImage->Width],TempImage->Width) != IL_TRUE) { + ifree(buffer); + if (iCurImage != TempImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + } + } + ifree(buffer); + + if (iCurImage != TempImage) + ilCloseImage(TempImage); + return IL_TRUE; +} + + +#endif//IL_NO_HDR diff --git a/DevIL/src-IL/src/il_header.c b/DevIL/src-IL/src/il_header.c deleted file mode 100644 index d92903d6..00000000 --- a/DevIL/src-IL/src/il_header.c +++ /dev/null @@ -1,135 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 10/10/2006 -// -// Filename: src-IL/src/il_header.c -// -// Description: Generates a C-style header file for the current image. -// -//----------------------------------------------------------------------------- - -#ifndef IL_NO_CHEAD - -#include "il_internal.h" - -// Just a guess...let's see what's purty! -#define MAX_LINE_WIDTH 14 - -//! Generates a C-style header file for the current image. -ILboolean ilSaveCHeader(ILconst_string FileName, char *InternalName) -{ - FILE *HeadFile; - ILuint i = 0, j; - ILimage *TempImage; - const char *Name; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Name = iGetString(IL_CHEAD_HEADER_STRING); - if (Name == NULL) - Name = InternalName; - - if (FileName == NULL || Name == NULL || - ilStrLen(FileName) < 1 || ilCharStrLen(Name) < 1) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - if (!iCheckExtension(FileName, IL_TEXT("h"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - if (iCurImage->Bpc > 1) { - TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - } else { - TempImage = iCurImage; - } - -#ifndef _UNICODE - HeadFile = fopen(FileName, "wb"); -#else - #ifdef _WIN32 - HeadFile = _wfopen(FileName, L"rb"); - #else - HeadFile = fopen((char*)FileName, "rb"); - #endif - -#endif//_UNICODE - - if (HeadFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - fprintf(HeadFile, "//#include \n"); - fprintf(HeadFile, "// C Image Header:\n\n\n"); - fprintf(HeadFile, "// IMAGE_BPP is in bytes per pixel, *not* bits\n"); - fprintf(HeadFile, "#define IMAGE_BPP %d\n",iCurImage->Bpp); - fprintf(HeadFile, "#define IMAGE_WIDTH %d\n", iCurImage->Width); - fprintf(HeadFile, "#define IMAGE_HEIGHT %d\n", iCurImage->Height); - fprintf(HeadFile, "#define IMAGE_DEPTH %d\n\n\n", iCurImage->Depth); - fprintf(HeadFile, "#define IMAGE_TYPE 0x%X\n", iCurImage->Type); - fprintf(HeadFile, "#define IMAGE_FORMAT 0x%X\n\n\n", iCurImage->Format); - fprintf(HeadFile, "ILubyte %s[] = {\n", Name); - - - for (; i < TempImage->SizeOfData; i += MAX_LINE_WIDTH) { - fprintf(HeadFile, "\t"); - for (j = 0; j < MAX_LINE_WIDTH; j++) { - if (i + j >= TempImage->SizeOfData - 1) { - fprintf(HeadFile, "%4d", TempImage->Data[i+j]); - break; - } - else - fprintf(HeadFile, "%4d,", TempImage->Data[i+j]); - } - fprintf(HeadFile, "\n"); - } - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - fprintf(HeadFile, "};\n"); - - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) { - fprintf(HeadFile, "\n\n"); - fprintf(HeadFile, "#define IMAGE_PALSIZE %u\n\n", iCurImage->Pal.PalSize); - fprintf(HeadFile, "#define IMAGE_PALTYPE 0x%X\n\n", iCurImage->Pal.PalType); - fprintf(HeadFile, "ILubyte %sPal[] = {\n", Name); - for (i = 0; i < iCurImage->Pal.PalSize; i += MAX_LINE_WIDTH) { - fprintf(HeadFile, "\t"); - for (j = 0; j < MAX_LINE_WIDTH; j++) { - if (i + j >= iCurImage->Pal.PalSize - 1) { - fprintf(HeadFile, " %4d", iCurImage->Pal.Palette[i+j]); - break; - } - else - fprintf(HeadFile, " %4d,", iCurImage->Pal.Palette[i+j]); - } - fprintf(HeadFile, "\n"); - } - - fprintf(HeadFile, "};\n"); - } - fclose(HeadFile); - return IL_TRUE; -} - - - -#endif//IL_NO_CHEAD diff --git a/DevIL/src-IL/src/il_header.cpp b/DevIL/src-IL/src/il_header.cpp new file mode 100644 index 00000000..d92903d6 --- /dev/null +++ b/DevIL/src-IL/src/il_header.cpp @@ -0,0 +1,135 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 10/10/2006 +// +// Filename: src-IL/src/il_header.c +// +// Description: Generates a C-style header file for the current image. +// +//----------------------------------------------------------------------------- + +#ifndef IL_NO_CHEAD + +#include "il_internal.h" + +// Just a guess...let's see what's purty! +#define MAX_LINE_WIDTH 14 + +//! Generates a C-style header file for the current image. +ILboolean ilSaveCHeader(ILconst_string FileName, char *InternalName) +{ + FILE *HeadFile; + ILuint i = 0, j; + ILimage *TempImage; + const char *Name; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Name = iGetString(IL_CHEAD_HEADER_STRING); + if (Name == NULL) + Name = InternalName; + + if (FileName == NULL || Name == NULL || + ilStrLen(FileName) < 1 || ilCharStrLen(Name) < 1) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + if (!iCheckExtension(FileName, IL_TEXT("h"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + if (iCurImage->Bpc > 1) { + TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + } else { + TempImage = iCurImage; + } + +#ifndef _UNICODE + HeadFile = fopen(FileName, "wb"); +#else + #ifdef _WIN32 + HeadFile = _wfopen(FileName, L"rb"); + #else + HeadFile = fopen((char*)FileName, "rb"); + #endif + +#endif//_UNICODE + + if (HeadFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + fprintf(HeadFile, "//#include \n"); + fprintf(HeadFile, "// C Image Header:\n\n\n"); + fprintf(HeadFile, "// IMAGE_BPP is in bytes per pixel, *not* bits\n"); + fprintf(HeadFile, "#define IMAGE_BPP %d\n",iCurImage->Bpp); + fprintf(HeadFile, "#define IMAGE_WIDTH %d\n", iCurImage->Width); + fprintf(HeadFile, "#define IMAGE_HEIGHT %d\n", iCurImage->Height); + fprintf(HeadFile, "#define IMAGE_DEPTH %d\n\n\n", iCurImage->Depth); + fprintf(HeadFile, "#define IMAGE_TYPE 0x%X\n", iCurImage->Type); + fprintf(HeadFile, "#define IMAGE_FORMAT 0x%X\n\n\n", iCurImage->Format); + fprintf(HeadFile, "ILubyte %s[] = {\n", Name); + + + for (; i < TempImage->SizeOfData; i += MAX_LINE_WIDTH) { + fprintf(HeadFile, "\t"); + for (j = 0; j < MAX_LINE_WIDTH; j++) { + if (i + j >= TempImage->SizeOfData - 1) { + fprintf(HeadFile, "%4d", TempImage->Data[i+j]); + break; + } + else + fprintf(HeadFile, "%4d,", TempImage->Data[i+j]); + } + fprintf(HeadFile, "\n"); + } + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + fprintf(HeadFile, "};\n"); + + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) { + fprintf(HeadFile, "\n\n"); + fprintf(HeadFile, "#define IMAGE_PALSIZE %u\n\n", iCurImage->Pal.PalSize); + fprintf(HeadFile, "#define IMAGE_PALTYPE 0x%X\n\n", iCurImage->Pal.PalType); + fprintf(HeadFile, "ILubyte %sPal[] = {\n", Name); + for (i = 0; i < iCurImage->Pal.PalSize; i += MAX_LINE_WIDTH) { + fprintf(HeadFile, "\t"); + for (j = 0; j < MAX_LINE_WIDTH; j++) { + if (i + j >= iCurImage->Pal.PalSize - 1) { + fprintf(HeadFile, " %4d", iCurImage->Pal.Palette[i+j]); + break; + } + else + fprintf(HeadFile, " %4d,", iCurImage->Pal.Palette[i+j]); + } + fprintf(HeadFile, "\n"); + } + + fprintf(HeadFile, "};\n"); + } + fclose(HeadFile); + return IL_TRUE; +} + + + +#endif//IL_NO_CHEAD diff --git a/DevIL/src-IL/src/il_icns.c b/DevIL/src-IL/src/il_icns.c deleted file mode 100644 index e316f2fb..00000000 --- a/DevIL/src-IL/src/il_icns.c +++ /dev/null @@ -1,362 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2001-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_icns.c -// -// Description: Reads from a Mac OS X icon (.icns) file. -// Credit for the format of .icns files goes to -// http://www.macdisk.com/maciconen.php3 and -// http://ezix.org/project/wiki/MacOSXIcons -// -//----------------------------------------------------------------------------- - -//@TODO: Put ilSetError calls in when errors occur. -//@TODO: Should we clear the alpha channel just in case there isn't one in the file? -//@TODO: Checks on iread - -#include "il_internal.h" -#ifndef IL_NO_ICNS -#include "il_icns.h" - -#ifndef IL_NO_JP2 - #if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "libjasper.lib") - #else - #pragma comment(lib, "libjasper.lib") //libjasper-d.lib - #endif - #endif - #endif -#endif//IL_NO_JP2 - - -//! Checks if the file specified in FileName is a valid .icns file. -ILboolean ilIsValidIcns(ILconst_string FileName) -{ - ILHANDLE IcnsFile; - ILboolean bIcns = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("icns"))) { - ilSetError(IL_INVALID_EXTENSION); - return bIcns; - } - - IcnsFile = iopenr(FileName); - if (IcnsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIcns; - } - - bIcns = ilIsValidIcnsF(IcnsFile); - icloser(IcnsFile); - - return bIcns; -} - - -//! Checks if the ILHANDLE contains a valid .icns file at the current position. -ILboolean ilIsValidIcnsF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidIcns(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .icns lump. -ILboolean ilIsValidIcnsL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidIcns(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidIcns() -{ - ICNSHEAD Header; - - iread(Header.Head, 1, 4); - iseek(-4, IL_SEEK_CUR); // Go ahead and restore to previous state - - if (strncmp(Header.Head, "icns", 4)) // First 4 bytes have to be 'icns'. - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads an icon file. -ILboolean ilLoadIcns(ILconst_string FileName) -{ - ILHANDLE IcnsFile; - ILboolean bIcns = IL_FALSE; - - IcnsFile = iopenr(FileName); - if (IcnsFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIcns; - } - - bIcns = ilLoadIcnsF(IcnsFile); - icloser(IcnsFile); - - return bIcns; -} - - -//! Reads an already-opened icon file. -ILboolean ilLoadIcnsF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadIcnsInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains an icon. -ILboolean ilLoadIcnsL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadIcnsInternal(); -} - - -// Internal function used to load the icon. -ILboolean iLoadIcnsInternal() -{ - ICNSHEAD Header; - ICNSDATA Entry; - ILimage *Image = NULL; - ILboolean BaseCreated = IL_FALSE; - - - if (iCurImage == NULL) - { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iread(Header.Head, 4, 1); - Header.Size = GetBigInt(); - - if (strncmp(Header.Head, "icns", 4)) // First 4 bytes have to be 'icns'. - return IL_FALSE; - - while ((ILint)itell() < Header.Size && !ieof()) - { - iread(Entry.ID, 4, 1); - Entry.Size = GetBigInt(); - - if (!strncmp(Entry.ID, "it32", 4)) // 128x128 24-bit - { - if (iIcnsReadData(&BaseCreated, IL_FALSE, 128, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "t8mk", 4)) // 128x128 alpha mask - { - if (iIcnsReadData(&BaseCreated, IL_TRUE, 128, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "ih32", 4)) // 48x48 24-bit - { - if (iIcnsReadData(&BaseCreated, IL_FALSE, 48, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "h8mk", 4)) // 48x48 alpha mask - { - if (iIcnsReadData(&BaseCreated, IL_TRUE, 48, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "il32", 4)) // 32x32 24-bit - { - if (iIcnsReadData(&BaseCreated, IL_FALSE, 32, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "l8mk", 4)) // 32x32 alpha mask - { - if (iIcnsReadData(&BaseCreated, IL_TRUE, 32, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "is32", 4)) // 16x16 24-bit - { - if (iIcnsReadData(&BaseCreated, IL_FALSE, 16, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "s8mk", 4)) // 16x16 alpha mask - { - if (iIcnsReadData(&BaseCreated, IL_TRUE, 16, &Entry, &Image) == IL_FALSE) - goto icns_error; - } -#ifndef IL_NO_JP2 - else if (!strncmp(Entry.ID, "ic09", 4)) // 512x512 JPEG2000 encoded - Uses JasPer - { - if (iIcnsReadData(&BaseCreated, IL_FALSE, 512, &Entry, &Image) == IL_FALSE) - goto icns_error; - } - else if (!strncmp(Entry.ID, "ic08", 4)) // 256x256 JPEG2000 encoded - Uses JasPer - { - if (iIcnsReadData(&BaseCreated, IL_FALSE, 256, &Entry, &Image) == IL_FALSE) - goto icns_error; - } -#endif//IL_NO_JP2 - else // Not a valid format or one that we can use - { - iseek(Entry.Size - 8, IL_SEEK_CUR); - } - } - - return ilFixImage(); - -icns_error: - return IL_FALSE; -} - -ILboolean iIcnsReadData(ILboolean *BaseCreated, ILboolean IsAlpha, ILint Width, ICNSDATA *Entry, ILimage **Image) -{ - ILint Position = 0, RLEPos = 0, Channel, i; - ILubyte RLERead, *Data = NULL; - ILimage *TempImage = NULL; - ILboolean ImageAlreadyExists = IL_FALSE; - - // The .icns format stores the alpha and RGB as two separate images, so this - // checks to see if one exists for that particular size. Unfortunately, - // there is no guarantee that they are in any particular order. - if (*BaseCreated && iCurImage != NULL) - { - TempImage = iCurImage; - while (TempImage != NULL) - { - if ((ILuint)Width == TempImage->Width) - { - ImageAlreadyExists = IL_TRUE; - break; - } - TempImage = TempImage->Next; - } - } - - Data = ialloc(Entry->Size - 8); - if (Data == NULL) - return IL_FALSE; - - if (!ImageAlreadyExists) - { - if (!*BaseCreated) // Create base image - { - ilTexImage(Width, Width, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - *Image = iCurImage; - *BaseCreated = IL_TRUE; - } - else // Create next image in list - { - (*Image)->Next = ilNewImage(Width, Width, 1, 4, 1); - *Image = (*Image)->Next; - (*Image)->Format = IL_RGBA; - (*Image)->Origin = IL_ORIGIN_UPPER_LEFT; - } - - TempImage = *Image; - } - - if (IsAlpha) // Alpha is never compressed. - { - iread(Data, Entry->Size - 8, 1); // Size includes the header - if (Entry->Size - 8 != Width * Width) - { - ifree(Data); - return IL_FALSE; - } - - for (i = 0; i < Width * Width; i++) - { - TempImage->Data[(i * 4) + 3] = Data[i]; - } - } - else if (Width == 256 || Width == 512) // JPEG2000 encoded - uses JasPer - { -#ifndef IL_NO_JP2 - iread(Data, Entry->Size - 8, 1); // Size includes the header - if (ilLoadJp2LInternal(Data, Entry->Size - 8, TempImage) == IL_FALSE) - { - ifree(Data); - ilSetError(IL_LIB_JP2_ERROR); - return IL_TRUE; - } -#else // Cannot handle this size. - ilSetError(IL_LIB_JP2_ERROR); //@TODO: Handle this better...just skip the data. - return IL_FALSE; -#endif//IL_NO_JP2 - } - else // RGB data - { - iread(Data, Entry->Size - 8, 1); // Size includes the header - if (Width == 128) - RLEPos += 4; // There are an extra 4 bytes here of zeros. - //@TODO: Should we check to make sure they are all 0? - - if (Entry->Size - 8 == Width * Width * 4) // Uncompressed - { - //memcpy(TempImage->Data, Data, Entry->Size); - for (i = 0; i < Width * Width; i++, Position += 4) - { - TempImage->Data[i * 4 + 0] = Data[Position+1]; - TempImage->Data[i * 4 + 1] = Data[Position+2]; - TempImage->Data[i * 4 + 2] = Data[Position+3]; - } - } - else // RLE decoding - { - for (Channel = 0; Channel < 3; Channel++) - { - Position = 0; - while (Position < Width * Width) - { - RLERead = Data[RLEPos]; - RLEPos++; - - if (RLERead >= 128) - { - for (i = 0; i < RLERead - 125 && (Position + i) < Width * Width; i++) - { - TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos]; - } - RLEPos++; - Position += RLERead - 125; - } - else - { - for (i = 0; i < RLERead + 1 && (Position + i) < Width * Width; i++) - { - TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos + i]; - } - RLEPos += RLERead + 1; - Position += RLERead + 1; - } - } - } - } - } - - ifree(Data); - return IL_TRUE; -} - -#endif//IL_NO_ICNS diff --git a/DevIL/src-IL/src/il_icns.cpp b/DevIL/src-IL/src/il_icns.cpp new file mode 100644 index 00000000..e316f2fb --- /dev/null +++ b/DevIL/src-IL/src/il_icns.cpp @@ -0,0 +1,362 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2001-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_icns.c +// +// Description: Reads from a Mac OS X icon (.icns) file. +// Credit for the format of .icns files goes to +// http://www.macdisk.com/maciconen.php3 and +// http://ezix.org/project/wiki/MacOSXIcons +// +//----------------------------------------------------------------------------- + +//@TODO: Put ilSetError calls in when errors occur. +//@TODO: Should we clear the alpha channel just in case there isn't one in the file? +//@TODO: Checks on iread + +#include "il_internal.h" +#ifndef IL_NO_ICNS +#include "il_icns.h" + +#ifndef IL_NO_JP2 + #if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "libjasper.lib") + #else + #pragma comment(lib, "libjasper.lib") //libjasper-d.lib + #endif + #endif + #endif +#endif//IL_NO_JP2 + + +//! Checks if the file specified in FileName is a valid .icns file. +ILboolean ilIsValidIcns(ILconst_string FileName) +{ + ILHANDLE IcnsFile; + ILboolean bIcns = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("icns"))) { + ilSetError(IL_INVALID_EXTENSION); + return bIcns; + } + + IcnsFile = iopenr(FileName); + if (IcnsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIcns; + } + + bIcns = ilIsValidIcnsF(IcnsFile); + icloser(IcnsFile); + + return bIcns; +} + + +//! Checks if the ILHANDLE contains a valid .icns file at the current position. +ILboolean ilIsValidIcnsF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidIcns(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .icns lump. +ILboolean ilIsValidIcnsL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidIcns(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidIcns() +{ + ICNSHEAD Header; + + iread(Header.Head, 1, 4); + iseek(-4, IL_SEEK_CUR); // Go ahead and restore to previous state + + if (strncmp(Header.Head, "icns", 4)) // First 4 bytes have to be 'icns'. + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads an icon file. +ILboolean ilLoadIcns(ILconst_string FileName) +{ + ILHANDLE IcnsFile; + ILboolean bIcns = IL_FALSE; + + IcnsFile = iopenr(FileName); + if (IcnsFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIcns; + } + + bIcns = ilLoadIcnsF(IcnsFile); + icloser(IcnsFile); + + return bIcns; +} + + +//! Reads an already-opened icon file. +ILboolean ilLoadIcnsF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadIcnsInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains an icon. +ILboolean ilLoadIcnsL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadIcnsInternal(); +} + + +// Internal function used to load the icon. +ILboolean iLoadIcnsInternal() +{ + ICNSHEAD Header; + ICNSDATA Entry; + ILimage *Image = NULL; + ILboolean BaseCreated = IL_FALSE; + + + if (iCurImage == NULL) + { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iread(Header.Head, 4, 1); + Header.Size = GetBigInt(); + + if (strncmp(Header.Head, "icns", 4)) // First 4 bytes have to be 'icns'. + return IL_FALSE; + + while ((ILint)itell() < Header.Size && !ieof()) + { + iread(Entry.ID, 4, 1); + Entry.Size = GetBigInt(); + + if (!strncmp(Entry.ID, "it32", 4)) // 128x128 24-bit + { + if (iIcnsReadData(&BaseCreated, IL_FALSE, 128, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "t8mk", 4)) // 128x128 alpha mask + { + if (iIcnsReadData(&BaseCreated, IL_TRUE, 128, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "ih32", 4)) // 48x48 24-bit + { + if (iIcnsReadData(&BaseCreated, IL_FALSE, 48, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "h8mk", 4)) // 48x48 alpha mask + { + if (iIcnsReadData(&BaseCreated, IL_TRUE, 48, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "il32", 4)) // 32x32 24-bit + { + if (iIcnsReadData(&BaseCreated, IL_FALSE, 32, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "l8mk", 4)) // 32x32 alpha mask + { + if (iIcnsReadData(&BaseCreated, IL_TRUE, 32, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "is32", 4)) // 16x16 24-bit + { + if (iIcnsReadData(&BaseCreated, IL_FALSE, 16, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "s8mk", 4)) // 16x16 alpha mask + { + if (iIcnsReadData(&BaseCreated, IL_TRUE, 16, &Entry, &Image) == IL_FALSE) + goto icns_error; + } +#ifndef IL_NO_JP2 + else if (!strncmp(Entry.ID, "ic09", 4)) // 512x512 JPEG2000 encoded - Uses JasPer + { + if (iIcnsReadData(&BaseCreated, IL_FALSE, 512, &Entry, &Image) == IL_FALSE) + goto icns_error; + } + else if (!strncmp(Entry.ID, "ic08", 4)) // 256x256 JPEG2000 encoded - Uses JasPer + { + if (iIcnsReadData(&BaseCreated, IL_FALSE, 256, &Entry, &Image) == IL_FALSE) + goto icns_error; + } +#endif//IL_NO_JP2 + else // Not a valid format or one that we can use + { + iseek(Entry.Size - 8, IL_SEEK_CUR); + } + } + + return ilFixImage(); + +icns_error: + return IL_FALSE; +} + +ILboolean iIcnsReadData(ILboolean *BaseCreated, ILboolean IsAlpha, ILint Width, ICNSDATA *Entry, ILimage **Image) +{ + ILint Position = 0, RLEPos = 0, Channel, i; + ILubyte RLERead, *Data = NULL; + ILimage *TempImage = NULL; + ILboolean ImageAlreadyExists = IL_FALSE; + + // The .icns format stores the alpha and RGB as two separate images, so this + // checks to see if one exists for that particular size. Unfortunately, + // there is no guarantee that they are in any particular order. + if (*BaseCreated && iCurImage != NULL) + { + TempImage = iCurImage; + while (TempImage != NULL) + { + if ((ILuint)Width == TempImage->Width) + { + ImageAlreadyExists = IL_TRUE; + break; + } + TempImage = TempImage->Next; + } + } + + Data = ialloc(Entry->Size - 8); + if (Data == NULL) + return IL_FALSE; + + if (!ImageAlreadyExists) + { + if (!*BaseCreated) // Create base image + { + ilTexImage(Width, Width, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + *Image = iCurImage; + *BaseCreated = IL_TRUE; + } + else // Create next image in list + { + (*Image)->Next = ilNewImage(Width, Width, 1, 4, 1); + *Image = (*Image)->Next; + (*Image)->Format = IL_RGBA; + (*Image)->Origin = IL_ORIGIN_UPPER_LEFT; + } + + TempImage = *Image; + } + + if (IsAlpha) // Alpha is never compressed. + { + iread(Data, Entry->Size - 8, 1); // Size includes the header + if (Entry->Size - 8 != Width * Width) + { + ifree(Data); + return IL_FALSE; + } + + for (i = 0; i < Width * Width; i++) + { + TempImage->Data[(i * 4) + 3] = Data[i]; + } + } + else if (Width == 256 || Width == 512) // JPEG2000 encoded - uses JasPer + { +#ifndef IL_NO_JP2 + iread(Data, Entry->Size - 8, 1); // Size includes the header + if (ilLoadJp2LInternal(Data, Entry->Size - 8, TempImage) == IL_FALSE) + { + ifree(Data); + ilSetError(IL_LIB_JP2_ERROR); + return IL_TRUE; + } +#else // Cannot handle this size. + ilSetError(IL_LIB_JP2_ERROR); //@TODO: Handle this better...just skip the data. + return IL_FALSE; +#endif//IL_NO_JP2 + } + else // RGB data + { + iread(Data, Entry->Size - 8, 1); // Size includes the header + if (Width == 128) + RLEPos += 4; // There are an extra 4 bytes here of zeros. + //@TODO: Should we check to make sure they are all 0? + + if (Entry->Size - 8 == Width * Width * 4) // Uncompressed + { + //memcpy(TempImage->Data, Data, Entry->Size); + for (i = 0; i < Width * Width; i++, Position += 4) + { + TempImage->Data[i * 4 + 0] = Data[Position+1]; + TempImage->Data[i * 4 + 1] = Data[Position+2]; + TempImage->Data[i * 4 + 2] = Data[Position+3]; + } + } + else // RLE decoding + { + for (Channel = 0; Channel < 3; Channel++) + { + Position = 0; + while (Position < Width * Width) + { + RLERead = Data[RLEPos]; + RLEPos++; + + if (RLERead >= 128) + { + for (i = 0; i < RLERead - 125 && (Position + i) < Width * Width; i++) + { + TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos]; + } + RLEPos++; + Position += RLERead - 125; + } + else + { + for (i = 0; i < RLERead + 1 && (Position + i) < Width * Width; i++) + { + TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos + i]; + } + RLEPos += RLERead + 1; + Position += RLERead + 1; + } + } + } + } + } + + ifree(Data); + return IL_TRUE; +} + +#endif//IL_NO_ICNS diff --git a/DevIL/src-IL/src/il_icon.c b/DevIL/src-IL/src/il_icon.c deleted file mode 100644 index fd9475dc..00000000 --- a/DevIL/src-IL/src/il_icon.c +++ /dev/null @@ -1,674 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2001-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_icon.c -// -// Description: Reads from a Windows icon (.ico) file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_ICO -#include "il_icon.h" -#ifndef IL_NO_PNG - #include -#endif - -//! Reads an icon file. -ILboolean ilLoadIcon(ILconst_string FileName) -{ - ILHANDLE IconFile; - ILboolean bIcon = IL_FALSE; - - IconFile = iopenr(FileName); - if (IconFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIcon; - } - - bIcon = ilLoadIconF(IconFile); - icloser(IconFile); - - return bIcon; -} - - -//! Reads an already-opened icon file. -ILboolean ilLoadIconF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadIconInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains an icon. -ILboolean ilLoadIconL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadIconInternal(); -} - - -// Internal function used to load the icon. -ILboolean iLoadIconInternal() -{ - ICODIR IconDir; - ICODIRENTRY *DirEntries = NULL; - ICOIMAGE *IconImages = NULL; - ILimage *Image = NULL; - ILint i; - ILuint Size, PadSize, ANDPadSize, j, k, l, m, x, w, CurAndByte, AndBytes; - ILboolean BaseCreated = IL_FALSE; - ILubyte PNGTest[3]; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - IconDir.Reserved = GetLittleShort(); - IconDir.Type = GetLittleShort(); - IconDir.Count = GetLittleShort(); - - if (ieof()) - goto file_read_error; - - DirEntries = (ICODIRENTRY*)ialloc(sizeof(ICODIRENTRY) * IconDir.Count); - IconImages = (ICOIMAGE*)ialloc(sizeof(ICOIMAGE) * IconDir.Count); - if (DirEntries == NULL || IconImages == NULL) { - ifree(DirEntries); - ifree(IconImages); - return IL_FALSE; - } - - // Make it easier for file_read_error. - for (i = 0; i < IconDir.Count; i++) - imemclear(&IconImages[i], sizeof(ICOIMAGE)); - - for (i = 0; i < IconDir.Count; ++i) { - DirEntries[i].Width = (ILubyte)igetc(); - DirEntries[i].Height = (ILubyte)igetc(); - DirEntries[i].NumColours = (ILubyte)igetc(); - DirEntries[i].Reserved = (ILubyte)igetc(); - DirEntries[i].Planes = GetLittleShort(); - DirEntries[i].Bpp = GetLittleShort(); - DirEntries[i].SizeOfData = GetLittleUInt(); - DirEntries[i].Offset = GetLittleUInt(); - - if (ieof()) - goto file_read_error; - } - - for (i = 0; i < IconDir.Count; i++) { - iseek(DirEntries[i].Offset, IL_SEEK_SET); - - // 08-22-2008: Adding test for compressed PNG data - igetc(); // Skip the first character...seems to vary. - iread(PNGTest, 3, 1); - if (!strnicmp((char*)PNGTest, "PNG", 3)) // Characters 'P', 'N', 'G' for PNG header - { -#ifdef IL_NO_PNG - ilSetError(IL_FORMAT_NOT_SUPPORTED); // Cannot handle these without libpng. - goto file_read_error; -#else - iseek(DirEntries[i].Offset, IL_SEEK_SET); - if (!iLoadIconPNG(&IconImages[i])) - goto file_read_error; -#endif - } - else - { - // Need to go back the 4 bytes that were just read. - iseek(DirEntries[i].Offset, IL_SEEK_SET); - - IconImages[i].Head.Size = GetLittleInt(); - IconImages[i].Head.Width = GetLittleInt(); - IconImages[i].Head.Height = GetLittleInt(); - IconImages[i].Head.Planes = GetLittleShort(); - IconImages[i].Head.BitCount = GetLittleShort(); - IconImages[i].Head.Compression = GetLittleInt(); - IconImages[i].Head.SizeImage = GetLittleInt(); - IconImages[i].Head.XPixPerMeter = GetLittleInt(); - IconImages[i].Head.YPixPerMeter = GetLittleInt(); - IconImages[i].Head.ColourUsed = GetLittleInt(); - IconImages[i].Head.ColourImportant = GetLittleInt(); - - if (ieof()) - goto file_read_error; - - if (IconImages[i].Head.BitCount < 8) { - if (IconImages[i].Head.ColourUsed == 0) { - switch (IconImages[i].Head.BitCount) - { - case 1: - IconImages[i].Head.ColourUsed = 2; - break; - case 4: - IconImages[i].Head.ColourUsed = 16; - break; - } - } - IconImages[i].Pal = (ILubyte*)ialloc(IconImages[i].Head.ColourUsed * 4); - if (IconImages[i].Pal == NULL) - goto file_read_error; // @TODO: Rename the label. - if (iread(IconImages[i].Pal, IconImages[i].Head.ColourUsed * 4, 1) != 1) - goto file_read_error; - } - else if (IconImages[i].Head.BitCount == 8) { - IconImages[i].Pal = (ILubyte*)ialloc(256 * 4); - if (IconImages[i].Pal == NULL) - goto file_read_error; - if (iread(IconImages[i].Pal, 1, 256 * 4) != 256*4) - goto file_read_error; - } - else { - IconImages[i].Pal = NULL; - } - - PadSize = (4 - ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4; // Has to be DWORD-aligned. - ANDPadSize = (4 - ((IconImages[i].Head.Width + 7) / 8) % 4) % 4; // AND is 1 bit/pixel - Size = ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8 + PadSize) - * (IconImages[i].Head.Height / 2); - - - IconImages[i].Data = (ILubyte*)ialloc(Size); - if (IconImages[i].Data == NULL) - goto file_read_error; - if (iread(IconImages[i].Data, 1, Size) != Size) - goto file_read_error; - - Size = (((IconImages[i].Head.Width + 7) /8) + ANDPadSize) * (IconImages[i].Head.Height / 2); - IconImages[i].AND = (ILubyte*)ialloc(Size); - if (IconImages[i].AND == NULL) - goto file_read_error; - if (iread(IconImages[i].AND, 1, Size) != Size) - goto file_read_error; - } - } - - - for (i = 0; i < IconDir.Count; i++) { - if (IconImages[i].Head.BitCount != 1 && IconImages[i].Head.BitCount != 4 && - IconImages[i].Head.BitCount != 8 && IconImages[i].Head.BitCount != 24 && - - IconImages[i].Head.BitCount != 32) - continue; - - if (!BaseCreated) { - if (IconImages[i].Head.Size == 0) // PNG compressed icon - ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); - else - ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - Image = iCurImage; - BaseCreated = IL_TRUE; - } - else { - if (IconImages[i].Head.Size == 0) // PNG compressed icon - Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height, 1, 4, 1); - else - Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, 1); - Image = Image->Next; - Image->Format = IL_BGRA; - } - Image->Type = IL_UNSIGNED_BYTE; - - j = 0; k = 0; l = 128; CurAndByte = 0; x = 0; - - w = IconImages[i].Head.Width; - PadSize = (4 - ((w*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4; // Has to be DWORD-aligned. - - ANDPadSize = (4 - ((w + 7) / 8) % 4) % 4; // AND is 1 bit/pixel - AndBytes = (w + 7) / 8; - - if (IconImages[i].Head.BitCount == 1) { - for (; j < Image->SizeOfData; k++) { - for (m = 128; m && x < w; m >>= 1) { - Image->Data[j] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4]; - Image->Data[j+1] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 1]; - Image->Data[j+2] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 2]; - Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; - j += 4; - l >>= 1; - - ++x; - } - if (l == 0 || x == w) { - l = 128; - CurAndByte++; - if (x == w) { - CurAndByte += ANDPadSize; - k += PadSize; - x = 0; - } - - } - } - } - else if (IconImages[i].Head.BitCount == 4) { - for (; j < Image->SizeOfData; j += 8, k++) { - Image->Data[j] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4]; - Image->Data[j+1] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 1]; - Image->Data[j+2] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 2]; - Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; - l >>= 1; - - ++x; - - if(x < w) { - Image->Data[j+4] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4]; - Image->Data[j+5] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 1]; - Image->Data[j+6] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 2]; - Image->Data[j+7] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; - l >>= 1; - - ++x; - - } - - else - - j -= 4; - - - if (l == 0 || x == w) { - l = 128; - CurAndByte++; - if (x == w) { - CurAndByte += ANDPadSize; - - k += PadSize; - x = 0; - } - } - } - } - else if (IconImages[i].Head.BitCount == 8) { - for (; j < Image->SizeOfData; j += 4, k++) { - Image->Data[j] = IconImages[i].Pal[IconImages[i].Data[k] * 4]; - Image->Data[j+1] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 1]; - Image->Data[j+2] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 2]; - if (IconImages[i].AND == NULL) // PNG Palette - { - Image->Data[j+3] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 3]; - } - else - { - Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; - } - l >>= 1; - - ++x; - if (l == 0 || x == w) { - l = 128; - CurAndByte++; - if (x == w) { - CurAndByte += ANDPadSize; - - k += PadSize; - x = 0; - } - } - } - } - else if (IconImages[i].Head.BitCount == 24) { - for (; j < Image->SizeOfData; j += 4, k += 3) { - Image->Data[j] = IconImages[i].Data[k]; - Image->Data[j+1] = IconImages[i].Data[k+1]; - Image->Data[j+2] = IconImages[i].Data[k+2]; - Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; - l >>= 1; - - ++x; - if (l == 0 || x == w) { - l = 128; - CurAndByte++; - if (x == w) { - CurAndByte += ANDPadSize; - - k += PadSize; - x = 0; - } - } - } - } - - else if (IconImages[i].Head.BitCount == 32) { - for (; j < Image->SizeOfData; j += 4, k += 4) { - Image->Data[j] = IconImages[i].Data[k]; - Image->Data[j+1] = IconImages[i].Data[k+1]; - Image->Data[j+2] = IconImages[i].Data[k+2]; - - //If the icon has 4 channels, use 4th channel for alpha... - //(for Windows XP style icons with true alpha channel - Image->Data[j+3] = IconImages[i].Data[k+3]; - } - } - } - - - for (i = 0; i < IconDir.Count; i++) { - ifree(IconImages[i].Pal); - ifree(IconImages[i].Data); - ifree(IconImages[i].AND); - } - ifree(IconImages); - ifree(DirEntries); - - return ilFixImage(); - -file_read_error: - if (IconImages) { - for (i = 0; i < IconDir.Count; i++) { - if (IconImages[i].Pal) - ifree(IconImages[i].Pal); - if (IconImages[i].Data) - ifree(IconImages[i].Data); - if (IconImages[i].AND) - ifree(IconImages[i].AND); - } - ifree(IconImages); - } - if (DirEntries) - ifree(DirEntries); - return IL_FALSE; -} - - -#ifndef IL_NO_PNG -// 08-22-2008: Copying a lot of this over from il_png.c for the moment. -// @TODO: Make .ico and .png use the same functions. -png_structp ico_png_ptr = NULL; -png_infop ico_info_ptr = NULL; -ILint ico_color_type; - -#define GAMMA_CORRECTION 1.0 // Doesn't seem to be doing anything... - -ILint ico_readpng_init(); -ILboolean ico_readpng_get_image(ICOIMAGE *Icon, ILdouble display_exponent); -void ico_readpng_cleanup(); -#endif - -ILboolean iLoadIconPNG(ICOIMAGE *Icon) -{ -#ifndef IL_NO_PNG - ILint init; - init = ico_readpng_init(); - if (init) - return IL_FALSE; - if (!ico_readpng_get_image(Icon, GAMMA_CORRECTION)) - return IL_FALSE; - - ico_readpng_cleanup(); - Icon->Head.Size = 0; // Easiest way to tell that this is a PNG. - // In the normal routine, it will not be 0. - - return IL_TRUE; -#else - Icon; - return IL_FALSE; -#endif -} - -#ifndef IL_NO_PNG -static void ico_png_read(png_structp png_ptr, png_bytep data, png_size_t length) -{ - (void)png_ptr; - iread(data, 1, (ILuint)length); - return; -} - - -static void ico_png_error_func(png_structp png_ptr, png_const_charp message) -{ - message; - ilSetError(IL_LIB_PNG_ERROR); - - /* - changed 20040224 - From the libpng docs: - "Errors handled through png_error() are fatal, meaning that png_error() - should never return to its caller. Currently, this is handled via - setjmp() and longjmp()" - */ - //return; - longjmp(png_jmpbuf(png_ptr), 1); -} - -static void ico_png_warn_func(png_structp png_ptr, png_const_charp message) -{ - png_ptr; message; - return; -} - - -ILint ico_readpng_init() -{ - ico_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, ico_png_error_func, ico_png_warn_func); - if (!ico_png_ptr) - return 4; /* out of memory */ - - ico_info_ptr = png_create_info_struct(ico_png_ptr); - if (!ico_info_ptr) { - png_destroy_read_struct(&ico_png_ptr, NULL, NULL); - return 4; /* out of memory */ - } - - - /* we could create a second info struct here (end_info), but it's only - * useful if we want to keep pre- and post-IDAT chunk info separated - * (mainly for PNG-aware image editors and converters) */ - - - /* setjmp() must be called in every function that calls a PNG-reading - * libpng function */ - - if (setjmp(png_jmpbuf(ico_png_ptr))) { - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - return 2; - } - - - png_set_read_fn(ico_png_ptr, NULL, ico_png_read); - png_set_error_fn(ico_png_ptr, NULL, ico_png_error_func, ico_png_warn_func); - -// png_set_sig_bytes(ico_png_ptr, 8); /* we already read the 8 signature bytes */ - - png_read_info(ico_png_ptr, ico_info_ptr); /* read all PNG info up to image data */ - - /* alternatively, could make separate calls to png_get_image_width(), - * etc., but want bit_depth and ico_color_type for later [don't care about - * compression_type and filter_type => NULLs] */ - - /* OK, that's all we need for now; return happy */ - - return 0; -} - - -ILboolean ico_readpng_get_image(ICOIMAGE *Icon, ILdouble display_exponent) -{ - png_bytepp row_pointers = NULL; - png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness - ILdouble screen_gamma = 1.0; - ILuint i, channels; - ILenum format; - png_colorp palette; - ILint num_palette, j, bit_depth; -#if _WIN32 || DJGPP - ILdouble image_gamma; -#endif - - display_exponent; - - /* setjmp() must be called in every function that calls a PNG-reading - * libpng function */ - - if (setjmp(png_jmpbuf(ico_png_ptr))) { - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - return IL_FALSE; - } - - png_get_IHDR(ico_png_ptr, ico_info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, - &bit_depth, &ico_color_type, NULL, NULL, NULL); - - // Expand low-bit-depth grayscale images to 8 bits - if (ico_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { - png_set_expand_gray_1_2_4_to_8(ico_png_ptr); - } - - // Expand RGB images with transparency to full alpha channels - // so the data will be available as RGBA quartets. - // But don't expand paletted images, since we want alpha palettes! - if (png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_tRNS) && !(png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_PLTE))) - png_set_tRNS_to_alpha(ico_png_ptr); - - //refresh information (added 20040224) - png_get_IHDR(ico_png_ptr, ico_info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, - &bit_depth, &ico_color_type, NULL, NULL, NULL); - - if (bit_depth < 8) { // Expanded earlier for grayscale, now take care of palette and rgb - bit_depth = 8; - png_set_packing(ico_png_ptr); - } - - // Perform gamma correction. - // @TODO: Determine if we should call png_set_gamma if image_gamma is 1.0. -#if _WIN32 || DJGPP - screen_gamma = 2.2; - if (png_get_gAMA(ico_png_ptr, ico_info_ptr, &image_gamma)) - png_set_gamma(ico_png_ptr, screen_gamma, image_gamma); -#else - screen_gamma = screen_gamma; -#endif - - //fix endianess -#ifdef __LITTLE_ENDIAN__ - if (bit_depth == 16) - png_set_swap(ico_png_ptr); -#endif - - - png_read_update_info(ico_png_ptr, ico_info_ptr); - channels = (ILint)png_get_channels(ico_png_ptr, ico_info_ptr); - // added 20040224: update ico_color_type so that it has the correct value - // in iLoadPngInternal (globals rule...) - ico_color_type = png_get_color_type(ico_png_ptr, ico_info_ptr); - - // Determine internal format - switch (ico_color_type) - { - case PNG_COLOR_TYPE_PALETTE: - Icon->Head.BitCount = 8; - format = IL_COLOUR_INDEX; - break; - case PNG_COLOR_TYPE_RGB: - Icon->Head.BitCount = 24; - format = IL_RGB; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - Icon->Head.BitCount = 32; - format = IL_RGBA; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - return IL_FALSE; - } - - if (ico_color_type & PNG_COLOR_MASK_COLOR) - png_set_bgr(ico_png_ptr); - - Icon->Head.Width = width; - Icon->Head.Height = height; - Icon->Data = ialloc(width * height * Icon->Head.BitCount / 8); - if (Icon->Data == NULL) - { - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - return IL_FALSE; - } - - // Copy Palette - if (format == IL_COLOUR_INDEX) - { - int chans; - png_bytep trans = NULL; - int num_trans = -1; - if (!png_get_PLTE(ico_png_ptr, ico_info_ptr, &palette, &num_palette)) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - return IL_FALSE; - } - - chans = 4; - - if (png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_tRNS)) { - png_get_tRNS(ico_png_ptr, ico_info_ptr, &trans, &num_trans, NULL); - } - -// @TODO: We may need to keep track of the size of the palette. - Icon->Pal = (ILubyte*)ialloc(num_palette * chans); - - for (j = 0; j < num_palette; ++j) { - Icon->Pal[chans*j + 0] = palette[j].blue; - Icon->Pal[chans*j + 1] = palette[j].green; - Icon->Pal[chans*j + 2] = palette[j].red; - if (trans != NULL) { - if (j < num_trans) - Icon->Pal[chans*j + 3] = trans[j]; - else - Icon->Pal[chans*j + 3] = 255; - } - } - - Icon->AND = NULL; // Transparency information is obtained from libpng. - } - - //allocate row pointers - if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) { - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - return IL_FALSE; - } - - - // Set the individual row_pointers to point at the correct offsets - // Needs to be flipped - for (i = 0; i < height; i++) - row_pointers[height - i - 1] = Icon->Data + i * width * Icon->Head.BitCount / 8; - //row_pointers[i] = Icon->Data + i * width * Icon->Head.BitCount / 8; - - - // Now we can go ahead and just read the whole image - png_read_image(ico_png_ptr, row_pointers); - - /* and we're done! (png_read_end() can be omitted if no processing of - * post-IDAT text/time/etc. is desired) */ - //png_read_end(ico_png_ptr, NULL); - ifree(row_pointers); - - return IL_TRUE; -} - - -void ico_readpng_cleanup() -{ - if (ico_png_ptr && ico_info_ptr) { - png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); - ico_png_ptr = NULL; - ico_info_ptr = NULL; - } -} -#endif//IL_NO_PNG - -#endif//IL_NO_ICO diff --git a/DevIL/src-IL/src/il_icon.cpp b/DevIL/src-IL/src/il_icon.cpp new file mode 100644 index 00000000..fd9475dc --- /dev/null +++ b/DevIL/src-IL/src/il_icon.cpp @@ -0,0 +1,674 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2001-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_icon.c +// +// Description: Reads from a Windows icon (.ico) file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_ICO +#include "il_icon.h" +#ifndef IL_NO_PNG + #include +#endif + +//! Reads an icon file. +ILboolean ilLoadIcon(ILconst_string FileName) +{ + ILHANDLE IconFile; + ILboolean bIcon = IL_FALSE; + + IconFile = iopenr(FileName); + if (IconFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIcon; + } + + bIcon = ilLoadIconF(IconFile); + icloser(IconFile); + + return bIcon; +} + + +//! Reads an already-opened icon file. +ILboolean ilLoadIconF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadIconInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains an icon. +ILboolean ilLoadIconL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadIconInternal(); +} + + +// Internal function used to load the icon. +ILboolean iLoadIconInternal() +{ + ICODIR IconDir; + ICODIRENTRY *DirEntries = NULL; + ICOIMAGE *IconImages = NULL; + ILimage *Image = NULL; + ILint i; + ILuint Size, PadSize, ANDPadSize, j, k, l, m, x, w, CurAndByte, AndBytes; + ILboolean BaseCreated = IL_FALSE; + ILubyte PNGTest[3]; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + IconDir.Reserved = GetLittleShort(); + IconDir.Type = GetLittleShort(); + IconDir.Count = GetLittleShort(); + + if (ieof()) + goto file_read_error; + + DirEntries = (ICODIRENTRY*)ialloc(sizeof(ICODIRENTRY) * IconDir.Count); + IconImages = (ICOIMAGE*)ialloc(sizeof(ICOIMAGE) * IconDir.Count); + if (DirEntries == NULL || IconImages == NULL) { + ifree(DirEntries); + ifree(IconImages); + return IL_FALSE; + } + + // Make it easier for file_read_error. + for (i = 0; i < IconDir.Count; i++) + imemclear(&IconImages[i], sizeof(ICOIMAGE)); + + for (i = 0; i < IconDir.Count; ++i) { + DirEntries[i].Width = (ILubyte)igetc(); + DirEntries[i].Height = (ILubyte)igetc(); + DirEntries[i].NumColours = (ILubyte)igetc(); + DirEntries[i].Reserved = (ILubyte)igetc(); + DirEntries[i].Planes = GetLittleShort(); + DirEntries[i].Bpp = GetLittleShort(); + DirEntries[i].SizeOfData = GetLittleUInt(); + DirEntries[i].Offset = GetLittleUInt(); + + if (ieof()) + goto file_read_error; + } + + for (i = 0; i < IconDir.Count; i++) { + iseek(DirEntries[i].Offset, IL_SEEK_SET); + + // 08-22-2008: Adding test for compressed PNG data + igetc(); // Skip the first character...seems to vary. + iread(PNGTest, 3, 1); + if (!strnicmp((char*)PNGTest, "PNG", 3)) // Characters 'P', 'N', 'G' for PNG header + { +#ifdef IL_NO_PNG + ilSetError(IL_FORMAT_NOT_SUPPORTED); // Cannot handle these without libpng. + goto file_read_error; +#else + iseek(DirEntries[i].Offset, IL_SEEK_SET); + if (!iLoadIconPNG(&IconImages[i])) + goto file_read_error; +#endif + } + else + { + // Need to go back the 4 bytes that were just read. + iseek(DirEntries[i].Offset, IL_SEEK_SET); + + IconImages[i].Head.Size = GetLittleInt(); + IconImages[i].Head.Width = GetLittleInt(); + IconImages[i].Head.Height = GetLittleInt(); + IconImages[i].Head.Planes = GetLittleShort(); + IconImages[i].Head.BitCount = GetLittleShort(); + IconImages[i].Head.Compression = GetLittleInt(); + IconImages[i].Head.SizeImage = GetLittleInt(); + IconImages[i].Head.XPixPerMeter = GetLittleInt(); + IconImages[i].Head.YPixPerMeter = GetLittleInt(); + IconImages[i].Head.ColourUsed = GetLittleInt(); + IconImages[i].Head.ColourImportant = GetLittleInt(); + + if (ieof()) + goto file_read_error; + + if (IconImages[i].Head.BitCount < 8) { + if (IconImages[i].Head.ColourUsed == 0) { + switch (IconImages[i].Head.BitCount) + { + case 1: + IconImages[i].Head.ColourUsed = 2; + break; + case 4: + IconImages[i].Head.ColourUsed = 16; + break; + } + } + IconImages[i].Pal = (ILubyte*)ialloc(IconImages[i].Head.ColourUsed * 4); + if (IconImages[i].Pal == NULL) + goto file_read_error; // @TODO: Rename the label. + if (iread(IconImages[i].Pal, IconImages[i].Head.ColourUsed * 4, 1) != 1) + goto file_read_error; + } + else if (IconImages[i].Head.BitCount == 8) { + IconImages[i].Pal = (ILubyte*)ialloc(256 * 4); + if (IconImages[i].Pal == NULL) + goto file_read_error; + if (iread(IconImages[i].Pal, 1, 256 * 4) != 256*4) + goto file_read_error; + } + else { + IconImages[i].Pal = NULL; + } + + PadSize = (4 - ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4; // Has to be DWORD-aligned. + ANDPadSize = (4 - ((IconImages[i].Head.Width + 7) / 8) % 4) % 4; // AND is 1 bit/pixel + Size = ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8 + PadSize) + * (IconImages[i].Head.Height / 2); + + + IconImages[i].Data = (ILubyte*)ialloc(Size); + if (IconImages[i].Data == NULL) + goto file_read_error; + if (iread(IconImages[i].Data, 1, Size) != Size) + goto file_read_error; + + Size = (((IconImages[i].Head.Width + 7) /8) + ANDPadSize) * (IconImages[i].Head.Height / 2); + IconImages[i].AND = (ILubyte*)ialloc(Size); + if (IconImages[i].AND == NULL) + goto file_read_error; + if (iread(IconImages[i].AND, 1, Size) != Size) + goto file_read_error; + } + } + + + for (i = 0; i < IconDir.Count; i++) { + if (IconImages[i].Head.BitCount != 1 && IconImages[i].Head.BitCount != 4 && + IconImages[i].Head.BitCount != 8 && IconImages[i].Head.BitCount != 24 && + + IconImages[i].Head.BitCount != 32) + continue; + + if (!BaseCreated) { + if (IconImages[i].Head.Size == 0) // PNG compressed icon + ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); + else + ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + Image = iCurImage; + BaseCreated = IL_TRUE; + } + else { + if (IconImages[i].Head.Size == 0) // PNG compressed icon + Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height, 1, 4, 1); + else + Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, 1); + Image = Image->Next; + Image->Format = IL_BGRA; + } + Image->Type = IL_UNSIGNED_BYTE; + + j = 0; k = 0; l = 128; CurAndByte = 0; x = 0; + + w = IconImages[i].Head.Width; + PadSize = (4 - ((w*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4; // Has to be DWORD-aligned. + + ANDPadSize = (4 - ((w + 7) / 8) % 4) % 4; // AND is 1 bit/pixel + AndBytes = (w + 7) / 8; + + if (IconImages[i].Head.BitCount == 1) { + for (; j < Image->SizeOfData; k++) { + for (m = 128; m && x < w; m >>= 1) { + Image->Data[j] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4]; + Image->Data[j+1] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 1]; + Image->Data[j+2] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 2]; + Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; + j += 4; + l >>= 1; + + ++x; + } + if (l == 0 || x == w) { + l = 128; + CurAndByte++; + if (x == w) { + CurAndByte += ANDPadSize; + k += PadSize; + x = 0; + } + + } + } + } + else if (IconImages[i].Head.BitCount == 4) { + for (; j < Image->SizeOfData; j += 8, k++) { + Image->Data[j] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4]; + Image->Data[j+1] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 1]; + Image->Data[j+2] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 2]; + Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; + l >>= 1; + + ++x; + + if(x < w) { + Image->Data[j+4] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4]; + Image->Data[j+5] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 1]; + Image->Data[j+6] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 2]; + Image->Data[j+7] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; + l >>= 1; + + ++x; + + } + + else + + j -= 4; + + + if (l == 0 || x == w) { + l = 128; + CurAndByte++; + if (x == w) { + CurAndByte += ANDPadSize; + + k += PadSize; + x = 0; + } + } + } + } + else if (IconImages[i].Head.BitCount == 8) { + for (; j < Image->SizeOfData; j += 4, k++) { + Image->Data[j] = IconImages[i].Pal[IconImages[i].Data[k] * 4]; + Image->Data[j+1] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 1]; + Image->Data[j+2] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 2]; + if (IconImages[i].AND == NULL) // PNG Palette + { + Image->Data[j+3] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 3]; + } + else + { + Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; + } + l >>= 1; + + ++x; + if (l == 0 || x == w) { + l = 128; + CurAndByte++; + if (x == w) { + CurAndByte += ANDPadSize; + + k += PadSize; + x = 0; + } + } + } + } + else if (IconImages[i].Head.BitCount == 24) { + for (; j < Image->SizeOfData; j += 4, k += 3) { + Image->Data[j] = IconImages[i].Data[k]; + Image->Data[j+1] = IconImages[i].Data[k+1]; + Image->Data[j+2] = IconImages[i].Data[k+2]; + Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255; + l >>= 1; + + ++x; + if (l == 0 || x == w) { + l = 128; + CurAndByte++; + if (x == w) { + CurAndByte += ANDPadSize; + + k += PadSize; + x = 0; + } + } + } + } + + else if (IconImages[i].Head.BitCount == 32) { + for (; j < Image->SizeOfData; j += 4, k += 4) { + Image->Data[j] = IconImages[i].Data[k]; + Image->Data[j+1] = IconImages[i].Data[k+1]; + Image->Data[j+2] = IconImages[i].Data[k+2]; + + //If the icon has 4 channels, use 4th channel for alpha... + //(for Windows XP style icons with true alpha channel + Image->Data[j+3] = IconImages[i].Data[k+3]; + } + } + } + + + for (i = 0; i < IconDir.Count; i++) { + ifree(IconImages[i].Pal); + ifree(IconImages[i].Data); + ifree(IconImages[i].AND); + } + ifree(IconImages); + ifree(DirEntries); + + return ilFixImage(); + +file_read_error: + if (IconImages) { + for (i = 0; i < IconDir.Count; i++) { + if (IconImages[i].Pal) + ifree(IconImages[i].Pal); + if (IconImages[i].Data) + ifree(IconImages[i].Data); + if (IconImages[i].AND) + ifree(IconImages[i].AND); + } + ifree(IconImages); + } + if (DirEntries) + ifree(DirEntries); + return IL_FALSE; +} + + +#ifndef IL_NO_PNG +// 08-22-2008: Copying a lot of this over from il_png.c for the moment. +// @TODO: Make .ico and .png use the same functions. +png_structp ico_png_ptr = NULL; +png_infop ico_info_ptr = NULL; +ILint ico_color_type; + +#define GAMMA_CORRECTION 1.0 // Doesn't seem to be doing anything... + +ILint ico_readpng_init(); +ILboolean ico_readpng_get_image(ICOIMAGE *Icon, ILdouble display_exponent); +void ico_readpng_cleanup(); +#endif + +ILboolean iLoadIconPNG(ICOIMAGE *Icon) +{ +#ifndef IL_NO_PNG + ILint init; + init = ico_readpng_init(); + if (init) + return IL_FALSE; + if (!ico_readpng_get_image(Icon, GAMMA_CORRECTION)) + return IL_FALSE; + + ico_readpng_cleanup(); + Icon->Head.Size = 0; // Easiest way to tell that this is a PNG. + // In the normal routine, it will not be 0. + + return IL_TRUE; +#else + Icon; + return IL_FALSE; +#endif +} + +#ifndef IL_NO_PNG +static void ico_png_read(png_structp png_ptr, png_bytep data, png_size_t length) +{ + (void)png_ptr; + iread(data, 1, (ILuint)length); + return; +} + + +static void ico_png_error_func(png_structp png_ptr, png_const_charp message) +{ + message; + ilSetError(IL_LIB_PNG_ERROR); + + /* + changed 20040224 + From the libpng docs: + "Errors handled through png_error() are fatal, meaning that png_error() + should never return to its caller. Currently, this is handled via + setjmp() and longjmp()" + */ + //return; + longjmp(png_jmpbuf(png_ptr), 1); +} + +static void ico_png_warn_func(png_structp png_ptr, png_const_charp message) +{ + png_ptr; message; + return; +} + + +ILint ico_readpng_init() +{ + ico_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, ico_png_error_func, ico_png_warn_func); + if (!ico_png_ptr) + return 4; /* out of memory */ + + ico_info_ptr = png_create_info_struct(ico_png_ptr); + if (!ico_info_ptr) { + png_destroy_read_struct(&ico_png_ptr, NULL, NULL); + return 4; /* out of memory */ + } + + + /* we could create a second info struct here (end_info), but it's only + * useful if we want to keep pre- and post-IDAT chunk info separated + * (mainly for PNG-aware image editors and converters) */ + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(ico_png_ptr))) { + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + return 2; + } + + + png_set_read_fn(ico_png_ptr, NULL, ico_png_read); + png_set_error_fn(ico_png_ptr, NULL, ico_png_error_func, ico_png_warn_func); + +// png_set_sig_bytes(ico_png_ptr, 8); /* we already read the 8 signature bytes */ + + png_read_info(ico_png_ptr, ico_info_ptr); /* read all PNG info up to image data */ + + /* alternatively, could make separate calls to png_get_image_width(), + * etc., but want bit_depth and ico_color_type for later [don't care about + * compression_type and filter_type => NULLs] */ + + /* OK, that's all we need for now; return happy */ + + return 0; +} + + +ILboolean ico_readpng_get_image(ICOIMAGE *Icon, ILdouble display_exponent) +{ + png_bytepp row_pointers = NULL; + png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness + ILdouble screen_gamma = 1.0; + ILuint i, channels; + ILenum format; + png_colorp palette; + ILint num_palette, j, bit_depth; +#if _WIN32 || DJGPP + ILdouble image_gamma; +#endif + + display_exponent; + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(ico_png_ptr))) { + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + return IL_FALSE; + } + + png_get_IHDR(ico_png_ptr, ico_info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, + &bit_depth, &ico_color_type, NULL, NULL, NULL); + + // Expand low-bit-depth grayscale images to 8 bits + if (ico_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(ico_png_ptr); + } + + // Expand RGB images with transparency to full alpha channels + // so the data will be available as RGBA quartets. + // But don't expand paletted images, since we want alpha palettes! + if (png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_tRNS) && !(png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_PLTE))) + png_set_tRNS_to_alpha(ico_png_ptr); + + //refresh information (added 20040224) + png_get_IHDR(ico_png_ptr, ico_info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, + &bit_depth, &ico_color_type, NULL, NULL, NULL); + + if (bit_depth < 8) { // Expanded earlier for grayscale, now take care of palette and rgb + bit_depth = 8; + png_set_packing(ico_png_ptr); + } + + // Perform gamma correction. + // @TODO: Determine if we should call png_set_gamma if image_gamma is 1.0. +#if _WIN32 || DJGPP + screen_gamma = 2.2; + if (png_get_gAMA(ico_png_ptr, ico_info_ptr, &image_gamma)) + png_set_gamma(ico_png_ptr, screen_gamma, image_gamma); +#else + screen_gamma = screen_gamma; +#endif + + //fix endianess +#ifdef __LITTLE_ENDIAN__ + if (bit_depth == 16) + png_set_swap(ico_png_ptr); +#endif + + + png_read_update_info(ico_png_ptr, ico_info_ptr); + channels = (ILint)png_get_channels(ico_png_ptr, ico_info_ptr); + // added 20040224: update ico_color_type so that it has the correct value + // in iLoadPngInternal (globals rule...) + ico_color_type = png_get_color_type(ico_png_ptr, ico_info_ptr); + + // Determine internal format + switch (ico_color_type) + { + case PNG_COLOR_TYPE_PALETTE: + Icon->Head.BitCount = 8; + format = IL_COLOUR_INDEX; + break; + case PNG_COLOR_TYPE_RGB: + Icon->Head.BitCount = 24; + format = IL_RGB; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + Icon->Head.BitCount = 32; + format = IL_RGBA; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + return IL_FALSE; + } + + if (ico_color_type & PNG_COLOR_MASK_COLOR) + png_set_bgr(ico_png_ptr); + + Icon->Head.Width = width; + Icon->Head.Height = height; + Icon->Data = ialloc(width * height * Icon->Head.BitCount / 8); + if (Icon->Data == NULL) + { + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + return IL_FALSE; + } + + // Copy Palette + if (format == IL_COLOUR_INDEX) + { + int chans; + png_bytep trans = NULL; + int num_trans = -1; + if (!png_get_PLTE(ico_png_ptr, ico_info_ptr, &palette, &num_palette)) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + return IL_FALSE; + } + + chans = 4; + + if (png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_tRNS)) { + png_get_tRNS(ico_png_ptr, ico_info_ptr, &trans, &num_trans, NULL); + } + +// @TODO: We may need to keep track of the size of the palette. + Icon->Pal = (ILubyte*)ialloc(num_palette * chans); + + for (j = 0; j < num_palette; ++j) { + Icon->Pal[chans*j + 0] = palette[j].blue; + Icon->Pal[chans*j + 1] = palette[j].green; + Icon->Pal[chans*j + 2] = palette[j].red; + if (trans != NULL) { + if (j < num_trans) + Icon->Pal[chans*j + 3] = trans[j]; + else + Icon->Pal[chans*j + 3] = 255; + } + } + + Icon->AND = NULL; // Transparency information is obtained from libpng. + } + + //allocate row pointers + if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) { + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + return IL_FALSE; + } + + + // Set the individual row_pointers to point at the correct offsets + // Needs to be flipped + for (i = 0; i < height; i++) + row_pointers[height - i - 1] = Icon->Data + i * width * Icon->Head.BitCount / 8; + //row_pointers[i] = Icon->Data + i * width * Icon->Head.BitCount / 8; + + + // Now we can go ahead and just read the whole image + png_read_image(ico_png_ptr, row_pointers); + + /* and we're done! (png_read_end() can be omitted if no processing of + * post-IDAT text/time/etc. is desired) */ + //png_read_end(ico_png_ptr, NULL); + ifree(row_pointers); + + return IL_TRUE; +} + + +void ico_readpng_cleanup() +{ + if (ico_png_ptr && ico_info_ptr) { + png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL); + ico_png_ptr = NULL; + ico_info_ptr = NULL; + } +} +#endif//IL_NO_PNG + +#endif//IL_NO_ICO diff --git a/DevIL/src-IL/src/il_iff.c b/DevIL/src-IL/src/il_iff.c deleted file mode 100755 index e4ad8070..00000000 --- a/DevIL/src-IL/src/il_iff.c +++ /dev/null @@ -1,479 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Last modified: 03/0/2009 -// -// Filename: src-IL/src/il_iff.c -// -// Description: Reads from an .iff file. Contribution from GAIA: -// http://gaia.fdi.ucm.es/grupo/projects/javy/devzone.html#DevILNotes. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" - -#ifndef IL_NO_IFF - -// Chunk type, data and functions: -typedef struct _iff_chunk { - ILuint tag; - ILuint start; - ILuint size; - ILuint chunkType; -} iff_chunk; - -#define CHUNK_STACK_SIZE (32) -static iff_chunk chunkStack[CHUNK_STACK_SIZE]; -static int chunkDepth = -1; - -iff_chunk iff_begin_read_chunk(); -void iff_end_read_chunk(); -char *iff_read_data(int size); -ILboolean iLoadIffInternal(void); - - -/* Define the IFF tags we are looking for in the file. */ -const ILuint IFF_TAG_CIMG = ('C' << 24) | ('I' << 16) | ('M' << 8) | ('G'); -const ILuint IFF_TAG_FOR4 = ('F' << 24) | ('O' << 16) | ('R' << 8) | ('4'); -const ILuint IFF_TAG_TBHD = ('T' << 24) | ('B' << 16) | ('H' << 8) | ('D'); -const ILuint IFF_TAG_TBMP = ('T' << 24) | ('B' << 16) | ('M' << 8) | ('P'); -const ILuint IFF_TAG_RGBA = ('R' << 24) | ('G' << 16) | ('B' << 8) | ('A'); -const ILuint IFF_TAG_CLPZ = ('C' << 24) | ('L' << 16) | ('P' << 8) | ('Z'); -const ILuint IFF_TAG_ESXY = ('E' << 24) | ('S' << 16) | ('X' << 8) | ('Y'); -const ILuint IFF_TAG_ZBUF = ('Z' << 24) | ('B' << 16) | ('U' << 8) | ('F'); -const ILuint IFF_TAG_BLUR = ('B' << 24) | ('L' << 16) | ('U' << 8) | ('R'); -const ILuint IFF_TAG_BLRT = ('B' << 24) | ('L' << 16) | ('R' << 8) | ('T'); -const ILuint IFF_TAG_HIST = ('H' << 24) | ('I' << 16) | ('S' << 8) | ('T'); - -// Flags -#define RGB_FLAG (1) -#define ALPHA_FLAG (2) -#define ZBUFFER_FLAG (4) - -// Function for decompress the file. -char *iff_decompress_rle(ILuint numBytes, char *compressedData, - ILuint compressedDataSize, - ILuint *compressedStartIndex); - -char *iffReadUncompressedTile(ILushort width, ILushort height, ILbyte depth); -char *iff_decompress_tile_rle(ILushort width, ILushort height, ILushort depth, - char *compressedData, ILuint compressedDataSize); - - -//! Reads an IFF file -ILboolean ilLoadIff(const ILstring FileName) -{ - ILHANDLE iffFile; - ILboolean ret = IL_FALSE; - - iffFile = iopenr(FileName); - if (iffFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return ret; - } - ret = ilLoadIffF(iffFile); - icloser(iffFile); - return ret; -} - - -//! Reads an already-opened IFF file -ILboolean ilLoadIffF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadIffInternal(); - iseek(FirstPos, IL_SEEK_SET); - - // Lbm files can have the .iff extension as well, so if Iff-loading failed, - // try to load it as a Lbm. - if (bRet == IL_FALSE) - return ilLoadIlbmF(File); - - return bRet; -} - - -//! Reads from a memory "lump" that contains an IFF -ILboolean ilLoadIffL(const void *Lump, ILuint Size) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputLump(Lump, Size); - FirstPos = itell(); - bRet = iLoadIffInternal(); - iseek(FirstPos, IL_SEEK_SET); - - // Lbm files can have the .iff extension as well, so if Iff-loading failed, - // try to load it as a Lbm. - if (bRet == IL_FALSE) - return ilLoadIlbmL(Lump, Size); - - return IL_TRUE; -} - -ILboolean iLoadIffInternal(void) -{ - iff_chunk chunkInfo; - - // -- Header info. - ILuint width, height; - ILuint flags, compress; - ILushort tiles; - - ILenum format; - ILubyte bpp; - - ILboolean tileImageDataFound; - - // -- Initialize the top of the chunk stack. - chunkDepth = -1; - - // -- File should begin with a FOR4 chunk of type CIMG - chunkInfo = iff_begin_read_chunk(); - if (chunkInfo.chunkType != IFF_TAG_CIMG) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - - /* - * Read the image header - * OK, we have a FOR4 of type CIMG, look for the following tags - * FVER - * TBHD bitmap header, definition of size, etc. - * AUTH - * DATE - */ - while (1) { - - chunkInfo = iff_begin_read_chunk(); - - // -- Right now, the only info we need about the image is in TBHD - // -- so search this level until we find it. - if( chunkInfo.tag == IFF_TAG_TBHD ) { - // -- Header chunk found - width = GetBigUInt(); - height = GetBigUInt(); - GetBigShort(); // -- Don't support - GetBigShort(); // -- Don't support - flags = GetBigUInt(); - GetBigShort(); // -- Don't support - tiles = GetBigUShort(); - compress = GetBigUInt(); - - iff_end_read_chunk(); - - if( compress > 1 ) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - break; - } else - iff_end_read_chunk(); - } /* END find TBHD while loop */ - - if (!(flags & RGB_FLAG)) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - if (flags & ALPHA_FLAG) { - format = IL_RGBA; bpp = 4; - } else { - format = IL_RGB; bpp = 3; - } - - if (!ilTexImage(width, height, 1, bpp, format, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - tileImageDataFound = IL_FALSE; - - while (!tileImageDataFound) { - ILuint tileImage; - ILuint tileZ; - - chunkInfo = iff_begin_read_chunk(); - - /* - * OK, we have a FOR4 of type TBMP, (embedded FOR4) - * look for the following tags - * RGBA color data, RLE compressed tiles of 32 bbp data - * ZBUF z-buffer data, 32 bit float values - * CLPZ depth map specific, clipping planes, 2 float values - * ESXY depth map specific, eye x-y ratios, 2 float values - * HIST - * VERS - * FOR4 BLUR (twice embedded FOR4) - */ - if (chunkInfo.chunkType != IFF_TAG_TBMP) { - iff_end_read_chunk(); - continue; - } - tileImageDataFound = IL_TRUE; - tileImage = 0; // Si no RGBA, tileImage = tiles... - if (flags & ZBUFFER_FLAG) - tileZ = 0; - else - tileZ = tiles; - - // Read tiles - while ( (tileImage < tiles) || (tileZ < tiles)) { - char *tileData; - ILushort x1, x2, y1, y2, tile_width, tile_height; - ILuint remainingDataSize; - ILushort tile_area; - ILuint tileCompressed; - - chunkInfo = iff_begin_read_chunk(); - if ((chunkInfo.tag != IFF_TAG_RGBA) && (chunkInfo.tag != IFF_TAG_ZBUF)) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - x1 = GetBigUShort(); y1 = GetBigUShort(); - x2 = GetBigUShort(); y2 = GetBigUShort(); - - remainingDataSize = chunkInfo.size - 4*sizeof(ILushort); - tile_width = x2 - x1 + 1; - tile_height = y2 - y1 + 1; - tile_area = tile_width * tile_height; - - if ((ILint)remainingDataSize >= (tile_width * tile_height * bpp)) - tileCompressed = 0; - else - tileCompressed = 1; - - if (chunkInfo.tag == IFF_TAG_RGBA) { - if (tileCompressed) { - char *data = iff_read_data(remainingDataSize); - if (data) { - tileData = iff_decompress_tile_rle(tile_width, tile_height, - bpp, data, remainingDataSize); - ifree(data); - } - } else { - tileData = iffReadUncompressedTile(tile_width, tile_height, bpp); - } - - if (tileData) { - // Dump RGBA data to our data structure - ILushort i; - ILuint base; - base = bpp*(width * y1 + x1); - for (i = 0; i < tile_height; i++) { - memcpy(&iCurImage->Data[base + bpp*i*width], - &tileData[bpp*i*tile_width], - tile_width*bpp*sizeof(char)); - } - ifree(tileData); - tileData = NULL; - - iff_end_read_chunk(); - tileImage++; - } else - return IL_FALSE; - } else if (chunkInfo.tag == IFF_TAG_ZBUF) { - tileZ++; - iff_end_read_chunk(); - } - - } - } - //ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Why was this here? - return ilFixImage(); -} - -/* - * IFF Chunking Routines. - * - */ - -iff_chunk iff_begin_read_chunk() -{ - chunkDepth++; - if (chunkDepth >= CHUNK_STACK_SIZE){ - ilSetError(IL_STACK_OVERFLOW); - return chunkStack[0]; - } - if (chunkDepth < 0) { - ilSetError(IL_STACK_UNDERFLOW); - return chunkStack[0]; - } - - chunkStack[chunkDepth].start = itell(); - chunkStack[chunkDepth].tag = GetBigInt(); - chunkStack[chunkDepth].size = GetBigInt(); - - if (chunkStack[chunkDepth].tag == IFF_TAG_FOR4) { - // -- We have a form, so read the form type tag as well. - chunkStack[chunkDepth].chunkType = GetBigInt(); - } else { - chunkStack[chunkDepth].chunkType = 0; - } - - return chunkStack[chunkDepth]; -} - -void iff_end_read_chunk() -{ - ILuint end; - int part; - - end = chunkStack[chunkDepth].start + chunkStack[chunkDepth].size + 8; - - if (chunkStack[chunkDepth].chunkType != 0) { - end += 4; - } - // Add padding - part = end % 4; - if (part != 0) { - end += 4 - part; - } - - iseek(end, IL_SEEK_SET); - - chunkDepth--; -} - -char * iff_read_data(int size) -{ - char *buffer = ialloc(size * sizeof(char)); - if (buffer == NULL) - return NULL; - - if (iread(buffer, size*sizeof(char), 1) != 1) { - ifree(buffer); - return NULL; - } - - return buffer; -} - -/* - IFF decompress functions -*/ - -char *iffReadUncompressedTile(ILushort width, ILushort height, ILbyte depth) -{ - - char *data = NULL; - char *iniPixel; - char *finPixel; - int i, j; - int tam = width* height * depth * sizeof(char); - - data = ialloc(tam); - if (data == NULL) - return NULL; - - if (iread(data, tam, 1) != 1) { - ifree(data); - return NULL; - } - - iniPixel = data; - for (i = 0; i < tam / depth; i++) { - finPixel = iniPixel + depth; - for (j = 0; j < (depth /2); j++) { - char aux; - aux = *iniPixel; - *(finPixel--) = *iniPixel; - *(iniPixel++) = aux; - } - } - return data; -} - - -char *iff_decompress_tile_rle(ILushort width, ILushort height, ILushort depth, - char *compressedData, ILuint compressedDataSize) -{ - - char *channels[4]; - char *data; - int i, k, row, column; - ILuint compressedStart = 0; - - // Decompress only in RGBA. - if (depth != 4) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return NULL; - } - - for (i = depth-1; i >= 0; --i) { - channels[i] = iff_decompress_rle(width * height, compressedData, - compressedDataSize, &compressedStart); - if (channels[i] == NULL) - return NULL; - } - - // Build all the channels from the decompression into an RGBA array. - data = ialloc(width * height * depth * sizeof(char)); - if (data == NULL) - return NULL; - - for (row = 0; row < height; row++) - for (column = 0; column < width; column++) - for (k = 0; k < depth; k++) - data[depth*(row*width + column) + k] = - channels[k][row*width + column]; - - ifree(channels[0]); ifree(channels[1]); - ifree(channels[2]); ifree(channels[3]); - - return data; -} - -char *iff_decompress_rle(ILuint numBytes, char *compressedData, - ILuint compressedDataSize, - ILuint *compressedStartIndex) -{ - - char *data = ialloc(numBytes * sizeof(char)); - unsigned char nextChar, count; - int i; - ILuint byteCount = 0; - - if (data == NULL) - return NULL; - - memset(data, 0, numBytes*sizeof(char)); - - while (byteCount < numBytes) { - if (*compressedStartIndex >= compressedDataSize) - break; - nextChar = compressedData[*compressedStartIndex]; - (*compressedStartIndex)++; - count = (nextChar & 0x7f) + 1; - if ((byteCount + count) > numBytes) break; - if (nextChar & 0x80) { - // Duplication run - nextChar = compressedData[*compressedStartIndex]; - (*compressedStartIndex)++; - // assert ((byteCount + count) <= numBytes); - for (i = 0; i < count; i++) { - data[byteCount]= nextChar; - byteCount++; - } - } else { - // Verbatim run - for (i = 0; i < count; i++) { - data[byteCount] = compressedData[*compressedStartIndex]; - (*compressedStartIndex)++; - byteCount++; - } - } - //assert(byteCount <= numBytes); - } - - return data; - -} - -#endif //IL_NO_IFF diff --git a/DevIL/src-IL/src/il_iff.cpp b/DevIL/src-IL/src/il_iff.cpp new file mode 100755 index 00000000..e4ad8070 --- /dev/null +++ b/DevIL/src-IL/src/il_iff.cpp @@ -0,0 +1,479 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Last modified: 03/0/2009 +// +// Filename: src-IL/src/il_iff.c +// +// Description: Reads from an .iff file. Contribution from GAIA: +// http://gaia.fdi.ucm.es/grupo/projects/javy/devzone.html#DevILNotes. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" + +#ifndef IL_NO_IFF + +// Chunk type, data and functions: +typedef struct _iff_chunk { + ILuint tag; + ILuint start; + ILuint size; + ILuint chunkType; +} iff_chunk; + +#define CHUNK_STACK_SIZE (32) +static iff_chunk chunkStack[CHUNK_STACK_SIZE]; +static int chunkDepth = -1; + +iff_chunk iff_begin_read_chunk(); +void iff_end_read_chunk(); +char *iff_read_data(int size); +ILboolean iLoadIffInternal(void); + + +/* Define the IFF tags we are looking for in the file. */ +const ILuint IFF_TAG_CIMG = ('C' << 24) | ('I' << 16) | ('M' << 8) | ('G'); +const ILuint IFF_TAG_FOR4 = ('F' << 24) | ('O' << 16) | ('R' << 8) | ('4'); +const ILuint IFF_TAG_TBHD = ('T' << 24) | ('B' << 16) | ('H' << 8) | ('D'); +const ILuint IFF_TAG_TBMP = ('T' << 24) | ('B' << 16) | ('M' << 8) | ('P'); +const ILuint IFF_TAG_RGBA = ('R' << 24) | ('G' << 16) | ('B' << 8) | ('A'); +const ILuint IFF_TAG_CLPZ = ('C' << 24) | ('L' << 16) | ('P' << 8) | ('Z'); +const ILuint IFF_TAG_ESXY = ('E' << 24) | ('S' << 16) | ('X' << 8) | ('Y'); +const ILuint IFF_TAG_ZBUF = ('Z' << 24) | ('B' << 16) | ('U' << 8) | ('F'); +const ILuint IFF_TAG_BLUR = ('B' << 24) | ('L' << 16) | ('U' << 8) | ('R'); +const ILuint IFF_TAG_BLRT = ('B' << 24) | ('L' << 16) | ('R' << 8) | ('T'); +const ILuint IFF_TAG_HIST = ('H' << 24) | ('I' << 16) | ('S' << 8) | ('T'); + +// Flags +#define RGB_FLAG (1) +#define ALPHA_FLAG (2) +#define ZBUFFER_FLAG (4) + +// Function for decompress the file. +char *iff_decompress_rle(ILuint numBytes, char *compressedData, + ILuint compressedDataSize, + ILuint *compressedStartIndex); + +char *iffReadUncompressedTile(ILushort width, ILushort height, ILbyte depth); +char *iff_decompress_tile_rle(ILushort width, ILushort height, ILushort depth, + char *compressedData, ILuint compressedDataSize); + + +//! Reads an IFF file +ILboolean ilLoadIff(const ILstring FileName) +{ + ILHANDLE iffFile; + ILboolean ret = IL_FALSE; + + iffFile = iopenr(FileName); + if (iffFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return ret; + } + ret = ilLoadIffF(iffFile); + icloser(iffFile); + return ret; +} + + +//! Reads an already-opened IFF file +ILboolean ilLoadIffF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadIffInternal(); + iseek(FirstPos, IL_SEEK_SET); + + // Lbm files can have the .iff extension as well, so if Iff-loading failed, + // try to load it as a Lbm. + if (bRet == IL_FALSE) + return ilLoadIlbmF(File); + + return bRet; +} + + +//! Reads from a memory "lump" that contains an IFF +ILboolean ilLoadIffL(const void *Lump, ILuint Size) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputLump(Lump, Size); + FirstPos = itell(); + bRet = iLoadIffInternal(); + iseek(FirstPos, IL_SEEK_SET); + + // Lbm files can have the .iff extension as well, so if Iff-loading failed, + // try to load it as a Lbm. + if (bRet == IL_FALSE) + return ilLoadIlbmL(Lump, Size); + + return IL_TRUE; +} + +ILboolean iLoadIffInternal(void) +{ + iff_chunk chunkInfo; + + // -- Header info. + ILuint width, height; + ILuint flags, compress; + ILushort tiles; + + ILenum format; + ILubyte bpp; + + ILboolean tileImageDataFound; + + // -- Initialize the top of the chunk stack. + chunkDepth = -1; + + // -- File should begin with a FOR4 chunk of type CIMG + chunkInfo = iff_begin_read_chunk(); + if (chunkInfo.chunkType != IFF_TAG_CIMG) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + + /* + * Read the image header + * OK, we have a FOR4 of type CIMG, look for the following tags + * FVER + * TBHD bitmap header, definition of size, etc. + * AUTH + * DATE + */ + while (1) { + + chunkInfo = iff_begin_read_chunk(); + + // -- Right now, the only info we need about the image is in TBHD + // -- so search this level until we find it. + if( chunkInfo.tag == IFF_TAG_TBHD ) { + // -- Header chunk found + width = GetBigUInt(); + height = GetBigUInt(); + GetBigShort(); // -- Don't support + GetBigShort(); // -- Don't support + flags = GetBigUInt(); + GetBigShort(); // -- Don't support + tiles = GetBigUShort(); + compress = GetBigUInt(); + + iff_end_read_chunk(); + + if( compress > 1 ) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + break; + } else + iff_end_read_chunk(); + } /* END find TBHD while loop */ + + if (!(flags & RGB_FLAG)) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + if (flags & ALPHA_FLAG) { + format = IL_RGBA; bpp = 4; + } else { + format = IL_RGB; bpp = 3; + } + + if (!ilTexImage(width, height, 1, bpp, format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + tileImageDataFound = IL_FALSE; + + while (!tileImageDataFound) { + ILuint tileImage; + ILuint tileZ; + + chunkInfo = iff_begin_read_chunk(); + + /* + * OK, we have a FOR4 of type TBMP, (embedded FOR4) + * look for the following tags + * RGBA color data, RLE compressed tiles of 32 bbp data + * ZBUF z-buffer data, 32 bit float values + * CLPZ depth map specific, clipping planes, 2 float values + * ESXY depth map specific, eye x-y ratios, 2 float values + * HIST + * VERS + * FOR4 BLUR (twice embedded FOR4) + */ + if (chunkInfo.chunkType != IFF_TAG_TBMP) { + iff_end_read_chunk(); + continue; + } + tileImageDataFound = IL_TRUE; + tileImage = 0; // Si no RGBA, tileImage = tiles... + if (flags & ZBUFFER_FLAG) + tileZ = 0; + else + tileZ = tiles; + + // Read tiles + while ( (tileImage < tiles) || (tileZ < tiles)) { + char *tileData; + ILushort x1, x2, y1, y2, tile_width, tile_height; + ILuint remainingDataSize; + ILushort tile_area; + ILuint tileCompressed; + + chunkInfo = iff_begin_read_chunk(); + if ((chunkInfo.tag != IFF_TAG_RGBA) && (chunkInfo.tag != IFF_TAG_ZBUF)) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + x1 = GetBigUShort(); y1 = GetBigUShort(); + x2 = GetBigUShort(); y2 = GetBigUShort(); + + remainingDataSize = chunkInfo.size - 4*sizeof(ILushort); + tile_width = x2 - x1 + 1; + tile_height = y2 - y1 + 1; + tile_area = tile_width * tile_height; + + if ((ILint)remainingDataSize >= (tile_width * tile_height * bpp)) + tileCompressed = 0; + else + tileCompressed = 1; + + if (chunkInfo.tag == IFF_TAG_RGBA) { + if (tileCompressed) { + char *data = iff_read_data(remainingDataSize); + if (data) { + tileData = iff_decompress_tile_rle(tile_width, tile_height, + bpp, data, remainingDataSize); + ifree(data); + } + } else { + tileData = iffReadUncompressedTile(tile_width, tile_height, bpp); + } + + if (tileData) { + // Dump RGBA data to our data structure + ILushort i; + ILuint base; + base = bpp*(width * y1 + x1); + for (i = 0; i < tile_height; i++) { + memcpy(&iCurImage->Data[base + bpp*i*width], + &tileData[bpp*i*tile_width], + tile_width*bpp*sizeof(char)); + } + ifree(tileData); + tileData = NULL; + + iff_end_read_chunk(); + tileImage++; + } else + return IL_FALSE; + } else if (chunkInfo.tag == IFF_TAG_ZBUF) { + tileZ++; + iff_end_read_chunk(); + } + + } + } + //ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Why was this here? + return ilFixImage(); +} + +/* + * IFF Chunking Routines. + * + */ + +iff_chunk iff_begin_read_chunk() +{ + chunkDepth++; + if (chunkDepth >= CHUNK_STACK_SIZE){ + ilSetError(IL_STACK_OVERFLOW); + return chunkStack[0]; + } + if (chunkDepth < 0) { + ilSetError(IL_STACK_UNDERFLOW); + return chunkStack[0]; + } + + chunkStack[chunkDepth].start = itell(); + chunkStack[chunkDepth].tag = GetBigInt(); + chunkStack[chunkDepth].size = GetBigInt(); + + if (chunkStack[chunkDepth].tag == IFF_TAG_FOR4) { + // -- We have a form, so read the form type tag as well. + chunkStack[chunkDepth].chunkType = GetBigInt(); + } else { + chunkStack[chunkDepth].chunkType = 0; + } + + return chunkStack[chunkDepth]; +} + +void iff_end_read_chunk() +{ + ILuint end; + int part; + + end = chunkStack[chunkDepth].start + chunkStack[chunkDepth].size + 8; + + if (chunkStack[chunkDepth].chunkType != 0) { + end += 4; + } + // Add padding + part = end % 4; + if (part != 0) { + end += 4 - part; + } + + iseek(end, IL_SEEK_SET); + + chunkDepth--; +} + +char * iff_read_data(int size) +{ + char *buffer = ialloc(size * sizeof(char)); + if (buffer == NULL) + return NULL; + + if (iread(buffer, size*sizeof(char), 1) != 1) { + ifree(buffer); + return NULL; + } + + return buffer; +} + +/* + IFF decompress functions +*/ + +char *iffReadUncompressedTile(ILushort width, ILushort height, ILbyte depth) +{ + + char *data = NULL; + char *iniPixel; + char *finPixel; + int i, j; + int tam = width* height * depth * sizeof(char); + + data = ialloc(tam); + if (data == NULL) + return NULL; + + if (iread(data, tam, 1) != 1) { + ifree(data); + return NULL; + } + + iniPixel = data; + for (i = 0; i < tam / depth; i++) { + finPixel = iniPixel + depth; + for (j = 0; j < (depth /2); j++) { + char aux; + aux = *iniPixel; + *(finPixel--) = *iniPixel; + *(iniPixel++) = aux; + } + } + return data; +} + + +char *iff_decompress_tile_rle(ILushort width, ILushort height, ILushort depth, + char *compressedData, ILuint compressedDataSize) +{ + + char *channels[4]; + char *data; + int i, k, row, column; + ILuint compressedStart = 0; + + // Decompress only in RGBA. + if (depth != 4) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return NULL; + } + + for (i = depth-1; i >= 0; --i) { + channels[i] = iff_decompress_rle(width * height, compressedData, + compressedDataSize, &compressedStart); + if (channels[i] == NULL) + return NULL; + } + + // Build all the channels from the decompression into an RGBA array. + data = ialloc(width * height * depth * sizeof(char)); + if (data == NULL) + return NULL; + + for (row = 0; row < height; row++) + for (column = 0; column < width; column++) + for (k = 0; k < depth; k++) + data[depth*(row*width + column) + k] = + channels[k][row*width + column]; + + ifree(channels[0]); ifree(channels[1]); + ifree(channels[2]); ifree(channels[3]); + + return data; +} + +char *iff_decompress_rle(ILuint numBytes, char *compressedData, + ILuint compressedDataSize, + ILuint *compressedStartIndex) +{ + + char *data = ialloc(numBytes * sizeof(char)); + unsigned char nextChar, count; + int i; + ILuint byteCount = 0; + + if (data == NULL) + return NULL; + + memset(data, 0, numBytes*sizeof(char)); + + while (byteCount < numBytes) { + if (*compressedStartIndex >= compressedDataSize) + break; + nextChar = compressedData[*compressedStartIndex]; + (*compressedStartIndex)++; + count = (nextChar & 0x7f) + 1; + if ((byteCount + count) > numBytes) break; + if (nextChar & 0x80) { + // Duplication run + nextChar = compressedData[*compressedStartIndex]; + (*compressedStartIndex)++; + // assert ((byteCount + count) <= numBytes); + for (i = 0; i < count; i++) { + data[byteCount]= nextChar; + byteCount++; + } + } else { + // Verbatim run + for (i = 0; i < count; i++) { + data[byteCount] = compressedData[*compressedStartIndex]; + (*compressedStartIndex)++; + byteCount++; + } + } + //assert(byteCount <= numBytes); + } + + return data; + +} + +#endif //IL_NO_IFF diff --git a/DevIL/src-IL/src/il_ilbm.c b/DevIL/src-IL/src/il_ilbm.c deleted file mode 100644 index 810383cd..00000000 --- a/DevIL/src-IL/src/il_ilbm.c +++ /dev/null @@ -1,658 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/08/2009 -// -// Filename: src-IL/src/il_ilbm.c -// -// Description: IFF ILBM file (.iff, .ilbm, .lbm) functions -// IFF ILBM loader, ported from SDL_Image library (IMG_lbm.c) -// http://www.libsdl.org/cgi/viewvc.cgi/trunk/SDL_image/IMG_lbm.c?view=markup -// -// Handles Amiga ILBM and PBM images (including .lbm files saved by the PC -// version of dpaint) -// Handles ExtraHalfBright and HAM images. -// -// Adapted from SDL_image by Ben Campbell (http://scumways.com) 2009-02-23 -// -//----------------------------------------------------------------------------- - - -// TODO: sort out the .iff extension confusion: .iff is currently handled by -// Maya IFF/CIMG handler (il_iff.c), but it should defer to this one if -// fileturns out to be an ILBM. I think the best solution would be to -// rename the IFF handler to CIMG, and create a new iff handler to act as -// a front end, passing off to either il_ilbm or il_cimg... -// For now, this handler only handles .lbm and .ilbm extenstions (but -// traditionally, .iff is more common). - -#include "il_internal.h" -#ifndef IL_NO_ILBM -#include - -ILboolean iIsValidIlbm(void); -ILboolean iLoadIlbmInternal(void); -static ILboolean load_ilbm(void); -static int isLBM(void ); - - -ILboolean ilIsValidIlbm(ILconst_string FileName) -{ - ILHANDLE f; - ILboolean bIlbm = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("iff")) && - !iCheckExtension(FileName, IL_TEXT("ilbm")) && - !iCheckExtension(FileName, IL_TEXT("lbm")) && - !iCheckExtension(FileName, IL_TEXT("ham")) ) { - ilSetError(IL_INVALID_EXTENSION); - return bIlbm; - } - - f = iopenr(FileName); - if (f == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIlbm; - } - - bIlbm = ilIsValidIlbmF(f); - icloser(f); - - return bIlbm; -} - - -ILboolean ilIsValidIlbmF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidIlbm(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -ILboolean ilIsValidIlbmL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidIlbm(); -} - - -ILboolean iIsValidIlbm() -{ - return isLBM() ? IL_TRUE:IL_FALSE; -} - - -// Reads a file -ILboolean ilLoadIlbm(ILconst_string FileName) -{ - ILHANDLE IlbmFile; - ILboolean bIlbm = IL_FALSE; - - IlbmFile = iopenr(FileName); - if (IlbmFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIlbm; - } - - bIlbm = ilLoadIlbmF(IlbmFile); - icloser(IlbmFile); - - return bIlbm; -} - - -// Reads an already-opened file -ILboolean ilLoadIlbmF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadIlbmInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -// Reads from a memory "lump" -ILboolean ilLoadIlbmL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadIlbmInternal(); -} - - -ILboolean iLoadIlbmInternal() -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - if (!iIsValidIlbm()) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - if (!load_ilbm() ) - { - return IL_FALSE; - } - - return ilFixImage(); -} - - -/* some defines to allow us to use the SDL_image source in as unmodified form - * as possible, so it'll be easy to diff. Yes, it does look evil, but it's - * really just some local syntactic sugar - most things correspond directly - * to DevIL calls. It's not that bad, honest ;-) - * This will make it _much_ easier to track changes to SDL_Image. - * - BenC - */ - -#define Sint8 ILbyte -#define Sint16 ILshort -#define Sint32 ILint -#define Uint8 ILubyte -#define Uint16 ILushort -#define Uint32 ILuint - -#define SDL_RWops void -#define SDL_RWtell(s) itell() -#define SDL_RWread(s,ptr,size,nmemb) iread(ptr,size,nmemb) -#define SDL_RWseek(s,offset,whence) iseek(offset, IL_ ## whence) - - -/* use different function names to avoid any possible symbol contamination - * (user might also be linking with libSDL) */ -#define SDL_SwapBE32(i) iSDL_SwapBE32(i) -#define SDL_SwapBE16(s) iSDL_SwapBE16(s) -static Uint16 iSDL_SwapBE16( Uint16 s ) - { Uint16 foo = s; iSwapUShort(&foo); return foo; } -static Uint32 iSDL_SwapBE32( Uint32 i ) - { Uint32 foo = i; iSwapUInt(&foo); return foo; } - -/* rest of this file is as unchanged as possible from IMG_lbm.c - BenC */ -/***************************************************************************/ - -/* This is a ILBM image file loading framework - Load IFF pictures, PBM & ILBM packing methods, with or without stencil - Written by Daniel Morais ( Daniel AT Morais DOT com ) in September 2001. - 24 bits ILBM files support added by Marc Le Douarain (http://www.multimania.com/mavati) - in December 2002. - EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain - (http://www.multimania.com/mavati) in December 2003. - Stencil and colorkey fixes by David Raulo (david.raulo AT free DOT fr) in February 2004. - Buffer overflow fix in RLE decompression by David Raulo in January 2008. -*/ - - -#define MAXCOLORS 256 - -/* Structure for an IFF picture ( BMHD = Bitmap Header ) */ - -/* TODO: SDL_Image seems to get away without any struct - * packing... should it be added? */ -typedef struct -{ - Uint16 w, h; /* width & height of the bitmap in pixels */ - Sint16 x, y; /* screen coordinates of the bitmap */ - Uint8 planes; /* number of planes of the bitmap */ - Uint8 mask; /* mask type ( 0 => no mask ) */ - Uint8 tcomp; /* compression type */ - Uint8 pad1; /* dummy value, for padding */ - Uint16 tcolor; /* transparent color */ - Uint8 xAspect, /* pixel aspect ratio */ - yAspect; - Sint16 Lpage; /* width of the screen in pixels */ - Sint16 Hpage; /* height of the screen in pixels */ -} BMHD; - -static int isLBM() -{ - SDL_RWops* src = 0; - int start; - int is_LBM; - Uint8 magic[4+4+4]; - - start = SDL_RWtell(src); - is_LBM = 0; - if ( SDL_RWread( src, magic, sizeof(magic), 1 ) ) - { - if ( !memcmp( magic, "FORM", 4 ) && - ( !memcmp( magic + 8, "PBM ", 4 ) || - !memcmp( magic + 8, "ILBM", 4 ) ) ) - { - is_LBM = 1; - } - } - SDL_RWseek(src, start, SEEK_SET); - return( is_LBM ); -} - -static ILboolean load_ilbm(void) -{ - SDL_RWops* src = 0; - struct { Uint8 r; Uint8 g; Uint8 b; } scratch_pal[MAXCOLORS]; - ILenum format; /* IL_RGB (ham or 24bit) or IL_COLOUR_INDEX */ - - int start; - Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk; - Uint32 size, bytesloaded, nbcolors; - Uint32 i, j, bytesperline, nbplanes, plane, h; - Uint32 remainingbytes; - Uint32 width; - BMHD bmhd; - char *error; - Uint8 flagHAM,flagEHB; - - error = NULL; - MiniBuf = NULL; - - start = SDL_RWtell(src); - if ( !SDL_RWread( src, id, 4, 1 ) ) - { - error="error reading IFF chunk"; - goto done; - } - - /* Should be the size of the file minus 4+4 ( 'FORM'+size ) */ - if ( !SDL_RWread( src, &size, 4, 1 ) ) - { - error="error reading IFF chunk size"; - goto done; - } - - /* As size is not used here, no need to swap it */ - - if ( memcmp( id, "FORM", 4 ) != 0 ) - { - ilSetError(IL_INVALID_FILE_HEADER); - error="not a IFF file"; - goto done; - } - - if ( !SDL_RWread( src, id, 4, 1 ) ) - { - error="error reading IFF chunk"; - goto done; - } - - pbm = 0; - - /* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */ - if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1; - else if ( memcmp( id, "ILBM", 4 ) ) - { - ilSetError(IL_INVALID_FILE_HEADER); - error="not a IFF picture"; - goto done; - } - - nbcolors = 0; - - memset( &bmhd, 0, sizeof( BMHD ) ); - flagHAM = 0; - flagEHB = 0; - - while ( memcmp( id, "BODY", 4 ) != 0 ) - { - if ( !SDL_RWread( src, id, 4, 1 ) ) - { - error="error reading IFF chunk"; - goto done; - } - - if ( !SDL_RWread( src, &size, 4, 1 ) ) - { - error="error reading IFF chunk size"; - goto done; - } - - bytesloaded = 0; - - size = SDL_SwapBE32( size ); - - if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */ - { - if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) ) - { - error="error reading BMHD chunk"; - goto done; - } - - bytesloaded = sizeof( BMHD ); - - bmhd.w = SDL_SwapBE16( bmhd.w ); - bmhd.h = SDL_SwapBE16( bmhd.h ); - bmhd.x = SDL_SwapBE16( bmhd.x ); - bmhd.y = SDL_SwapBE16( bmhd.y ); - bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor ); - bmhd.Lpage = SDL_SwapBE16( bmhd.Lpage ); - bmhd.Hpage = SDL_SwapBE16( bmhd.Hpage ); - } - - if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */ - { - if ( !SDL_RWread( src, &colormap, size, 1 ) ) - { - error="error reading CMAP chunk"; - goto done; - } - - bytesloaded = size; - nbcolors = size / 3; - } - - if ( !memcmp( id, "CAMG", 4 ) ) /* Amiga ViewMode */ - { - Uint32 viewmodes; - if ( !SDL_RWread( src, &viewmodes, sizeof(viewmodes), 1 ) ) - { - error="error reading CAMG chunk"; - goto done; - } - - bytesloaded = size; - viewmodes = SDL_SwapBE32( viewmodes ); - if ( viewmodes & 0x0800 ) - flagHAM = 1; - if ( viewmodes & 0x0080 ) - flagEHB = 1; - } - - if ( memcmp( id, "BODY", 4 ) ) - { - if ( size & 1 ) ++size; /* padding ! */ - size -= bytesloaded; - /* skip the remaining bytes of this chunk */ - if ( size ) SDL_RWseek( src, size, SEEK_CUR ); - } - } - - /* compute some usefull values, based on the bitmap header */ - - width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */ - - bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2; - - nbplanes = bmhd.planes; - - if ( pbm ) /* File format : 'Packed Bitmap' */ - { - bytesperline *= 8; - nbplanes = 1; - } - - if ( bmhd.mask & 1 ) ++nbplanes; /* There is a mask ( 'stencil' ) */ - - /* Allocate memory for a temporary buffer ( used for - decompression/deinterleaving ) */ - - if ( ( MiniBuf = (void *)malloc( bytesperline * nbplanes ) ) == NULL ) - { - ilSetError( IL_OUT_OF_MEMORY ); - error="no enough memory for temporary buffer"; - goto done; - } - - if( bmhd.planes==24 || flagHAM==1 ) { - format = IL_BGR; - } else { - format = IL_COLOUR_INDEX; - } - if( !ilTexImage( width, bmhd.h, 1, (format==IL_COLOUR_INDEX)?1:3, format, IL_UNSIGNED_BYTE, NULL ) ) - goto done; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - -#if 0 /* No transparent colour support in DevIL? (TODO: confirm) */ - if ( bmhd.mask & 2 ) /* There is a transparent color */ - SDL_SetColorKey( Image, SDL_SRCCOLORKEY, bmhd.tcolor ); -#endif - - /* Update palette informations */ - - /* There is no palette in 24 bits ILBM file */ - if ( nbcolors>0 && flagHAM==0 ) - { - int nbrcolorsfinal = 1 << nbplanes; - ptr = &colormap[0]; - - for ( i=0; i (1< remainingbytes ) || !SDL_RWread( src, &color, 1, 1 ) ) - { - if( count>remainingbytes) - ilSetError(IL_ILLEGAL_FILE_VALUE ); - error="error reading BODY chunk"; - goto done; - } - memset( ptr, color, count ); - } - else - { - ++count; - - if ( ( count > remainingbytes ) || !SDL_RWread( src, ptr, count, 1 ) ) - { - if( count>remainingbytes) - ilSetError(IL_ILLEGAL_FILE_VALUE ); - error="error reading BODY chunk"; - goto done; - } - } - - ptr += count; - remainingbytes -= count; - - } while ( remainingbytes > 0 ); - } - else - { - if ( !SDL_RWread( src, ptr, bytesperline, 1 ) ) - { - error="error reading BODY chunk"; - goto done; - } - } - } - - /* One line has been read, store it ! */ - - ptr = ilGetData(); - if ( nbplanes==24 || flagHAM==1 ) - ptr += h * width * 3; - else - ptr += h * width; - - if ( pbm ) /* File format : 'Packed Bitmap' */ - { - memcpy( ptr, MiniBuf, width ); - } - else /* We have to un-interlace the bits ! */ - { - if ( nbplanes!=24 && flagHAM==0 ) - { - size = ( width + 7 ) / 8; - - for ( i=0; i < size; i++ ) - { - memset( ptr, 0, 8 ); - - for ( plane=0; plane < nbplanes; plane++ ) - { - color = *( MiniBuf + i + ( plane * bytesperline ) ); - msk = 0x80; - - for ( j=0; j<8; j++ ) - { - if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j ); - else ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 ); - - msk >>= 1; - } - } - ptr += 8; - } - } - else - { - Uint32 finalcolor = 0; - size = ( width + 7 ) / 8; - /* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */ - /* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */ - for ( i=0; i>(nbplanes-2) ) - { - case 0: /* take direct color from palette */ - finalcolor = colormap[ pixelcolor*3 ] + (colormap[ pixelcolor*3+1 ]<<8) + (colormap[ pixelcolor*3+2 ]<<16); - break; - case 1: /* modify only blue component */ - finalcolor = finalcolor&0x00FFFF; - finalcolor = finalcolor | (pixelcolor<<(16+(10-nbplanes))); - break; - case 2: /* modify only red component */ - finalcolor = finalcolor&0xFFFF00; - finalcolor = finalcolor | pixelcolor<<(10-nbplanes); - break; - case 3: /* modify only green component */ - finalcolor = finalcolor&0xFF00FF; - finalcolor = finalcolor | (pixelcolor<<(8+(10-nbplanes))); - break; - } - } - else - { - finalcolor = pixelcolor; - } -#if defined( __LITTLE_ENDIAN__ ) - { - *ptr++ = (Uint8)(finalcolor>>16); - *ptr++ = (Uint8)(finalcolor>>8); - *ptr++ = (Uint8)(finalcolor); - } -#else - { - *ptr++ = (Uint8)(finalcolor); - *ptr++ = (Uint8)(finalcolor>>8); - *ptr++ = (Uint8)(finalcolor>>16); - } -#endif - maskBit = maskBit>>1; - } - } - } - } - } - -done: - - if ( MiniBuf ) free( MiniBuf ); - - if ( error ) - { - /* fprintf(stderr,"il_ilbm.c: '%s'\n",error); */ - return IL_FALSE; - } - - return IL_TRUE; -} - - - -#endif//IL_NO_ILBM - diff --git a/DevIL/src-IL/src/il_ilbm.cpp b/DevIL/src-IL/src/il_ilbm.cpp new file mode 100644 index 00000000..810383cd --- /dev/null +++ b/DevIL/src-IL/src/il_ilbm.cpp @@ -0,0 +1,658 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/08/2009 +// +// Filename: src-IL/src/il_ilbm.c +// +// Description: IFF ILBM file (.iff, .ilbm, .lbm) functions +// IFF ILBM loader, ported from SDL_Image library (IMG_lbm.c) +// http://www.libsdl.org/cgi/viewvc.cgi/trunk/SDL_image/IMG_lbm.c?view=markup +// +// Handles Amiga ILBM and PBM images (including .lbm files saved by the PC +// version of dpaint) +// Handles ExtraHalfBright and HAM images. +// +// Adapted from SDL_image by Ben Campbell (http://scumways.com) 2009-02-23 +// +//----------------------------------------------------------------------------- + + +// TODO: sort out the .iff extension confusion: .iff is currently handled by +// Maya IFF/CIMG handler (il_iff.c), but it should defer to this one if +// fileturns out to be an ILBM. I think the best solution would be to +// rename the IFF handler to CIMG, and create a new iff handler to act as +// a front end, passing off to either il_ilbm or il_cimg... +// For now, this handler only handles .lbm and .ilbm extenstions (but +// traditionally, .iff is more common). + +#include "il_internal.h" +#ifndef IL_NO_ILBM +#include + +ILboolean iIsValidIlbm(void); +ILboolean iLoadIlbmInternal(void); +static ILboolean load_ilbm(void); +static int isLBM(void ); + + +ILboolean ilIsValidIlbm(ILconst_string FileName) +{ + ILHANDLE f; + ILboolean bIlbm = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("iff")) && + !iCheckExtension(FileName, IL_TEXT("ilbm")) && + !iCheckExtension(FileName, IL_TEXT("lbm")) && + !iCheckExtension(FileName, IL_TEXT("ham")) ) { + ilSetError(IL_INVALID_EXTENSION); + return bIlbm; + } + + f = iopenr(FileName); + if (f == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIlbm; + } + + bIlbm = ilIsValidIlbmF(f); + icloser(f); + + return bIlbm; +} + + +ILboolean ilIsValidIlbmF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidIlbm(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +ILboolean ilIsValidIlbmL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidIlbm(); +} + + +ILboolean iIsValidIlbm() +{ + return isLBM() ? IL_TRUE:IL_FALSE; +} + + +// Reads a file +ILboolean ilLoadIlbm(ILconst_string FileName) +{ + ILHANDLE IlbmFile; + ILboolean bIlbm = IL_FALSE; + + IlbmFile = iopenr(FileName); + if (IlbmFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIlbm; + } + + bIlbm = ilLoadIlbmF(IlbmFile); + icloser(IlbmFile); + + return bIlbm; +} + + +// Reads an already-opened file +ILboolean ilLoadIlbmF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadIlbmInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +// Reads from a memory "lump" +ILboolean ilLoadIlbmL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadIlbmInternal(); +} + + +ILboolean iLoadIlbmInternal() +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + if (!iIsValidIlbm()) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + if (!load_ilbm() ) + { + return IL_FALSE; + } + + return ilFixImage(); +} + + +/* some defines to allow us to use the SDL_image source in as unmodified form + * as possible, so it'll be easy to diff. Yes, it does look evil, but it's + * really just some local syntactic sugar - most things correspond directly + * to DevIL calls. It's not that bad, honest ;-) + * This will make it _much_ easier to track changes to SDL_Image. + * - BenC + */ + +#define Sint8 ILbyte +#define Sint16 ILshort +#define Sint32 ILint +#define Uint8 ILubyte +#define Uint16 ILushort +#define Uint32 ILuint + +#define SDL_RWops void +#define SDL_RWtell(s) itell() +#define SDL_RWread(s,ptr,size,nmemb) iread(ptr,size,nmemb) +#define SDL_RWseek(s,offset,whence) iseek(offset, IL_ ## whence) + + +/* use different function names to avoid any possible symbol contamination + * (user might also be linking with libSDL) */ +#define SDL_SwapBE32(i) iSDL_SwapBE32(i) +#define SDL_SwapBE16(s) iSDL_SwapBE16(s) +static Uint16 iSDL_SwapBE16( Uint16 s ) + { Uint16 foo = s; iSwapUShort(&foo); return foo; } +static Uint32 iSDL_SwapBE32( Uint32 i ) + { Uint32 foo = i; iSwapUInt(&foo); return foo; } + +/* rest of this file is as unchanged as possible from IMG_lbm.c - BenC */ +/***************************************************************************/ + +/* This is a ILBM image file loading framework + Load IFF pictures, PBM & ILBM packing methods, with or without stencil + Written by Daniel Morais ( Daniel AT Morais DOT com ) in September 2001. + 24 bits ILBM files support added by Marc Le Douarain (http://www.multimania.com/mavati) + in December 2002. + EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain + (http://www.multimania.com/mavati) in December 2003. + Stencil and colorkey fixes by David Raulo (david.raulo AT free DOT fr) in February 2004. + Buffer overflow fix in RLE decompression by David Raulo in January 2008. +*/ + + +#define MAXCOLORS 256 + +/* Structure for an IFF picture ( BMHD = Bitmap Header ) */ + +/* TODO: SDL_Image seems to get away without any struct + * packing... should it be added? */ +typedef struct +{ + Uint16 w, h; /* width & height of the bitmap in pixels */ + Sint16 x, y; /* screen coordinates of the bitmap */ + Uint8 planes; /* number of planes of the bitmap */ + Uint8 mask; /* mask type ( 0 => no mask ) */ + Uint8 tcomp; /* compression type */ + Uint8 pad1; /* dummy value, for padding */ + Uint16 tcolor; /* transparent color */ + Uint8 xAspect, /* pixel aspect ratio */ + yAspect; + Sint16 Lpage; /* width of the screen in pixels */ + Sint16 Hpage; /* height of the screen in pixels */ +} BMHD; + +static int isLBM() +{ + SDL_RWops* src = 0; + int start; + int is_LBM; + Uint8 magic[4+4+4]; + + start = SDL_RWtell(src); + is_LBM = 0; + if ( SDL_RWread( src, magic, sizeof(magic), 1 ) ) + { + if ( !memcmp( magic, "FORM", 4 ) && + ( !memcmp( magic + 8, "PBM ", 4 ) || + !memcmp( magic + 8, "ILBM", 4 ) ) ) + { + is_LBM = 1; + } + } + SDL_RWseek(src, start, SEEK_SET); + return( is_LBM ); +} + +static ILboolean load_ilbm(void) +{ + SDL_RWops* src = 0; + struct { Uint8 r; Uint8 g; Uint8 b; } scratch_pal[MAXCOLORS]; + ILenum format; /* IL_RGB (ham or 24bit) or IL_COLOUR_INDEX */ + + int start; + Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk; + Uint32 size, bytesloaded, nbcolors; + Uint32 i, j, bytesperline, nbplanes, plane, h; + Uint32 remainingbytes; + Uint32 width; + BMHD bmhd; + char *error; + Uint8 flagHAM,flagEHB; + + error = NULL; + MiniBuf = NULL; + + start = SDL_RWtell(src); + if ( !SDL_RWread( src, id, 4, 1 ) ) + { + error="error reading IFF chunk"; + goto done; + } + + /* Should be the size of the file minus 4+4 ( 'FORM'+size ) */ + if ( !SDL_RWread( src, &size, 4, 1 ) ) + { + error="error reading IFF chunk size"; + goto done; + } + + /* As size is not used here, no need to swap it */ + + if ( memcmp( id, "FORM", 4 ) != 0 ) + { + ilSetError(IL_INVALID_FILE_HEADER); + error="not a IFF file"; + goto done; + } + + if ( !SDL_RWread( src, id, 4, 1 ) ) + { + error="error reading IFF chunk"; + goto done; + } + + pbm = 0; + + /* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */ + if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1; + else if ( memcmp( id, "ILBM", 4 ) ) + { + ilSetError(IL_INVALID_FILE_HEADER); + error="not a IFF picture"; + goto done; + } + + nbcolors = 0; + + memset( &bmhd, 0, sizeof( BMHD ) ); + flagHAM = 0; + flagEHB = 0; + + while ( memcmp( id, "BODY", 4 ) != 0 ) + { + if ( !SDL_RWread( src, id, 4, 1 ) ) + { + error="error reading IFF chunk"; + goto done; + } + + if ( !SDL_RWread( src, &size, 4, 1 ) ) + { + error="error reading IFF chunk size"; + goto done; + } + + bytesloaded = 0; + + size = SDL_SwapBE32( size ); + + if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */ + { + if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) ) + { + error="error reading BMHD chunk"; + goto done; + } + + bytesloaded = sizeof( BMHD ); + + bmhd.w = SDL_SwapBE16( bmhd.w ); + bmhd.h = SDL_SwapBE16( bmhd.h ); + bmhd.x = SDL_SwapBE16( bmhd.x ); + bmhd.y = SDL_SwapBE16( bmhd.y ); + bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor ); + bmhd.Lpage = SDL_SwapBE16( bmhd.Lpage ); + bmhd.Hpage = SDL_SwapBE16( bmhd.Hpage ); + } + + if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */ + { + if ( !SDL_RWread( src, &colormap, size, 1 ) ) + { + error="error reading CMAP chunk"; + goto done; + } + + bytesloaded = size; + nbcolors = size / 3; + } + + if ( !memcmp( id, "CAMG", 4 ) ) /* Amiga ViewMode */ + { + Uint32 viewmodes; + if ( !SDL_RWread( src, &viewmodes, sizeof(viewmodes), 1 ) ) + { + error="error reading CAMG chunk"; + goto done; + } + + bytesloaded = size; + viewmodes = SDL_SwapBE32( viewmodes ); + if ( viewmodes & 0x0800 ) + flagHAM = 1; + if ( viewmodes & 0x0080 ) + flagEHB = 1; + } + + if ( memcmp( id, "BODY", 4 ) ) + { + if ( size & 1 ) ++size; /* padding ! */ + size -= bytesloaded; + /* skip the remaining bytes of this chunk */ + if ( size ) SDL_RWseek( src, size, SEEK_CUR ); + } + } + + /* compute some usefull values, based on the bitmap header */ + + width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */ + + bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2; + + nbplanes = bmhd.planes; + + if ( pbm ) /* File format : 'Packed Bitmap' */ + { + bytesperline *= 8; + nbplanes = 1; + } + + if ( bmhd.mask & 1 ) ++nbplanes; /* There is a mask ( 'stencil' ) */ + + /* Allocate memory for a temporary buffer ( used for + decompression/deinterleaving ) */ + + if ( ( MiniBuf = (void *)malloc( bytesperline * nbplanes ) ) == NULL ) + { + ilSetError( IL_OUT_OF_MEMORY ); + error="no enough memory for temporary buffer"; + goto done; + } + + if( bmhd.planes==24 || flagHAM==1 ) { + format = IL_BGR; + } else { + format = IL_COLOUR_INDEX; + } + if( !ilTexImage( width, bmhd.h, 1, (format==IL_COLOUR_INDEX)?1:3, format, IL_UNSIGNED_BYTE, NULL ) ) + goto done; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + +#if 0 /* No transparent colour support in DevIL? (TODO: confirm) */ + if ( bmhd.mask & 2 ) /* There is a transparent color */ + SDL_SetColorKey( Image, SDL_SRCCOLORKEY, bmhd.tcolor ); +#endif + + /* Update palette informations */ + + /* There is no palette in 24 bits ILBM file */ + if ( nbcolors>0 && flagHAM==0 ) + { + int nbrcolorsfinal = 1 << nbplanes; + ptr = &colormap[0]; + + for ( i=0; i (1< remainingbytes ) || !SDL_RWread( src, &color, 1, 1 ) ) + { + if( count>remainingbytes) + ilSetError(IL_ILLEGAL_FILE_VALUE ); + error="error reading BODY chunk"; + goto done; + } + memset( ptr, color, count ); + } + else + { + ++count; + + if ( ( count > remainingbytes ) || !SDL_RWread( src, ptr, count, 1 ) ) + { + if( count>remainingbytes) + ilSetError(IL_ILLEGAL_FILE_VALUE ); + error="error reading BODY chunk"; + goto done; + } + } + + ptr += count; + remainingbytes -= count; + + } while ( remainingbytes > 0 ); + } + else + { + if ( !SDL_RWread( src, ptr, bytesperline, 1 ) ) + { + error="error reading BODY chunk"; + goto done; + } + } + } + + /* One line has been read, store it ! */ + + ptr = ilGetData(); + if ( nbplanes==24 || flagHAM==1 ) + ptr += h * width * 3; + else + ptr += h * width; + + if ( pbm ) /* File format : 'Packed Bitmap' */ + { + memcpy( ptr, MiniBuf, width ); + } + else /* We have to un-interlace the bits ! */ + { + if ( nbplanes!=24 && flagHAM==0 ) + { + size = ( width + 7 ) / 8; + + for ( i=0; i < size; i++ ) + { + memset( ptr, 0, 8 ); + + for ( plane=0; plane < nbplanes; plane++ ) + { + color = *( MiniBuf + i + ( plane * bytesperline ) ); + msk = 0x80; + + for ( j=0; j<8; j++ ) + { + if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j ); + else ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 ); + + msk >>= 1; + } + } + ptr += 8; + } + } + else + { + Uint32 finalcolor = 0; + size = ( width + 7 ) / 8; + /* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */ + /* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */ + for ( i=0; i>(nbplanes-2) ) + { + case 0: /* take direct color from palette */ + finalcolor = colormap[ pixelcolor*3 ] + (colormap[ pixelcolor*3+1 ]<<8) + (colormap[ pixelcolor*3+2 ]<<16); + break; + case 1: /* modify only blue component */ + finalcolor = finalcolor&0x00FFFF; + finalcolor = finalcolor | (pixelcolor<<(16+(10-nbplanes))); + break; + case 2: /* modify only red component */ + finalcolor = finalcolor&0xFFFF00; + finalcolor = finalcolor | pixelcolor<<(10-nbplanes); + break; + case 3: /* modify only green component */ + finalcolor = finalcolor&0xFF00FF; + finalcolor = finalcolor | (pixelcolor<<(8+(10-nbplanes))); + break; + } + } + else + { + finalcolor = pixelcolor; + } +#if defined( __LITTLE_ENDIAN__ ) + { + *ptr++ = (Uint8)(finalcolor>>16); + *ptr++ = (Uint8)(finalcolor>>8); + *ptr++ = (Uint8)(finalcolor); + } +#else + { + *ptr++ = (Uint8)(finalcolor); + *ptr++ = (Uint8)(finalcolor>>8); + *ptr++ = (Uint8)(finalcolor>>16); + } +#endif + maskBit = maskBit>>1; + } + } + } + } + } + +done: + + if ( MiniBuf ) free( MiniBuf ); + + if ( error ) + { + /* fprintf(stderr,"il_ilbm.c: '%s'\n",error); */ + return IL_FALSE; + } + + return IL_TRUE; +} + + + +#endif//IL_NO_ILBM + diff --git a/DevIL/src-IL/src/il_internal.c b/DevIL/src-IL/src/il_internal.c deleted file mode 100644 index 35fe9391..00000000 --- a/DevIL/src-IL/src/il_internal.c +++ /dev/null @@ -1,271 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 11/08/2008 -// -// Filename: src-IL/src/il_internal.c -// -// Description: Internal stuff for DevIL -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include -#include - - -ILimage *iCurImage = NULL; - - -/* Siigron: added this for Linux... a #define should work, but for some reason - it doesn't (anyone who knows why?) */ -#if !_WIN32 || (_WIN32 && __GNUC__) // Cygwin - int stricmp(const char *src1, const char *src2) - { - return strcasecmp(src1, src2); - } - int strnicmp(const char *src1, const char *src2, size_t max) - { - return strncasecmp(src1, src2, max); - } -#elif _WIN32_WCE - int stricmp(const char *src1, const char *src2) - { - return _stricmp(src1, src2); - } - int strnicmp(const char *src1, const char *src2, size_t max) - { - return _strnicmp(src1, src2, max); - } -#endif /* _WIN32 */ - -#ifdef _WIN32_WCE - char *strdup(const char *src) - { - return _strdup(src); - } -#endif//_WIN32_WCE - - -#ifdef _UNICODE - int iStrCmp(ILconst_string src1, ILconst_string src2) - { - return wcsicmp(src1, src2); - } -#else - int iStrCmp(ILconst_string src1, ILconst_string src2) - { - return stricmp(src1, src2); - } -#endif - - -//! Glut's portability.txt says to use this... -ILstring ilStrDup(ILconst_string Str) -{ - ILstring copy; - - copy = (ILstring)ialloc((ilStrLen(Str) + 1) * sizeof(ILchar)); - if (copy == NULL) - return NULL; - iStrCpy(copy, Str); - return copy; -} - - -// Because MSVC++'s version is too stupid to check for NULL... -ILuint ilStrLen(ILconst_string Str) -{ - ILconst_string eos = Str; - - if (Str == NULL) - return 0; - - while (*eos++); - - return((int)(eos - Str - 1)); -} - - -// Because MSVC++'s version is too stupid to check for NULL... -// Passing NULL to strlen will definitely cause a crash. -ILuint ilCharStrLen(const char *Str) -{ - const char *eos = Str; - - if (Str == NULL) - return 0; - - while (*eos++); - - return((int)(eos - Str - 1)); -} - - -// Simple function to test if a filename has a given extension, disregarding case -ILboolean iCheckExtension(ILconst_string Arg, ILconst_string Ext) -{ - ILboolean PeriodFound = IL_FALSE; - ILint i, Len; - ILstring Argu = (ILstring)Arg; - - if (Arg == NULL || Ext == NULL || !ilStrLen(Arg) || !ilStrLen(Ext)) // if not a good filename/extension, exit early - return IL_FALSE; - - Len = ilStrLen(Arg); - Argu += Len; // start at the end - - for (i = Len; i >= 0; i--) { - if (*Argu == '.') { // try to find a period - PeriodFound = IL_TRUE; - break; - } - Argu--; - } - - if (!PeriodFound) // if no period, no extension - return IL_FALSE; - - if (!iStrCmp(Argu+1, Ext)) // extension and ext match? - return IL_TRUE; - - return IL_FALSE; // if all else fails, return IL_FALSE -} - - -ILstring iGetExtension(ILconst_string FileName) -{ - ILboolean PeriodFound = IL_FALSE; - ILstring Ext = (ILstring)FileName; - ILint i, Len = ilStrLen(FileName); - - if (FileName == NULL || !Len) // if not a good filename/extension, exit early - return NULL; - - Ext += Len; // start at the end - - for (i = Len; i >= 0; i--) { - if (*Ext == '.') { // try to find a period - PeriodFound = IL_TRUE; - break; - } - Ext--; - } - - if (!PeriodFound) // if no period, no extension - return NULL; - - return Ext+1; -} - - -// Checks if the file exists -ILboolean iFileExists(ILconst_string FileName) -{ -#if (!defined(_UNICODE) || !defined(_WIN32)) - FILE *CheckFile = fopen(FileName, "rb"); -#else // Windows uses _wfopen instead. - FILE *CheckFile = _wfopen(FileName, L"rb"); -#endif//_UNICODE - - if (CheckFile) { - fclose(CheckFile); - return IL_TRUE; - } - return IL_FALSE; -} - - -// Last time I tried, MSVC++'s fgets() was really really screwy -ILbyte *iFgets(char *buffer, ILuint maxlen) -{ - ILuint counter = 0; - ILint temp = '\0'; - - while ((temp = igetc()) && temp != '\n' && temp != IL_EOF && counter < maxlen) { - buffer[counter] = temp; - counter++; - } - buffer[counter] = '\0'; - - if (temp == IL_EOF && counter == 0) // Only return NULL if no data was "got". - return NULL; - - return (ILbyte*)buffer; -} - - -// A fast integer squareroot, completely accurate for x < 289. -// Taken from http://atoms.org.uk/sqrt/ -// There is also a version that is accurate for all integers -// < 2^31, if we should need it - -static int table[] = { - 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, - 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, - 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, - 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, - 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157, - 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, - 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, - 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, - 189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197, - 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206, - 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215, - 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223, - 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231, - 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, - 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, - 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, - 253, 254, 254, 255 -}; - -int iSqrt(int x) { - if (x >= 0x10000) { - if (x >= 0x1000000) { - if (x >= 0x10000000) { - if (x >= 0x40000000) { - return (table[x >> 24] << 8); - } else { - return (table[x >> 22] << 7); - } - } else if (x >= 0x4000000) { - return (table[x >> 20] << 6); - } else { - return (table[x >> 18] << 5); - } - } else if (x >= 0x100000) { - if (x >= 0x400000) { - return (table[x >> 16] << 4); - } else { - return (table[x >> 14] << 3); - } - } else if (x >= 0x40000) { - return (table[x >> 12] << 2); - } else { - return (table[x >> 10] << 1); - } - } else if (x >= 0x100) { - if (x >= 0x1000) { - if (x >= 0x4000) { - return (table[x >> 8]); - } else { - return (table[x >> 6] >> 1); - } - } else if (x >= 0x400) { - return (table[x >> 4] >> 2); - } else { - return (table[x >> 2] >> 3); - } - } else if (x >= 0) { - return table[x] >> 4; - } - - //hm, x was negative.... - return -1; -} - diff --git a/DevIL/src-IL/src/il_internal.cpp b/DevIL/src-IL/src/il_internal.cpp new file mode 100644 index 00000000..35fe9391 --- /dev/null +++ b/DevIL/src-IL/src/il_internal.cpp @@ -0,0 +1,271 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 11/08/2008 +// +// Filename: src-IL/src/il_internal.c +// +// Description: Internal stuff for DevIL +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include +#include + + +ILimage *iCurImage = NULL; + + +/* Siigron: added this for Linux... a #define should work, but for some reason + it doesn't (anyone who knows why?) */ +#if !_WIN32 || (_WIN32 && __GNUC__) // Cygwin + int stricmp(const char *src1, const char *src2) + { + return strcasecmp(src1, src2); + } + int strnicmp(const char *src1, const char *src2, size_t max) + { + return strncasecmp(src1, src2, max); + } +#elif _WIN32_WCE + int stricmp(const char *src1, const char *src2) + { + return _stricmp(src1, src2); + } + int strnicmp(const char *src1, const char *src2, size_t max) + { + return _strnicmp(src1, src2, max); + } +#endif /* _WIN32 */ + +#ifdef _WIN32_WCE + char *strdup(const char *src) + { + return _strdup(src); + } +#endif//_WIN32_WCE + + +#ifdef _UNICODE + int iStrCmp(ILconst_string src1, ILconst_string src2) + { + return wcsicmp(src1, src2); + } +#else + int iStrCmp(ILconst_string src1, ILconst_string src2) + { + return stricmp(src1, src2); + } +#endif + + +//! Glut's portability.txt says to use this... +ILstring ilStrDup(ILconst_string Str) +{ + ILstring copy; + + copy = (ILstring)ialloc((ilStrLen(Str) + 1) * sizeof(ILchar)); + if (copy == NULL) + return NULL; + iStrCpy(copy, Str); + return copy; +} + + +// Because MSVC++'s version is too stupid to check for NULL... +ILuint ilStrLen(ILconst_string Str) +{ + ILconst_string eos = Str; + + if (Str == NULL) + return 0; + + while (*eos++); + + return((int)(eos - Str - 1)); +} + + +// Because MSVC++'s version is too stupid to check for NULL... +// Passing NULL to strlen will definitely cause a crash. +ILuint ilCharStrLen(const char *Str) +{ + const char *eos = Str; + + if (Str == NULL) + return 0; + + while (*eos++); + + return((int)(eos - Str - 1)); +} + + +// Simple function to test if a filename has a given extension, disregarding case +ILboolean iCheckExtension(ILconst_string Arg, ILconst_string Ext) +{ + ILboolean PeriodFound = IL_FALSE; + ILint i, Len; + ILstring Argu = (ILstring)Arg; + + if (Arg == NULL || Ext == NULL || !ilStrLen(Arg) || !ilStrLen(Ext)) // if not a good filename/extension, exit early + return IL_FALSE; + + Len = ilStrLen(Arg); + Argu += Len; // start at the end + + for (i = Len; i >= 0; i--) { + if (*Argu == '.') { // try to find a period + PeriodFound = IL_TRUE; + break; + } + Argu--; + } + + if (!PeriodFound) // if no period, no extension + return IL_FALSE; + + if (!iStrCmp(Argu+1, Ext)) // extension and ext match? + return IL_TRUE; + + return IL_FALSE; // if all else fails, return IL_FALSE +} + + +ILstring iGetExtension(ILconst_string FileName) +{ + ILboolean PeriodFound = IL_FALSE; + ILstring Ext = (ILstring)FileName; + ILint i, Len = ilStrLen(FileName); + + if (FileName == NULL || !Len) // if not a good filename/extension, exit early + return NULL; + + Ext += Len; // start at the end + + for (i = Len; i >= 0; i--) { + if (*Ext == '.') { // try to find a period + PeriodFound = IL_TRUE; + break; + } + Ext--; + } + + if (!PeriodFound) // if no period, no extension + return NULL; + + return Ext+1; +} + + +// Checks if the file exists +ILboolean iFileExists(ILconst_string FileName) +{ +#if (!defined(_UNICODE) || !defined(_WIN32)) + FILE *CheckFile = fopen(FileName, "rb"); +#else // Windows uses _wfopen instead. + FILE *CheckFile = _wfopen(FileName, L"rb"); +#endif//_UNICODE + + if (CheckFile) { + fclose(CheckFile); + return IL_TRUE; + } + return IL_FALSE; +} + + +// Last time I tried, MSVC++'s fgets() was really really screwy +ILbyte *iFgets(char *buffer, ILuint maxlen) +{ + ILuint counter = 0; + ILint temp = '\0'; + + while ((temp = igetc()) && temp != '\n' && temp != IL_EOF && counter < maxlen) { + buffer[counter] = temp; + counter++; + } + buffer[counter] = '\0'; + + if (temp == IL_EOF && counter == 0) // Only return NULL if no data was "got". + return NULL; + + return (ILbyte*)buffer; +} + + +// A fast integer squareroot, completely accurate for x < 289. +// Taken from http://atoms.org.uk/sqrt/ +// There is also a version that is accurate for all integers +// < 2^31, if we should need it + +static int table[] = { + 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, + 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, + 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102, + 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145, + 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157, + 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, + 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178, + 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, + 189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197, + 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206, + 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215, + 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223, + 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231, + 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, + 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, + 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, + 253, 254, 254, 255 +}; + +int iSqrt(int x) { + if (x >= 0x10000) { + if (x >= 0x1000000) { + if (x >= 0x10000000) { + if (x >= 0x40000000) { + return (table[x >> 24] << 8); + } else { + return (table[x >> 22] << 7); + } + } else if (x >= 0x4000000) { + return (table[x >> 20] << 6); + } else { + return (table[x >> 18] << 5); + } + } else if (x >= 0x100000) { + if (x >= 0x400000) { + return (table[x >> 16] << 4); + } else { + return (table[x >> 14] << 3); + } + } else if (x >= 0x40000) { + return (table[x >> 12] << 2); + } else { + return (table[x >> 10] << 1); + } + } else if (x >= 0x100) { + if (x >= 0x1000) { + if (x >= 0x4000) { + return (table[x >> 8]); + } else { + return (table[x >> 6] >> 1); + } + } else if (x >= 0x400) { + return (table[x >> 4] >> 2); + } else { + return (table[x >> 2] >> 3); + } + } else if (x >= 0) { + return table[x] >> 4; + } + + //hm, x was negative.... + return -1; +} + diff --git a/DevIL/src-IL/src/il_io.c b/DevIL/src-IL/src/il_io.c deleted file mode 100644 index d5ce3ae5..00000000 --- a/DevIL/src-IL/src/il_io.c +++ /dev/null @@ -1,2698 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_io.c -// -// Description: Determines image types and loads/saves images -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#include "il_register.h" -#include "il_pal.h" -#include - - -// Returns a widened version of a string. -// Make sure to free this after it is used. Code help from -// https://buildsecurityin.us-cert.gov/daisy/bsi-rules/home/g1/769-BSI.html -#if defined(_UNICODE) -wchar_t *WideFromMultiByte(const char *Multi) -{ - ILint Length; - wchar_t *Temp; - - Length = (ILint)mbstowcs(NULL, (const char*)Multi, 0) + 1; // note error return of -1 is possible - if (Length == 0) { - ilSetError(IL_INVALID_PARAM); - return NULL; - } - if (Length > ULONG_MAX/sizeof(wchar_t)) { - ilSetError(IL_INTERNAL_ERROR); - return NULL; - } - Temp = (wchar_t*)ialloc(Length * sizeof(wchar_t)); - mbstowcs(Temp, (const char*)Multi, Length); - - return Temp; -} -#endif - - -ILenum ILAPIENTRY ilTypeFromExt(ILconst_string FileName) -{ - ILenum Type; - ILstring Ext; - - if (FileName == NULL || ilStrLen(FileName) < 1) { - ilSetError(IL_INVALID_PARAM); - return IL_TYPE_UNKNOWN; - } - - Ext = iGetExtension(FileName); - //added 2003-08-31: fix sf bug 789535 - if (Ext == NULL) { - return IL_TYPE_UNKNOWN; - } - - if (!iStrCmp(Ext, IL_TEXT("tga")) || !iStrCmp(Ext, IL_TEXT("vda")) || - !iStrCmp(Ext, IL_TEXT("icb")) || !iStrCmp(Ext, IL_TEXT("vst"))) - Type = IL_TGA; - else if (!iStrCmp(Ext, IL_TEXT("jpg")) || !iStrCmp(Ext, IL_TEXT("jpe")) || - !iStrCmp(Ext, IL_TEXT("jpeg")) || !iStrCmp(Ext, IL_TEXT("jif")) || !iStrCmp(Ext, IL_TEXT("jfif"))) - Type = IL_JPG; - else if (!iStrCmp(Ext, IL_TEXT("jp2")) || !iStrCmp(Ext, IL_TEXT("jpx")) || - !iStrCmp(Ext, IL_TEXT("j2k")) || !iStrCmp(Ext, IL_TEXT("j2c"))) - Type = IL_JP2; - else if (!iStrCmp(Ext, IL_TEXT("dds"))) - Type = IL_DDS; - else if (!iStrCmp(Ext, IL_TEXT("png"))) - Type = IL_PNG; - else if (!iStrCmp(Ext, IL_TEXT("bmp")) || !iStrCmp(Ext, IL_TEXT("dib"))) - Type = IL_BMP; - else if (!iStrCmp(Ext, IL_TEXT("gif"))) - Type = IL_GIF; - else if (!iStrCmp(Ext, IL_TEXT("blp"))) - Type = IL_BLP; - else if (!iStrCmp(Ext, IL_TEXT("cut"))) - Type = IL_CUT; - else if (!iStrCmp(Ext, IL_TEXT("dcm")) || !iStrCmp(Ext, IL_TEXT("dicom"))) - Type = IL_DICOM; - else if (!iStrCmp(Ext, IL_TEXT("dpx"))) - Type = IL_DPX; - else if (!iStrCmp(Ext, IL_TEXT("exr"))) - Type = IL_EXR; - else if (!iStrCmp(Ext, IL_TEXT("fit")) || !iStrCmp(Ext, IL_TEXT("fits"))) - Type = IL_FITS; - else if (!iStrCmp(Ext, IL_TEXT("ftx"))) - Type = IL_FTX; - else if (!iStrCmp(Ext, IL_TEXT("hdr"))) - Type = IL_HDR; - else if (!iStrCmp(Ext, IL_TEXT("iff"))) - Type = IL_IFF; - else if (!iStrCmp(Ext, IL_TEXT("ilbm")) || !iStrCmp(Ext, IL_TEXT("lbm")) || - !iStrCmp(Ext, IL_TEXT("ham"))) - Type = IL_ILBM; - else if (!iStrCmp(Ext, IL_TEXT("ico")) || !iStrCmp(Ext, IL_TEXT("cur"))) - Type = IL_ICO; - else if (!iStrCmp(Ext, IL_TEXT("icns"))) - Type = IL_ICNS; - else if (!iStrCmp(Ext, IL_TEXT("iwi"))) - Type = IL_IWI; - else if (!iStrCmp(Ext, IL_TEXT("iwi"))) - Type = IL_IWI; - else if (!iStrCmp(Ext, IL_TEXT("jng"))) - Type = IL_JNG; - else if (!iStrCmp(Ext, IL_TEXT("ktx"))) - Type = IL_KTX; - else if (!iStrCmp(Ext, IL_TEXT("lif"))) - Type = IL_LIF; - else if (!iStrCmp(Ext, IL_TEXT("mdl"))) - Type = IL_MDL; - else if (!iStrCmp(Ext, IL_TEXT("mng")) || !iStrCmp(Ext, IL_TEXT("jng"))) - Type = IL_MNG; - else if (!iStrCmp(Ext, IL_TEXT("mp3"))) - Type = IL_MP3; - else if (!iStrCmp(Ext, IL_TEXT("pcd"))) - Type = IL_PCD; - else if (!iStrCmp(Ext, IL_TEXT("pcx"))) - Type = IL_PCX; - else if (!iStrCmp(Ext, IL_TEXT("pic"))) - Type = IL_PIC; - else if (!iStrCmp(Ext, IL_TEXT("pix"))) - Type = IL_PIX; - else if (!iStrCmp(Ext, IL_TEXT("pbm")) || !iStrCmp(Ext, IL_TEXT("pgm")) || - !iStrCmp(Ext, IL_TEXT("pnm")) || !iStrCmp(Ext, IL_TEXT("ppm"))) - Type = IL_PNM; - else if (!iStrCmp(Ext, IL_TEXT("psd")) || !iStrCmp(Ext, IL_TEXT("pdd"))) - Type = IL_PSD; - else if (!iStrCmp(Ext, IL_TEXT("psp"))) - Type = IL_PSP; - else if (!iStrCmp(Ext, IL_TEXT("pxr"))) - Type = IL_PXR; - else if (!iStrCmp(Ext, IL_TEXT("rot"))) - Type = IL_ROT; - else if (!iStrCmp(Ext, IL_TEXT("sgi")) || !iStrCmp(Ext, IL_TEXT("bw")) || - !iStrCmp(Ext, IL_TEXT("rgb")) || !iStrCmp(Ext, IL_TEXT("rgba"))) - Type = IL_SGI; - else if (!iStrCmp(Ext, IL_TEXT("sun")) || !iStrCmp(Ext, IL_TEXT("ras")) || - !iStrCmp(Ext, IL_TEXT("rs")) || !iStrCmp(Ext, IL_TEXT("im1")) || - !iStrCmp(Ext, IL_TEXT("im8")) || !iStrCmp(Ext, IL_TEXT("im24")) || - !iStrCmp(Ext, IL_TEXT("im32"))) - Type = IL_SUN; - else if (!iStrCmp(Ext, IL_TEXT("texture"))) - Type = IL_TEXTURE; - else if (!iStrCmp(Ext, IL_TEXT("tif")) || !iStrCmp(Ext, IL_TEXT("tiff"))) - Type = IL_TIF; - else if (!iStrCmp(Ext, IL_TEXT("tpl"))) - Type = IL_TPL; - else if (!iStrCmp(Ext, IL_TEXT("utx"))) - Type = IL_UTX; - else if (!iStrCmp(Ext, IL_TEXT("vtf"))) - Type = IL_VTF; - else if (!iStrCmp(Ext, IL_TEXT("wal"))) - Type = IL_WAL; - else if (!iStrCmp(Ext, IL_TEXT("wbmp"))) - Type = IL_WBMP; - else if (!iStrCmp(Ext, IL_TEXT("wdp")) || !iStrCmp(Ext, IL_TEXT("hdp"))) - Type = IL_WDP; - else if (!iStrCmp(Ext, IL_TEXT("xpm"))) - Type = IL_XPM; - else - Type = IL_TYPE_UNKNOWN; - - return Type; -} - - -//changed 2003-09-17 to ILAPIENTRY -ILenum ILAPIENTRY ilDetermineType(ILconst_string FileName) -{ - ILHANDLE File; - ILenum Type; - - if (FileName == NULL) - return IL_TYPE_UNKNOWN; - - File = iopenr(FileName); - if (File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - Type = ilDetermineTypeF(File); - icloser(File); - - return Type; -} - - -ILenum ILAPIENTRY ilDetermineTypeF(ILHANDLE File) -{ - if (File == NULL) - return IL_TYPE_UNKNOWN; - - #ifndef IL_NO_JPG - if (ilIsValidJpegF(File)) - return IL_JPG; - #endif - - #ifndef IL_NO_DDS - if (ilIsValidDdsF(File)) - return IL_DDS; - #endif - - #ifndef IL_NO_PNG - if (ilIsValidPngF(File)) - return IL_PNG; - #endif - - #ifndef IL_NO_BMP - if (ilIsValidBmpF(File)) - return IL_BMP; - #endif - - #ifndef IL_NO_EXR - if (ilIsValidExrF(File)) - return IL_EXR; - #endif - - #ifndef IL_NO_GIF - if (ilIsValidGifF(File)) - return IL_GIF; - #endif - - #ifndef IL_NO_HDR - if (ilIsValidHdrF(File)) - return IL_HDR; - #endif - - #ifndef IL_NO_ICNS - if (ilIsValidIcnsF(File)) - return IL_ICNS; - #endif - - #ifndef IL_NO_ILBM - if (ilIsValidIlbmF(File)) - return IL_ILBM; - #endif - - #ifndef IL_NO_IWI - if (ilIsValidIwiF(File)) - return IL_IWI; - #endif - - #ifndef IL_NO_JP2 - if (ilIsValidJp2F(File)) - return IL_JP2; - #endif - - #ifndef IL_NO_KTX - if (ilIsValidKtxF(File)) - return IL_KTX; - #endif - - #ifndef IL_NO_LIF - if (ilIsValidLifF(File)) - return IL_LIF; - #endif - - #ifndef IL_NO_MDL - if (ilIsValidMdlF(File)) - return IL_MDL; - #endif - - #ifndef IL_NO_MDL - if (ilIsValidMp3F(File)) - return IL_MP3; - #endif - - #ifndef IL_NO_PCX - if (ilIsValidPcxF(File)) - return IL_PCX; - #endif - - #ifndef IL_NO_PIC - if (ilIsValidPicF(File)) - return IL_PIC; - #endif - - #ifndef IL_NO_PNM - if (ilIsValidPnmF(File)) - return IL_PNM; - #endif - - #ifndef IL_NO_PSD - if (ilIsValidPsdF(File)) - return IL_PSD; - #endif - - #ifndef IL_NO_PSP - if (ilIsValidPspF(File)) - return IL_PSP; - #endif - - #ifndef IL_NO_SGI - if (ilIsValidSgiF(File)) - return IL_SGI; - #endif - - #ifndef IL_NO_SUN - if (ilIsValidSunF(File)) - return IL_SUN; - #endif - - #ifndef IL_NO_TIF - if (ilIsValidTiffF(File)) - return IL_TIF; - #endif - - #ifndef IL_NO_TPL - if (ilIsValidTplF(File)) - return IL_TPL; - #endif - - #ifndef IL_NO_VTF - if (ilIsValidVtfF(File)) - return IL_VTF; - #endif - - #ifndef IL_NO_XPM - if (ilIsValidXpmF(File)) - return IL_XPM; - #endif - - //moved tga to end of list because it has no magic number - //in header to assure that this is really a tga... (20040218) - #ifndef IL_NO_TGA - if (ilIsValidTgaF(File)) - return IL_TGA; - #endif - - return IL_TYPE_UNKNOWN; -} - - -ILenum ILAPIENTRY ilDetermineTypeL(const void *Lump, ILuint Size) -{ - if (Lump == NULL) - return IL_TYPE_UNKNOWN; - - #ifndef IL_NO_JPG - if (ilIsValidJpegL(Lump, Size)) - return IL_JPG; - #endif - - #ifndef IL_NO_DDS - if (ilIsValidDdsL(Lump, Size)) - return IL_DDS; - #endif - - #ifndef IL_NO_PNG - if (ilIsValidPngL(Lump, Size)) - return IL_PNG; - #endif - - #ifndef IL_NO_BMP - if (ilIsValidBmpL(Lump, Size)) - return IL_BMP; - #endif - - #ifndef IL_NO_EXR - if (ilIsValidExrL(Lump, Size)) - return IL_EXR; - #endif - - #ifndef IL_NO_GIF - if (ilIsValidGifL(Lump, Size)) - return IL_GIF; - #endif - - #ifndef IL_NO_HDR - if (ilIsValidHdrL(Lump, Size)) - return IL_HDR; - #endif - - #ifndef IL_NO_ICNS - if (ilIsValidIcnsL(Lump, Size)) - return IL_ICNS; - #endif - - #ifndef IL_NO_IWI - if (ilIsValidIwiL(Lump, Size)) - return IL_IWI; - #endif - - #ifndef IL_NO_ILBM - if (ilIsValidIlbmL(Lump,Size)) - return IL_ILBM; - #endif - - #ifndef IL_NO_JP2 - if (ilIsValidJp2L(Lump, Size)) - return IL_JP2; - #endif - - #ifndef IL_NO_KTX - if (ilIsValidKtxL(Lump, Size)) - return IL_KTX; - #endif - - #ifndef IL_NO_LIF - if (ilIsValidLifL(Lump, Size)) - return IL_LIF; - #endif - - #ifndef IL_NO_MDL - if (ilIsValidMdlL(Lump, Size)) - return IL_MDL; - #endif - - #ifndef IL_NO_MP3 - if (ilIsValidMp3L(Lump, Size)) - return IL_MP3; - #endif - - #ifndef IL_NO_PCX - if (ilIsValidPcxL(Lump, Size)) - return IL_PCX; - #endif - - #ifndef IL_NO_PIC - if (ilIsValidPicL(Lump, Size)) - return IL_PIC; - #endif - - #ifndef IL_NO_PNM - if (ilIsValidPnmL(Lump, Size)) - return IL_PNM; - #endif - - #ifndef IL_NO_PSD - if (ilIsValidPsdL(Lump, Size)) - return IL_PSD; - #endif - - #ifndef IL_NO_PSP - if (ilIsValidPspL(Lump, Size)) - return IL_PSP; - #endif - - #ifndef IL_NO_SGI - if (ilIsValidSgiL(Lump, Size)) - return IL_SGI; - #endif - - #ifndef IL_NO_SUN - if (ilIsValidSunL(Lump, Size)) - return IL_SUN; - #endif - - #ifndef IL_NO_TIF - if (ilIsValidTiffL(Lump, Size)) - return IL_TIF; - #endif - - #ifndef IL_NO_TPL - if (ilIsValidTplL(Lump, Size)) - return IL_TPL; - #endif - - #ifndef IL_NO_VTF - if (ilIsValidVtfL(Lump, Size)) - return IL_VTF; - #endif - - #ifndef IL_NO_XPM - if (ilIsValidXpmL(Lump, Size)) - return IL_XPM; - #endif - - //Moved Targa to end of list because it has no magic number - // in header to assure that this is really a tga... (20040218). - #ifndef IL_NO_TGA - if (ilIsValidTgaL(Lump, Size)) - return IL_TGA; - #endif - - return IL_TYPE_UNKNOWN; -} - - -ILboolean ILAPIENTRY ilIsValid(ILenum Type, ILconst_string FileName) -{ - if (FileName == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - switch (Type) - { - #ifndef IL_NO_TGA - case IL_TGA: - return ilIsValidTga(FileName); - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - return ilIsValidJpeg(FileName); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilIsValidDds(FileName); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilIsValidPng(FileName); - #endif - - #ifndef IL_NO_BMP - case IL_BMP: - return ilIsValidBmp(FileName); - #endif - - #ifndef IL_NO_DICOM - case IL_DICOM: - return ilIsValidDicom(FileName); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilIsValidExr(FileName); - #endif - - #ifndef IL_NO_GIF - case IL_GIF: - return ilIsValidGif(FileName); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilIsValidHdr(FileName); - #endif - - #ifndef IL_NO_ICNS - case IL_ICNS: - return ilIsValidIcns(FileName); - #endif - - #ifndef IL_NO_IWI - case IL_IWI: - return ilIsValidIwi(FileName); - #endif - - #ifndef IL_NO_ILBM - case IL_ILBM: - return ilIsValidIlbm(FileName); - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilIsValidJp2(FileName); - #endif - - #ifndef IL_NO_KTX - case IL_KTX: - return ilIsValidKtx(FileName); - #endif - - #ifndef IL_NO_LIF - case IL_LIF: - return ilIsValidLif(FileName); - #endif - - #ifndef IL_NO_MDL - case IL_MDL: - return ilIsValidMdl(FileName); - #endif - - #ifndef IL_NO_MP3 - case IL_MP3: - return ilIsValidMp3(FileName); - #endif - - #ifndef IL_NO_PCX - case IL_PCX: - return ilIsValidPcx(FileName); - #endif - - #ifndef IL_NO_PIC - case IL_PIC: - return ilIsValidPic(FileName); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilIsValidPnm(FileName); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilIsValidPsd(FileName); - #endif - - #ifndef IL_NO_PSP - case IL_PSP: - return ilIsValidPsp(FileName); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilIsValidSgi(FileName); - #endif - - #ifndef IL_NO_SUN - case IL_SUN: - return ilIsValidSun(FileName); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilIsValidTiff(FileName); - #endif - - #ifndef IL_NO_TPL - case IL_TPL: - return ilIsValidTpl(FileName); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilIsValidVtf(FileName); - #endif - - #ifndef IL_NO_XPM - case IL_XPM: - return ilIsValidXpm(FileName); - #endif - } - - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; -} - - -ILboolean ILAPIENTRY ilIsValidF(ILenum Type, ILHANDLE File) -{ - if (File == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - switch (Type) - { - #ifndef IL_NO_TGA - case IL_TGA: - return ilIsValidTgaF(File); - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - return ilIsValidJpegF(File); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilIsValidDdsF(File); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilIsValidPngF(File); - #endif - - #ifndef IL_NO_BMP - case IL_BMP: - return ilIsValidBmpF(File); - #endif - - #ifndef IL_NO_DICOM - case IL_DICOM: - return ilIsValidDicomF(File); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilIsValidExrF(File); - #endif - - #ifndef IL_NO_GIF - case IL_GIF: - return ilIsValidGifF(File); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilIsValidHdrF(File); - #endif - - #ifndef IL_NO_ICNS - case IL_ICNS: - return ilIsValidIcnsF(File); - #endif - - #ifndef IL_NO_IWI - case IL_IWI: - return ilIsValidIwiF(File); - #endif - - #ifndef IL_NO_ILBM - case IL_ILBM: - return ilIsValidIlbmF(File); - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilIsValidJp2F(File); - #endif - - #ifndef IL_NO_KTX - case IL_KTX: - return ilIsValidKtxF(File); - #endif - - #ifndef IL_NO_LIF - case IL_LIF: - return ilIsValidLifF(File); - #endif - - #ifndef IL_NO_MDL - case IL_MDL: - return ilIsValidMdlF(File); - #endif - - #ifndef IL_NO_MP3 - case IL_MP3: - return ilIsValidMp3F(File); - #endif - - #ifndef IL_NO_PCX - case IL_PCX: - return ilIsValidPcxF(File); - #endif - - #ifndef IL_NO_PIC - case IL_PIC: - return ilIsValidPicF(File); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilIsValidPnmF(File); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilIsValidPsdF(File); - #endif - - #ifndef IL_NO_PSP - case IL_PSP: - return ilIsValidPspF(File); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilIsValidSgiF(File); - #endif - - #ifndef IL_NO_SUN - case IL_SUN: - return ilIsValidSunF(File); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilIsValidTiffF(File); - #endif - - #ifndef IL_NO_TPL - case IL_TPL: - return ilIsValidTplF(File); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilIsValidVtfF(File); - #endif - - #ifndef IL_NO_XPM - case IL_XPM: - return ilIsValidXpmF(File); - #endif - } - - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; -} - - -ILboolean ILAPIENTRY ilIsValidL(ILenum Type, void *Lump, ILuint Size) -{ - if (Lump == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - switch (Type) - { - #ifndef IL_NO_TGA - case IL_TGA: - return ilIsValidTgaL(Lump, Size); - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - return ilIsValidJpegL(Lump, Size); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilIsValidDdsL(Lump, Size); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilIsValidPngL(Lump, Size); - #endif - - #ifndef IL_NO_BMP - case IL_BMP: - return ilIsValidBmpL(Lump, Size); - #endif - - #ifndef IL_NO_DICOM - case IL_DICOM: - return ilIsValidDicomL(Lump, Size); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilIsValidExrL(Lump, Size); - #endif - - #ifndef IL_NO_GIF - case IL_GIF: - return ilIsValidGifL(Lump, Size); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilIsValidHdrL(Lump, Size); - #endif - - #ifndef IL_NO_ICNS - case IL_ICNS: - return ilIsValidIcnsL(Lump, Size); - #endif - - #ifndef IL_NO_IWI - case IL_IWI: - return ilIsValidIwiL(Lump, Size); - #endif - - #ifndef IL_NO_ILBM - case IL_ILBM: - return ilIsValidIlbmL(Lump, Size); - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilIsValidJp2L(Lump, Size); - #endif - - #ifndef IL_NO_KTX - case IL_KTX: - return ilIsValidKtxL(Lump, Size); - #endif - - #ifndef IL_NO_LIF - case IL_LIF: - return ilIsValidLifL(Lump, Size); - #endif - - #ifndef IL_NO_MDL - case IL_MDL: - return ilIsValidMdlL(Lump, Size); - #endif - - #ifndef IL_NO_MP3 - case IL_MP3: - return ilIsValidMp3L(Lump, Size); - #endif - - #ifndef IL_NO_PCX - case IL_PCX: - return ilIsValidPcxL(Lump, Size); - #endif - - #ifndef IL_NO_PIC - case IL_PIC: - return ilIsValidPicL(Lump, Size); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilIsValidPnmL(Lump, Size); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilIsValidPsdL(Lump, Size); - #endif - - #ifndef IL_NO_PSP - case IL_PSP: - return ilIsValidPspL(Lump, Size); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilIsValidSgiL(Lump, Size); - #endif - - #ifndef IL_NO_SUN - case IL_SUN: - return ilIsValidSunL(Lump, Size); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilIsValidTiffL(Lump, Size); - #endif - - #ifndef IL_NO_TPL - case IL_TPL: - return ilIsValidTplL(Lump, Size); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilIsValidVtfL(Lump, Size); - #endif - - #ifndef IL_NO_XPM - case IL_XPM: - return ilIsValidXpmL(Lump, Size); - #endif - } - - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; -} - - -//! Attempts to load an image from a file. The file format is specified by the user. -/*! \param Type Format of this file. Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS, - IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS, - IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG, - IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIF, IL_TPL, - IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN. - If IL_TYPE_UNKNOWN is specified, ilLoad will try to determine the type of the file and load it. - \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives - the filename of the file to load. - \return Boolean value of failure or success. Returns IL_FALSE if all three loading methods - have been tried and failed.*/ -ILboolean ILAPIENTRY ilLoad(ILenum Type, ILconst_string FileName) -{ - ILboolean bRet; - - if (FileName == NULL || ilStrLen(FileName) < 1) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - switch (Type) - { - case IL_TYPE_UNKNOWN: - bRet = ilLoadImage(FileName); - break; - - #ifndef IL_NO_TGA - case IL_TGA: - bRet = ilLoadTarga(FileName); - break; - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - bRet = ilLoadJpeg(FileName); - break; - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - bRet = ilLoadJp2(FileName); - break; - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - bRet = ilLoadDds(FileName); - break; - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - bRet = ilLoadPng(FileName); - break; - #endif - - #ifndef IL_NO_BLP - case IL_BLP: - bRet = ilLoadBlp(FileName); - break; - #endif - - #ifndef IL_NO_BMP - case IL_BMP: - bRet = ilLoadBmp(FileName); - break; - #endif - - #ifndef IL_NO_DPX - case IL_DPX: - bRet = ilLoadDpx(FileName); - break; - #endif - - #ifndef IL_NO_GIF - case IL_GIF: - bRet = ilLoadGif(FileName); - break; - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - bRet = ilLoadHdr(FileName); - break; - #endif - - #ifndef IL_NO_CUT - case IL_CUT: - bRet = ilLoadCut(FileName); - break; - #endif - - #ifndef IL_NO_DICOM - case IL_DICOM: - bRet = ilLoadDicom(FileName); - break; - #endif - - #ifndef IL_NO_DOOM - case IL_DOOM: - bRet = ilLoadDoom(FileName); - break; - case IL_DOOM_FLAT: - bRet = ilLoadDoomFlat(FileName); - break; - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - bRet = ilLoadExr(FileName); - break; - #endif - - #ifndef IL_NO_FITS - case IL_FITS: - bRet = ilLoadFits(FileName); - break; - #endif - - #ifndef IL_NO_FTX - case IL_FTX: - bRet = ilLoadFtx(FileName); - break; - #endif - - #ifndef IL_NO_ICO - case IL_ICO: - bRet = ilLoadIcon(FileName); - break; - #endif - - #ifndef IL_NO_ICNS - case IL_ICNS: - bRet = ilLoadIcns(FileName); - break; - #endif - - #ifndef IL_NO_IFF - case IL_IFF: - bRet = ilLoadIff(FileName); - break; - #endif - - #ifndef IL_NO_ILBM - case IL_ILBM: - bRet = ilLoadIlbm(FileName); - break; - #endif - - #ifndef IL_NO_IWI - case IL_IWI: - bRet = ilLoadIwi(FileName); - break; - #endif - - #ifndef IL_NO_KTX - case IL_KTX: - bRet = ilLoadKtx(FileName); - break; - #endif - - #ifndef IL_NO_LIF - case IL_LIF: - bRet = ilLoadLif(FileName); - break; - #endif - - #ifndef IL_NO_MDL - case IL_MDL: - bRet = ilLoadMdl(FileName); - break; - #endif - - #ifndef IL_NO_MNG - case IL_MNG: - bRet = ilLoadMng(FileName); - break; - #endif - - #ifndef IL_NO_MP3 - case IL_MP3: - bRet = ilLoadMp3(FileName); - break; - #endif - - #ifndef IL_NO_PCD - case IL_PCD: - ilLoadPcd(FileName); - break; - #endif - - #ifndef IL_NO_PCX - case IL_PCX: - bRet = ilLoadPcx(FileName); - break; - #endif - - #ifndef IL_NO_PIC - case IL_PIC: - bRet = ilLoadPic(FileName); - break; - #endif - - #ifndef IL_NO_PIX - case IL_PIX: - bRet = ilLoadPix(FileName); - break; - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - bRet = ilLoadPnm(FileName); - break; - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - bRet = ilLoadPsd(FileName); - break; - #endif - - #ifndef IL_NO_PSP - case IL_PSP: - bRet = ilLoadPsp(FileName); - break; - #endif - - #ifndef IL_NO_PXR - case IL_PXR: - bRet = ilLoadPxr(FileName); - break; - #endif - - #ifndef IL_NO_RAW - case IL_RAW: - bRet = ilLoadRaw(FileName); - break; - #endif - - #ifndef IL_NO_ROT - case IL_ROT: - bRet = ilLoadRot(FileName); - break; - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - bRet = ilLoadSgi(FileName); - break; - #endif - - #ifndef IL_NO_SUN - case IL_SUN: - bRet = ilLoadSun(FileName); - break; - #endif - - #ifndef IL_NO_TEXTURE - case IL_TEXTURE: - bRet = ilLoadTexture(FileName); - break; - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - bRet = ilLoadTiff(FileName); - break; - #endif - - #ifndef IL_NO_TPL - case IL_TPL: - bRet = ilLoadTpl(FileName); - break; - #endif - - #ifndef IL_NO_UTX - case IL_UTX: - bRet = ilLoadUtx(FileName); - break; - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - bRet = ilLoadVtf(FileName); - break; - #endif - - #ifndef IL_NO_WAL - case IL_WAL: - bRet = ilLoadWal(FileName); - break; - #endif - - #ifndef IL_NO_WBMP - case IL_WBMP: - bRet = ilLoadWbmp(FileName); - break; - #endif - - #ifndef IL_NO_XPM - case IL_XPM: - bRet = ilLoadXpm(FileName); - break; - #endif - - #ifndef IL_NO_WDP - case IL_WDP: - bRet = ilLoadWdp(FileName); - break; - #endif - - default: - ilSetError(IL_INVALID_ENUM); - bRet = IL_FALSE; - } - - return bRet; -} - - -//! Attempts to load an image from a file stream. The file format is specified by the user. -/*! \param Type Format of this file. Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS, - IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS, - IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG, - IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIF, IL_TPL, - IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN. - If IL_TYPE_UNKNOWN is specified, ilLoadF will try to determine the type of the file and load it. - \param File File stream to load from. - \return Boolean value of failure or success. Returns IL_FALSE if loading fails.*/ -ILboolean ILAPIENTRY ilLoadF(ILenum Type, ILHANDLE File) -{ - if (File == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (Type == IL_TYPE_UNKNOWN) - Type = ilDetermineTypeF(File); - - switch (Type) - { - case IL_TYPE_UNKNOWN: - return IL_FALSE; - - #ifndef IL_NO_TGA - case IL_TGA: - return ilLoadTargaF(File); - #endif - - #ifndef IL_NO_JPG - #ifndef IL_USE_IJL - case IL_JPG: - return ilLoadJpegF(File); - #endif - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilLoadJp2F(File); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilLoadDdsF(File); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilLoadPngF(File); - #endif - - #ifndef IL_NO_BLP - case IL_BLP: - return ilLoadBlpF(File); - #endif - - #ifndef IL_NO_BMP - case IL_BMP: - return ilLoadBmpF(File); - #endif - - #ifndef IL_NO_CUT - case IL_CUT: - return ilLoadCutF(File); - #endif - - #ifndef IL_NO_DICOM - case IL_DICOM: - return ilLoadDicomF(File); - #endif - - #ifndef IL_NO_DOOM - case IL_DOOM: - return ilLoadDoomF(File); - case IL_DOOM_FLAT: - return ilLoadDoomFlatF(File); - #endif - - #ifndef IL_NO_DPX - case IL_DPX: - return ilLoadDpxF(File); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilLoadExrF(File); - #endif - - #ifndef IL_NO_FITS - case IL_FITS: - return ilLoadFitsF(File); - #endif - - #ifndef IL_NO_FTX - case IL_FTX: - return ilLoadFtxF(File); - #endif - - #ifndef IL_NO_GIF - case IL_GIF: - return ilLoadGifF(File); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilLoadHdrF(File); - #endif - - #ifndef IL_NO_ICO - case IL_ICO: - return ilLoadIconF(File); - #endif - - #ifndef IL_NO_ICNS - case IL_ICNS: - return ilLoadIcnsF(File); - #endif - - #ifndef IL_NO_IFF - case IL_IFF: - return ilLoadIffF(File); - #endif - - #ifndef IL_NO_ILBM - case IL_ILBM: - return ilLoadIlbmF(File); - #endif - - #ifndef IL_NO_IWI - case IL_IWI: - return ilLoadIwiF(File); - #endif - - #ifndef IL_NO_KTX - case IL_KTX: - return ilLoadKtxF(File); - #endif - - #ifndef IL_NO_LIF - case IL_LIF: - return ilLoadLifF(File); - #endif - - #ifndef IL_NO_MDL - case IL_MDL: - return ilLoadMdlF(File); - #endif - - #ifndef IL_NO_MNG - case IL_MNG: - return ilLoadMngF(File); - #endif - - #ifndef IL_NO_MP3 - case IL_MP3: - return ilLoadMp3F(File); - #endif - - #ifndef IL_NO_PCD - case IL_PCD: - return ilLoadPcdF(File); - #endif - - #ifndef IL_NO_PCX - case IL_PCX: - return ilLoadPcxF(File); - #endif - - #ifndef IL_NO_PIC - case IL_PIC: - return ilLoadPicF(File); - #endif - - #ifndef IL_NO_PIX - case IL_PIX: - return ilLoadPixF(File); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilLoadPnmF(File); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilLoadPsdF(File); - #endif - - #ifndef IL_NO_PSP - case IL_PSP: - return ilLoadPspF(File); - #endif - - #ifndef IL_NO_PXR - case IL_PXR: - return ilLoadPxrF(File); - #endif - - #ifndef IL_NO_RAW - case IL_RAW: - return ilLoadRawF(File); - #endif - - #ifndef IL_NO_ROT - case IL_ROT: - return ilLoadRotF(File); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilLoadSgiF(File); - #endif - - #ifndef IL_NO_SUN - case IL_SUN: - return ilLoadSunF(File); - #endif - - #ifndef IL_NO_TEXTURE - case IL_TEXTURE: - return ilLoadTextureF(File); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilLoadTiffF(File); - #endif - - #ifndef IL_NO_TPL - case IL_TPL: - return ilLoadTplF(File); - #endif - - #ifndef IL_NO_UTX - case IL_UTX: - return ilLoadUtxF(File); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilLoadVtfF(File); - #endif - - #ifndef IL_NO_WAL - case IL_WAL: - return ilLoadWalF(File); - #endif - - #ifndef IL_NO_WBMP - case IL_WBMP: - return ilLoadWbmpF(File); - #endif - - #ifndef IL_NO_XPM - case IL_XPM: - return ilLoadXpmF(File); - #endif - } - - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; -} - - -//! Attempts to load an image from a memory buffer. The file format is specified by the user. -/*! \param Type Format of this file. Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS, - IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS, - IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG, - IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIF, IL_TPL, - IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN. - If IL_TYPE_UNKNOWN is specified, ilLoadL will try to determine the type of the file and load it. - \param Lump The buffer where the file data is located - \param Size Size of the buffer - \return Boolean value of failure or success. Returns IL_FALSE if loading fails.*/ -ILboolean ILAPIENTRY ilLoadL(ILenum Type, const void *Lump, ILuint Size) -{ - if (Lump == NULL || Size == 0) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (Type == IL_TYPE_UNKNOWN) - Type = ilDetermineTypeL(Lump, Size); - - switch (Type) - { - case IL_TYPE_UNKNOWN: - return IL_FALSE; - - #ifndef IL_NO_TGA - case IL_TGA: - return ilLoadTargaL(Lump, Size); - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - return ilLoadJpegL(Lump, Size); - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilLoadJp2L(Lump, Size); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilLoadDdsL(Lump, Size); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilLoadPngL(Lump, Size); - #endif - - #ifndef IL_NO_BLP - case IL_BLP: - return ilLoadBlpL(Lump, Size); - #endif - - #ifndef IL_NO_BMP - case IL_BMP: - return ilLoadBmpL(Lump, Size); - #endif - - #ifndef IL_NO_CUT - case IL_CUT: - return ilLoadCutL(Lump, Size); - #endif - - #ifndef IL_NO_DICOM - case IL_DICOM: - return ilLoadDicomL(Lump, Size); - #endif - - #ifndef IL_NO_DOOM - case IL_DOOM: - return ilLoadDoomL(Lump, Size); - case IL_DOOM_FLAT: - return ilLoadDoomFlatL(Lump, Size); - #endif - - #ifndef IL_NO_DPX - case IL_DPX: - return ilLoadDpxL(Lump, Size); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilLoadExrL(Lump, Size); - #endif - - #ifndef IL_NO_FITS - case IL_FITS: - return ilLoadFitsL(Lump, Size); - #endif - - #ifndef IL_NO_FTX - case IL_FTX: - return ilLoadFtxL(Lump, Size); - #endif - - #ifndef IL_NO_GIF - case IL_GIF: - return ilLoadGifL(Lump, Size); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilLoadHdrL(Lump, Size); - #endif - - #ifndef IL_NO_ICO - case IL_ICO: - return ilLoadIconL(Lump, Size); - #endif - - #ifndef IL_NO_ICNS - case IL_ICNS: - return ilLoadIcnsL(Lump, Size); - #endif - - #ifndef IL_NO_IFF - case IL_IFF: - return ilLoadIffL(Lump, Size); - #endif - - #ifndef IL_NO_ILBM - case IL_ILBM: - return ilLoadIlbmL(Lump, Size); - #endif - - #ifndef IL_NO_IWI - case IL_IWI: - return ilLoadIwiL(Lump, Size); - #endif - - #ifndef IL_NO_KTX - case IL_KTX: - return ilLoadKtxL(Lump, Size); - #endif - - #ifndef IL_NO_LIF - case IL_LIF: - return ilLoadLifL(Lump, Size); - #endif - - #ifndef IL_NO_MDL - case IL_MDL: - return ilLoadMdlL(Lump, Size); - #endif - - #ifndef IL_NO_MNG - case IL_MNG: - return ilLoadMngL(Lump, Size); - #endif - - #ifndef IL_NO_MP3 - case IL_MP3: - return ilLoadMp3L(Lump, Size); - #endif - - #ifndef IL_NO_PCD - case IL_PCD: - return ilLoadPcdL(Lump, Size); - #endif - - #ifndef IL_NO_PCX - case IL_PCX: - return ilLoadPcxL(Lump, Size); - #endif - - #ifndef IL_NO_PIC - case IL_PIC: - return ilLoadPicL(Lump, Size); - #endif - - #ifndef IL_NO_PIX - case IL_PIX: - return ilLoadPixL(Lump, Size); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilLoadPnmL(Lump, Size); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilLoadPsdL(Lump, Size); - #endif - - #ifndef IL_NO_PSP - case IL_PSP: - return ilLoadPspL(Lump, Size); - #endif - - #ifndef IL_NO_PXR - case IL_PXR: - return ilLoadPxrL(Lump, Size); - #endif - - #ifndef IL_NO_RAW - case IL_RAW: - return ilLoadRawL(Lump, Size); - #endif - - #ifndef IL_NO_ROT - case IL_ROT: - return ilLoadRotL(Lump, Size); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilLoadSgiL(Lump, Size); - #endif - - #ifndef IL_NO_SUN - case IL_SUN: - return ilLoadSunL(Lump, Size); - #endif - - #ifndef IL_NO_TEXTURE - case IL_TEXTURE: - return ilLoadTextureL(Lump, Size); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilLoadTiffL(Lump, Size); - #endif - - #ifndef IL_NO_TPL - case IL_TPL: - return ilLoadTplL(Lump, Size); - #endif - - #ifndef IL_NO_UTX - case IL_UTX: - return ilLoadUtxL(Lump, Size); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilLoadVtfL(Lump, Size); - #endif - - #ifndef IL_NO_WAL - case IL_WAL: - return ilLoadWalL(Lump, Size); - #endif - - #ifndef IL_NO_WBMP - case IL_WBMP: - return ilLoadWbmpL(Lump, Size); - #endif - - #ifndef IL_NO_XPM - case IL_XPM: - return ilLoadXpmL(Lump, Size); - #endif - } - - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; -} - - -//! Attempts to load an image from a file with various different methods before failing - very generic. -/*! The ilLoadImage function allows a general interface to the specific internal file-loading - routines. First, it finds the extension and checks to see if any user-registered functions - (registered through ilRegisterLoad) match the extension. If nothing matches, it takes the - extension and determines which function to call based on it. Lastly, it attempts to identify - the image based on various image header verification functions, such as ilIsValidPngF. - If all this checking fails, IL_FALSE is returned with no modification to the current bound image. - \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives - the filename of the file to load. - \return Boolean value of failure or success. Returns IL_FALSE if all three loading methods - have been tried and failed.*/ -ILboolean ILAPIENTRY ilLoadImage(ILconst_string FileName) -{ - ILstring Ext; - ILenum Type; - ILboolean bRet = IL_FALSE; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (FileName == NULL || ilStrLen(FileName) < 1) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - Ext = iGetExtension(FileName); - - // Try registered procedures first (so users can override default lib functions). - if (Ext) { - if (iRegisterLoad(FileName)) - return IL_TRUE; - - #ifndef IL_NO_TGA - if (!iStrCmp(Ext, IL_TEXT("tga")) || !iStrCmp(Ext, IL_TEXT("vda")) || - !iStrCmp(Ext, IL_TEXT("icb")) || !iStrCmp(Ext, IL_TEXT("vst"))) { - bRet = ilLoadTarga(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_JPG - if (!iStrCmp(Ext, IL_TEXT("jpg")) || !iStrCmp(Ext, IL_TEXT("jpe")) || - !iStrCmp(Ext, IL_TEXT("jpeg")) || !iStrCmp(Ext, IL_TEXT("jif")) || !iStrCmp(Ext, IL_TEXT("jfif"))) { - bRet = ilLoadJpeg(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_JP2 - if (!iStrCmp(Ext, IL_TEXT("jp2")) || !iStrCmp(Ext, IL_TEXT("jpx")) || - !iStrCmp(Ext, IL_TEXT("j2k")) || !iStrCmp(Ext, IL_TEXT("j2c"))) { - bRet = ilLoadJp2(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_DDS - if (!iStrCmp(Ext, IL_TEXT("dds"))) { - bRet = ilLoadDds(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PNG - if (!iStrCmp(Ext, IL_TEXT("png"))) { - bRet = ilLoadPng(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_BMP - if (!iStrCmp(Ext, IL_TEXT("bmp")) || !iStrCmp(Ext, IL_TEXT("dib"))) { - bRet = ilLoadBmp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_BLP - if (!iStrCmp(Ext, IL_TEXT("blp"))) { - bRet = ilLoadBlp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_DPX - if (!iStrCmp(Ext, IL_TEXT("dpx"))) { - bRet = ilLoadDpx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_EXR - if (!iStrCmp(Ext, IL_TEXT("exr"))) { - bRet = ilLoadExr(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_GIF - if (!iStrCmp(Ext, IL_TEXT("gif"))) { - bRet = ilLoadGif(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_HDR - if (!iStrCmp(Ext, IL_TEXT("hdr"))) { - bRet = ilLoadHdr(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_CUT - if (!iStrCmp(Ext, IL_TEXT("cut"))) { - bRet = ilLoadCut(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_DCX - if (!iStrCmp(Ext, IL_TEXT("dcx"))) { - bRet = ilLoadDcx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_DICOM - if (!iStrCmp(Ext, IL_TEXT("dicom")) || !iStrCmp(Ext, IL_TEXT("dcm"))) { - bRet = ilLoadDicom(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_FITS - if (!iStrCmp(Ext, IL_TEXT("fits")) || !iStrCmp(Ext, IL_TEXT("fit"))) { - bRet = ilLoadFits(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_FTX - if (!iStrCmp(Ext, IL_TEXT("ftx"))) { - bRet = ilLoadFtx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_ICO - if (!iStrCmp(Ext, IL_TEXT("ico")) || !iStrCmp(Ext, IL_TEXT("cur"))) { - bRet = ilLoadIcon(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_ICNS - if (!iStrCmp(Ext, IL_TEXT("icns"))) { - bRet = ilLoadIcns(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_IFF - if (!iStrCmp(Ext, IL_TEXT("iff"))) { - bRet = ilLoadIff(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_ILBM - if (!iStrCmp(Ext, IL_TEXT("ilbm")) || !iStrCmp(Ext, IL_TEXT("lbm")) || - !iStrCmp(Ext, IL_TEXT("ham")) ) { - bRet = ilLoadIlbm(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_IWI - if (!iStrCmp(Ext, IL_TEXT("iwi"))) { - bRet = ilLoadIwi(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_KTX - if (!iStrCmp(Ext, IL_TEXT("ktx"))) { - bRet = ilLoadKtx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_LIF - if (!iStrCmp(Ext, IL_TEXT("lif"))) { - bRet = ilLoadLif(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_MDL - if (!iStrCmp(Ext, IL_TEXT("mdl"))) { - bRet = ilLoadMdl(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_MNG - if (!iStrCmp(Ext, IL_TEXT("mng")) || !iStrCmp(Ext, IL_TEXT("jng"))) { - bRet = ilLoadMng(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_MP3 - if (!iStrCmp(Ext, IL_TEXT("mp3"))) { - bRet = ilLoadMp3(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PCD - if (!iStrCmp(Ext, IL_TEXT("pcd"))) { - bRet = ilLoadPcd(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PCX - if (!iStrCmp(Ext, IL_TEXT("pcx"))) { - bRet = ilLoadPcx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PIC - if (!iStrCmp(Ext, IL_TEXT("pic"))) { - bRet = ilLoadPic(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PIX - if (!iStrCmp(Ext, IL_TEXT("pix"))) { - bRet = ilLoadPix(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PNM - if (!iStrCmp(Ext, IL_TEXT("pbm"))) { - bRet = ilLoadPnm(FileName); - goto finish; - } - if (!iStrCmp(Ext, IL_TEXT("pgm"))) { - bRet = ilLoadPnm(FileName); - goto finish; - } - if (!iStrCmp(Ext, IL_TEXT("pnm"))) { - bRet = ilLoadPnm(FileName); - goto finish; - } - if (!iStrCmp(Ext, IL_TEXT("ppm"))) { - bRet = ilLoadPnm(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PSD - if (!iStrCmp(Ext, IL_TEXT("psd")) || !iStrCmp(Ext, IL_TEXT("pdd"))) { - bRet = ilLoadPsd(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PSP - if (!iStrCmp(Ext, IL_TEXT("psp"))) { - bRet = ilLoadPsp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PXR - if (!iStrCmp(Ext, IL_TEXT("pxr"))) { - bRet = ilLoadPxr(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_ROT - if (!iStrCmp(Ext, IL_TEXT("rot"))) { - bRet = ilLoadRot(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_SGI - if (!iStrCmp(Ext, IL_TEXT("sgi")) || !iStrCmp(Ext, IL_TEXT("bw")) || - !iStrCmp(Ext, IL_TEXT("rgb")) || !iStrCmp(Ext, IL_TEXT("rgba"))) { - bRet = ilLoadSgi(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_SUN - if (!iStrCmp(Ext, IL_TEXT("sun")) || !iStrCmp(Ext, IL_TEXT("ras")) || - !iStrCmp(Ext, IL_TEXT("rs")) || !iStrCmp(Ext, IL_TEXT("im1")) || - !iStrCmp(Ext, IL_TEXT("im8")) || !iStrCmp(Ext, IL_TEXT("im24")) || - !iStrCmp(Ext, IL_TEXT("im32"))) { - bRet = ilLoadSun(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_TEXTURE - if (!iStrCmp(Ext, IL_TEXT("texture"))) { - bRet = ilLoadTexture(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_TIF - if (!iStrCmp(Ext, IL_TEXT("tif")) || !iStrCmp(Ext, IL_TEXT("tiff"))) { - bRet = ilLoadTiff(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_TPL - if (!iStrCmp(Ext, IL_TEXT("tpl"))) { - bRet = ilLoadTpl(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_UTX - if (!iStrCmp(Ext, IL_TEXT("utx"))) { - bRet = ilLoadUtx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_VTF - if (!iStrCmp(Ext, IL_TEXT("vtf"))) { - bRet = ilLoadVtf(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_WAL - if (!iStrCmp(Ext, IL_TEXT("wal"))) { - bRet = ilLoadWal(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_WBMP - if (!iStrCmp(Ext, IL_TEXT("wbmp"))) { - bRet = ilLoadWbmp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_WDP - if (!iStrCmp(Ext, IL_TEXT("wdp")) || !iStrCmp(Ext, IL_TEXT("hdp")) ) { - bRet = ilLoadWdp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_XPM - if (!iStrCmp(Ext, IL_TEXT("xpm"))) { - bRet = ilLoadXpm(FileName); - goto finish; - } - #endif - } - - // As a last-ditch effort, try to identify the image - Type = ilDetermineType(FileName); - if (Type == IL_TYPE_UNKNOWN) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - return ilLoad(Type, FileName); - -finish: - return bRet; -} - - -//! Attempts to save an image to a file. The file format is specified by the user. -/*! \param Type Format of this file. Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR, - IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIF, - IL_VTF, IL_WBMP and IL_JASC_PAL. - \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives - the filename to save to. - \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ -ILboolean ILAPIENTRY ilSave(ILenum Type, ILconst_string FileName) -{ - switch (Type) - { - case IL_TYPE_UNKNOWN: - return ilSaveImage(FileName); - - #ifndef IL_NO_BMP - case IL_BMP: - return ilSaveBmp(FileName); - #endif - - #ifndef IL_NO_CHEAD - case IL_CHEAD: - return ilSaveCHeader(FileName, "IL_IMAGE"); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilSaveDds(FileName); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilSaveExr(FileName); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilSaveHdr(FileName); - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilSaveJp2(FileName); - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - return ilSaveJpeg(FileName); - #endif - - /*#ifndef IL_NO_KTX - case IL_KTX: - return ilSaveKtx(FileName); - #endif*/ - - #ifndef IL_NO_PCX - case IL_PCX: - return ilSavePcx(FileName); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilSavePng(FileName); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilSavePnm(FileName); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilSavePsd(FileName); - #endif - - #ifndef IL_NO_RAW - case IL_RAW: - return ilSaveRaw(FileName); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilSaveSgi(FileName); - #endif - - #ifndef IL_NO_TGA - case IL_TGA: - return ilSaveTarga(FileName); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilSaveTiff(FileName); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilSaveVtf(FileName); - #endif - - #ifndef IL_NO_WBMP - case IL_WBMP: - return ilSaveWbmp(FileName); - #endif - - case IL_JASC_PAL: - return ilSaveJascPal(FileName); - } - - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; -} - - -//! Attempts to save an image to a file stream. The file format is specified by the user. -/*! \param Type Format of this file. Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR, - IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIF, - IL_VTF, IL_WBMP and IL_JASC_PAL. - \param File File stream to save to. - \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ -ILuint ILAPIENTRY ilSaveF(ILenum Type, ILHANDLE File) -{ - ILboolean Ret; - - if (File == NULL) { - ilSetError(IL_INVALID_PARAM); - return 0; - } - - switch (Type) - { - #ifndef IL_NO_BMP - case IL_BMP: - Ret = ilSaveBmpF(File); - break; - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - Ret = ilSaveDdsF(File); - break; - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - Ret = ilSaveExrF(File); - break; - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - Ret = ilSaveHdrF(File); - break; - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - Ret = ilSaveJp2F(File); - break; - #endif - - #ifndef IL_NO_JPG - #ifndef IL_USE_IJL - case IL_JPG: - Ret = ilSaveJpegF(File); - break; - #endif - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - Ret = ilSavePnmF(File); - break; - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - Ret = ilSavePngF(File); - break; - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - Ret = ilSavePsdF(File); - break; - #endif - - #ifndef IL_NO_RAW - case IL_RAW: - Ret = ilSaveRawF(File); - break; - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - Ret = ilSaveSgiF(File); - break; - #endif - - #ifndef IL_NO_TGA - case IL_TGA: - Ret = ilSaveTargaF(File); - break; - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - Ret = ilSaveVtfF(File); - break; - #endif - - #ifndef IL_NO_WBMP - case IL_WBMP: - Ret = ilSaveWbmpF(File); - break; - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - Ret = ilSaveTiffF(File); - break; - #endif - - default: - ilSetError(IL_INVALID_ENUM); - return 0; - } - - if (Ret == IL_FALSE) - return 0; - - return itellw(); -} - - -//! Attempts to save an image to a memory buffer. The file format is specified by the user. -/*! \param Type Format of this image file. Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR, - IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIF, - IL_VTF, IL_WBMP and IL_JASC_PAL. - \param Lump Memory buffer to save to - \param Size Size of the memory buffer - \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ -ILuint ILAPIENTRY ilSaveL(ILenum Type, void *Lump, ILuint Size) -{ - if (Lump == NULL) { - if (Size != 0) { - ilSetError(IL_INVALID_PARAM); - return 0; - } - // The user wants to know how large of a buffer they need. - else { - return ilDetermineSize(Type); - } - } - - switch (Type) - { - #ifndef IL_NO_BMP - case IL_BMP: - return ilSaveBmpL(Lump, Size); - #endif - - #ifndef IL_NO_EXR - case IL_EXR: - return ilSaveExrL(Lump, Size); - #endif - - #ifndef IL_NO_HDR - case IL_HDR: - return ilSaveHdrL(Lump, Size); - #endif - - #ifndef IL_NO_JP2 - case IL_JP2: - return ilSaveJp2L(Lump, Size); - #endif - - #ifndef IL_NO_JPG - case IL_JPG: - return ilSaveJpegL(Lump, Size); - #endif - - #ifndef IL_NO_PNG - case IL_PNG: - return ilSavePngL(Lump, Size); - #endif - - #ifndef IL_NO_PNM - case IL_PNM: - return ilSavePnmL(Lump, Size); - #endif - - #ifndef IL_NO_PSD - case IL_PSD: - return ilSavePsdL(Lump, Size); - #endif - - #ifndef IL_NO_RAW - case IL_RAW: - return ilSaveRawL(Lump, Size); - #endif - - #ifndef IL_NO_SGI - case IL_SGI: - return ilSaveSgiL(Lump, Size); - #endif - - #ifndef IL_NO_TGA - case IL_TGA: - return ilSaveTargaL(Lump, Size); - #endif - - #ifndef IL_NO_DDS - case IL_DDS: - return ilSaveDdsL(Lump, Size); - #endif - - #ifndef IL_NO_VTF - case IL_VTF: - return ilSaveVtfL(Lump, Size); - #endif - - #ifndef IL_NO_WBMP - case IL_WBMP: - return ilSaveWbmpL(Lump, Size); - #endif - - #ifndef IL_NO_TIF - case IL_TIF: - return ilSaveTiffL(Lump, Size); - #endif - } - - ilSetError(IL_INVALID_ENUM); - return 0; -} - - -//! Saves the current image based on the extension given in FileName. -/*! \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives - the filename to save to. - \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ -ILboolean ILAPIENTRY ilSaveImage(ILconst_string FileName) -{ - ILstring Ext; - ILboolean bRet = IL_FALSE; - - if (FileName == NULL || ilStrLen(FileName) < 1) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Ext = iGetExtension(FileName); - if (Ext == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - #ifndef IL_NO_BMP - if (!iStrCmp(Ext, IL_TEXT("bmp"))) { - bRet = ilSaveBmp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_CHEAD - if (!iStrCmp(Ext, IL_TEXT("h"))) { - bRet = ilSaveCHeader(FileName, "IL_IMAGE"); - goto finish; - } - #endif - - #ifndef IL_NO_DDS - if (!iStrCmp(Ext, IL_TEXT("dds"))) { - bRet = ilSaveDds(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_EXR - if (!iStrCmp(Ext, IL_TEXT("exr"))) { - bRet = ilSaveExr(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_HDR - if (!iStrCmp(Ext, IL_TEXT("hdr"))) { - bRet = ilSaveHdr(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_JP2 - if (!iStrCmp(Ext, IL_TEXT("jp2"))) { - bRet = ilSaveJp2(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_JPG - if (!iStrCmp(Ext, IL_TEXT("jpg")) || !iStrCmp(Ext, IL_TEXT("jpeg")) || !iStrCmp(Ext, IL_TEXT("jpe"))) { - bRet = ilSaveJpeg(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PCX - if (!iStrCmp(Ext, IL_TEXT("pcx"))) { - bRet = ilSavePcx(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PNG - if (!iStrCmp(Ext, IL_TEXT("png"))) { - bRet = ilSavePng(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PNM // Not sure if binary or ascii should be defaulted...maybe an option? - if (!iStrCmp(Ext, IL_TEXT("pbm"))) { - bRet = ilSavePnm(FileName); - goto finish; - } - if (!iStrCmp(Ext, IL_TEXT("pgm"))) { - bRet = ilSavePnm(FileName); - goto finish; - } - if (!iStrCmp(Ext, IL_TEXT("ppm"))) { - bRet = ilSavePnm(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_PSD - if (!iStrCmp(Ext, IL_TEXT("psd"))) { - bRet = ilSavePsd(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_RAW - if (!iStrCmp(Ext, IL_TEXT("raw"))) { - bRet = ilSaveRaw(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_SGI - if (!iStrCmp(Ext, IL_TEXT("sgi")) || !iStrCmp(Ext, IL_TEXT("bw")) || - !iStrCmp(Ext, IL_TEXT("rgb")) || !iStrCmp(Ext, IL_TEXT("rgba"))) { - bRet = ilSaveSgi(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_TGA - if (!iStrCmp(Ext, IL_TEXT("tga"))) { - bRet = ilSaveTarga(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_TIF - if (!iStrCmp(Ext, IL_TEXT("tif")) || !iStrCmp(Ext, IL_TEXT("tiff"))) { - bRet = ilSaveTiff(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_VTF - if (!iStrCmp(Ext, IL_TEXT("vtf"))) { - bRet = ilSaveVtf(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_WBMP - if (!iStrCmp(Ext, IL_TEXT("wbmp"))) { - bRet = ilSaveWbmp(FileName); - goto finish; - } - #endif - - #ifndef IL_NO_MNG - if (!iStrCmp(Ext, IL_TEXT("mng"))) { - bRet = ilSaveMng(FileName); - goto finish; - } - #endif - - // Check if we just want to save the palette. - if (!iStrCmp(Ext, IL_TEXT("pal"))) { - bRet = ilSavePal(FileName); - goto finish; - } - - // Try registered procedures - if (iRegisterSave(FileName)) - return IL_TRUE; - - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - -finish: - return bRet; -} diff --git a/DevIL/src-IL/src/il_io.cpp b/DevIL/src-IL/src/il_io.cpp new file mode 100644 index 00000000..d5ce3ae5 --- /dev/null +++ b/DevIL/src-IL/src/il_io.cpp @@ -0,0 +1,2698 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_io.c +// +// Description: Determines image types and loads/saves images +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#include "il_register.h" +#include "il_pal.h" +#include + + +// Returns a widened version of a string. +// Make sure to free this after it is used. Code help from +// https://buildsecurityin.us-cert.gov/daisy/bsi-rules/home/g1/769-BSI.html +#if defined(_UNICODE) +wchar_t *WideFromMultiByte(const char *Multi) +{ + ILint Length; + wchar_t *Temp; + + Length = (ILint)mbstowcs(NULL, (const char*)Multi, 0) + 1; // note error return of -1 is possible + if (Length == 0) { + ilSetError(IL_INVALID_PARAM); + return NULL; + } + if (Length > ULONG_MAX/sizeof(wchar_t)) { + ilSetError(IL_INTERNAL_ERROR); + return NULL; + } + Temp = (wchar_t*)ialloc(Length * sizeof(wchar_t)); + mbstowcs(Temp, (const char*)Multi, Length); + + return Temp; +} +#endif + + +ILenum ILAPIENTRY ilTypeFromExt(ILconst_string FileName) +{ + ILenum Type; + ILstring Ext; + + if (FileName == NULL || ilStrLen(FileName) < 1) { + ilSetError(IL_INVALID_PARAM); + return IL_TYPE_UNKNOWN; + } + + Ext = iGetExtension(FileName); + //added 2003-08-31: fix sf bug 789535 + if (Ext == NULL) { + return IL_TYPE_UNKNOWN; + } + + if (!iStrCmp(Ext, IL_TEXT("tga")) || !iStrCmp(Ext, IL_TEXT("vda")) || + !iStrCmp(Ext, IL_TEXT("icb")) || !iStrCmp(Ext, IL_TEXT("vst"))) + Type = IL_TGA; + else if (!iStrCmp(Ext, IL_TEXT("jpg")) || !iStrCmp(Ext, IL_TEXT("jpe")) || + !iStrCmp(Ext, IL_TEXT("jpeg")) || !iStrCmp(Ext, IL_TEXT("jif")) || !iStrCmp(Ext, IL_TEXT("jfif"))) + Type = IL_JPG; + else if (!iStrCmp(Ext, IL_TEXT("jp2")) || !iStrCmp(Ext, IL_TEXT("jpx")) || + !iStrCmp(Ext, IL_TEXT("j2k")) || !iStrCmp(Ext, IL_TEXT("j2c"))) + Type = IL_JP2; + else if (!iStrCmp(Ext, IL_TEXT("dds"))) + Type = IL_DDS; + else if (!iStrCmp(Ext, IL_TEXT("png"))) + Type = IL_PNG; + else if (!iStrCmp(Ext, IL_TEXT("bmp")) || !iStrCmp(Ext, IL_TEXT("dib"))) + Type = IL_BMP; + else if (!iStrCmp(Ext, IL_TEXT("gif"))) + Type = IL_GIF; + else if (!iStrCmp(Ext, IL_TEXT("blp"))) + Type = IL_BLP; + else if (!iStrCmp(Ext, IL_TEXT("cut"))) + Type = IL_CUT; + else if (!iStrCmp(Ext, IL_TEXT("dcm")) || !iStrCmp(Ext, IL_TEXT("dicom"))) + Type = IL_DICOM; + else if (!iStrCmp(Ext, IL_TEXT("dpx"))) + Type = IL_DPX; + else if (!iStrCmp(Ext, IL_TEXT("exr"))) + Type = IL_EXR; + else if (!iStrCmp(Ext, IL_TEXT("fit")) || !iStrCmp(Ext, IL_TEXT("fits"))) + Type = IL_FITS; + else if (!iStrCmp(Ext, IL_TEXT("ftx"))) + Type = IL_FTX; + else if (!iStrCmp(Ext, IL_TEXT("hdr"))) + Type = IL_HDR; + else if (!iStrCmp(Ext, IL_TEXT("iff"))) + Type = IL_IFF; + else if (!iStrCmp(Ext, IL_TEXT("ilbm")) || !iStrCmp(Ext, IL_TEXT("lbm")) || + !iStrCmp(Ext, IL_TEXT("ham"))) + Type = IL_ILBM; + else if (!iStrCmp(Ext, IL_TEXT("ico")) || !iStrCmp(Ext, IL_TEXT("cur"))) + Type = IL_ICO; + else if (!iStrCmp(Ext, IL_TEXT("icns"))) + Type = IL_ICNS; + else if (!iStrCmp(Ext, IL_TEXT("iwi"))) + Type = IL_IWI; + else if (!iStrCmp(Ext, IL_TEXT("iwi"))) + Type = IL_IWI; + else if (!iStrCmp(Ext, IL_TEXT("jng"))) + Type = IL_JNG; + else if (!iStrCmp(Ext, IL_TEXT("ktx"))) + Type = IL_KTX; + else if (!iStrCmp(Ext, IL_TEXT("lif"))) + Type = IL_LIF; + else if (!iStrCmp(Ext, IL_TEXT("mdl"))) + Type = IL_MDL; + else if (!iStrCmp(Ext, IL_TEXT("mng")) || !iStrCmp(Ext, IL_TEXT("jng"))) + Type = IL_MNG; + else if (!iStrCmp(Ext, IL_TEXT("mp3"))) + Type = IL_MP3; + else if (!iStrCmp(Ext, IL_TEXT("pcd"))) + Type = IL_PCD; + else if (!iStrCmp(Ext, IL_TEXT("pcx"))) + Type = IL_PCX; + else if (!iStrCmp(Ext, IL_TEXT("pic"))) + Type = IL_PIC; + else if (!iStrCmp(Ext, IL_TEXT("pix"))) + Type = IL_PIX; + else if (!iStrCmp(Ext, IL_TEXT("pbm")) || !iStrCmp(Ext, IL_TEXT("pgm")) || + !iStrCmp(Ext, IL_TEXT("pnm")) || !iStrCmp(Ext, IL_TEXT("ppm"))) + Type = IL_PNM; + else if (!iStrCmp(Ext, IL_TEXT("psd")) || !iStrCmp(Ext, IL_TEXT("pdd"))) + Type = IL_PSD; + else if (!iStrCmp(Ext, IL_TEXT("psp"))) + Type = IL_PSP; + else if (!iStrCmp(Ext, IL_TEXT("pxr"))) + Type = IL_PXR; + else if (!iStrCmp(Ext, IL_TEXT("rot"))) + Type = IL_ROT; + else if (!iStrCmp(Ext, IL_TEXT("sgi")) || !iStrCmp(Ext, IL_TEXT("bw")) || + !iStrCmp(Ext, IL_TEXT("rgb")) || !iStrCmp(Ext, IL_TEXT("rgba"))) + Type = IL_SGI; + else if (!iStrCmp(Ext, IL_TEXT("sun")) || !iStrCmp(Ext, IL_TEXT("ras")) || + !iStrCmp(Ext, IL_TEXT("rs")) || !iStrCmp(Ext, IL_TEXT("im1")) || + !iStrCmp(Ext, IL_TEXT("im8")) || !iStrCmp(Ext, IL_TEXT("im24")) || + !iStrCmp(Ext, IL_TEXT("im32"))) + Type = IL_SUN; + else if (!iStrCmp(Ext, IL_TEXT("texture"))) + Type = IL_TEXTURE; + else if (!iStrCmp(Ext, IL_TEXT("tif")) || !iStrCmp(Ext, IL_TEXT("tiff"))) + Type = IL_TIF; + else if (!iStrCmp(Ext, IL_TEXT("tpl"))) + Type = IL_TPL; + else if (!iStrCmp(Ext, IL_TEXT("utx"))) + Type = IL_UTX; + else if (!iStrCmp(Ext, IL_TEXT("vtf"))) + Type = IL_VTF; + else if (!iStrCmp(Ext, IL_TEXT("wal"))) + Type = IL_WAL; + else if (!iStrCmp(Ext, IL_TEXT("wbmp"))) + Type = IL_WBMP; + else if (!iStrCmp(Ext, IL_TEXT("wdp")) || !iStrCmp(Ext, IL_TEXT("hdp"))) + Type = IL_WDP; + else if (!iStrCmp(Ext, IL_TEXT("xpm"))) + Type = IL_XPM; + else + Type = IL_TYPE_UNKNOWN; + + return Type; +} + + +//changed 2003-09-17 to ILAPIENTRY +ILenum ILAPIENTRY ilDetermineType(ILconst_string FileName) +{ + ILHANDLE File; + ILenum Type; + + if (FileName == NULL) + return IL_TYPE_UNKNOWN; + + File = iopenr(FileName); + if (File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + Type = ilDetermineTypeF(File); + icloser(File); + + return Type; +} + + +ILenum ILAPIENTRY ilDetermineTypeF(ILHANDLE File) +{ + if (File == NULL) + return IL_TYPE_UNKNOWN; + + #ifndef IL_NO_JPG + if (ilIsValidJpegF(File)) + return IL_JPG; + #endif + + #ifndef IL_NO_DDS + if (ilIsValidDdsF(File)) + return IL_DDS; + #endif + + #ifndef IL_NO_PNG + if (ilIsValidPngF(File)) + return IL_PNG; + #endif + + #ifndef IL_NO_BMP + if (ilIsValidBmpF(File)) + return IL_BMP; + #endif + + #ifndef IL_NO_EXR + if (ilIsValidExrF(File)) + return IL_EXR; + #endif + + #ifndef IL_NO_GIF + if (ilIsValidGifF(File)) + return IL_GIF; + #endif + + #ifndef IL_NO_HDR + if (ilIsValidHdrF(File)) + return IL_HDR; + #endif + + #ifndef IL_NO_ICNS + if (ilIsValidIcnsF(File)) + return IL_ICNS; + #endif + + #ifndef IL_NO_ILBM + if (ilIsValidIlbmF(File)) + return IL_ILBM; + #endif + + #ifndef IL_NO_IWI + if (ilIsValidIwiF(File)) + return IL_IWI; + #endif + + #ifndef IL_NO_JP2 + if (ilIsValidJp2F(File)) + return IL_JP2; + #endif + + #ifndef IL_NO_KTX + if (ilIsValidKtxF(File)) + return IL_KTX; + #endif + + #ifndef IL_NO_LIF + if (ilIsValidLifF(File)) + return IL_LIF; + #endif + + #ifndef IL_NO_MDL + if (ilIsValidMdlF(File)) + return IL_MDL; + #endif + + #ifndef IL_NO_MDL + if (ilIsValidMp3F(File)) + return IL_MP3; + #endif + + #ifndef IL_NO_PCX + if (ilIsValidPcxF(File)) + return IL_PCX; + #endif + + #ifndef IL_NO_PIC + if (ilIsValidPicF(File)) + return IL_PIC; + #endif + + #ifndef IL_NO_PNM + if (ilIsValidPnmF(File)) + return IL_PNM; + #endif + + #ifndef IL_NO_PSD + if (ilIsValidPsdF(File)) + return IL_PSD; + #endif + + #ifndef IL_NO_PSP + if (ilIsValidPspF(File)) + return IL_PSP; + #endif + + #ifndef IL_NO_SGI + if (ilIsValidSgiF(File)) + return IL_SGI; + #endif + + #ifndef IL_NO_SUN + if (ilIsValidSunF(File)) + return IL_SUN; + #endif + + #ifndef IL_NO_TIF + if (ilIsValidTiffF(File)) + return IL_TIF; + #endif + + #ifndef IL_NO_TPL + if (ilIsValidTplF(File)) + return IL_TPL; + #endif + + #ifndef IL_NO_VTF + if (ilIsValidVtfF(File)) + return IL_VTF; + #endif + + #ifndef IL_NO_XPM + if (ilIsValidXpmF(File)) + return IL_XPM; + #endif + + //moved tga to end of list because it has no magic number + //in header to assure that this is really a tga... (20040218) + #ifndef IL_NO_TGA + if (ilIsValidTgaF(File)) + return IL_TGA; + #endif + + return IL_TYPE_UNKNOWN; +} + + +ILenum ILAPIENTRY ilDetermineTypeL(const void *Lump, ILuint Size) +{ + if (Lump == NULL) + return IL_TYPE_UNKNOWN; + + #ifndef IL_NO_JPG + if (ilIsValidJpegL(Lump, Size)) + return IL_JPG; + #endif + + #ifndef IL_NO_DDS + if (ilIsValidDdsL(Lump, Size)) + return IL_DDS; + #endif + + #ifndef IL_NO_PNG + if (ilIsValidPngL(Lump, Size)) + return IL_PNG; + #endif + + #ifndef IL_NO_BMP + if (ilIsValidBmpL(Lump, Size)) + return IL_BMP; + #endif + + #ifndef IL_NO_EXR + if (ilIsValidExrL(Lump, Size)) + return IL_EXR; + #endif + + #ifndef IL_NO_GIF + if (ilIsValidGifL(Lump, Size)) + return IL_GIF; + #endif + + #ifndef IL_NO_HDR + if (ilIsValidHdrL(Lump, Size)) + return IL_HDR; + #endif + + #ifndef IL_NO_ICNS + if (ilIsValidIcnsL(Lump, Size)) + return IL_ICNS; + #endif + + #ifndef IL_NO_IWI + if (ilIsValidIwiL(Lump, Size)) + return IL_IWI; + #endif + + #ifndef IL_NO_ILBM + if (ilIsValidIlbmL(Lump,Size)) + return IL_ILBM; + #endif + + #ifndef IL_NO_JP2 + if (ilIsValidJp2L(Lump, Size)) + return IL_JP2; + #endif + + #ifndef IL_NO_KTX + if (ilIsValidKtxL(Lump, Size)) + return IL_KTX; + #endif + + #ifndef IL_NO_LIF + if (ilIsValidLifL(Lump, Size)) + return IL_LIF; + #endif + + #ifndef IL_NO_MDL + if (ilIsValidMdlL(Lump, Size)) + return IL_MDL; + #endif + + #ifndef IL_NO_MP3 + if (ilIsValidMp3L(Lump, Size)) + return IL_MP3; + #endif + + #ifndef IL_NO_PCX + if (ilIsValidPcxL(Lump, Size)) + return IL_PCX; + #endif + + #ifndef IL_NO_PIC + if (ilIsValidPicL(Lump, Size)) + return IL_PIC; + #endif + + #ifndef IL_NO_PNM + if (ilIsValidPnmL(Lump, Size)) + return IL_PNM; + #endif + + #ifndef IL_NO_PSD + if (ilIsValidPsdL(Lump, Size)) + return IL_PSD; + #endif + + #ifndef IL_NO_PSP + if (ilIsValidPspL(Lump, Size)) + return IL_PSP; + #endif + + #ifndef IL_NO_SGI + if (ilIsValidSgiL(Lump, Size)) + return IL_SGI; + #endif + + #ifndef IL_NO_SUN + if (ilIsValidSunL(Lump, Size)) + return IL_SUN; + #endif + + #ifndef IL_NO_TIF + if (ilIsValidTiffL(Lump, Size)) + return IL_TIF; + #endif + + #ifndef IL_NO_TPL + if (ilIsValidTplL(Lump, Size)) + return IL_TPL; + #endif + + #ifndef IL_NO_VTF + if (ilIsValidVtfL(Lump, Size)) + return IL_VTF; + #endif + + #ifndef IL_NO_XPM + if (ilIsValidXpmL(Lump, Size)) + return IL_XPM; + #endif + + //Moved Targa to end of list because it has no magic number + // in header to assure that this is really a tga... (20040218). + #ifndef IL_NO_TGA + if (ilIsValidTgaL(Lump, Size)) + return IL_TGA; + #endif + + return IL_TYPE_UNKNOWN; +} + + +ILboolean ILAPIENTRY ilIsValid(ILenum Type, ILconst_string FileName) +{ + if (FileName == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + switch (Type) + { + #ifndef IL_NO_TGA + case IL_TGA: + return ilIsValidTga(FileName); + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + return ilIsValidJpeg(FileName); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilIsValidDds(FileName); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilIsValidPng(FileName); + #endif + + #ifndef IL_NO_BMP + case IL_BMP: + return ilIsValidBmp(FileName); + #endif + + #ifndef IL_NO_DICOM + case IL_DICOM: + return ilIsValidDicom(FileName); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilIsValidExr(FileName); + #endif + + #ifndef IL_NO_GIF + case IL_GIF: + return ilIsValidGif(FileName); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilIsValidHdr(FileName); + #endif + + #ifndef IL_NO_ICNS + case IL_ICNS: + return ilIsValidIcns(FileName); + #endif + + #ifndef IL_NO_IWI + case IL_IWI: + return ilIsValidIwi(FileName); + #endif + + #ifndef IL_NO_ILBM + case IL_ILBM: + return ilIsValidIlbm(FileName); + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilIsValidJp2(FileName); + #endif + + #ifndef IL_NO_KTX + case IL_KTX: + return ilIsValidKtx(FileName); + #endif + + #ifndef IL_NO_LIF + case IL_LIF: + return ilIsValidLif(FileName); + #endif + + #ifndef IL_NO_MDL + case IL_MDL: + return ilIsValidMdl(FileName); + #endif + + #ifndef IL_NO_MP3 + case IL_MP3: + return ilIsValidMp3(FileName); + #endif + + #ifndef IL_NO_PCX + case IL_PCX: + return ilIsValidPcx(FileName); + #endif + + #ifndef IL_NO_PIC + case IL_PIC: + return ilIsValidPic(FileName); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilIsValidPnm(FileName); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilIsValidPsd(FileName); + #endif + + #ifndef IL_NO_PSP + case IL_PSP: + return ilIsValidPsp(FileName); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilIsValidSgi(FileName); + #endif + + #ifndef IL_NO_SUN + case IL_SUN: + return ilIsValidSun(FileName); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilIsValidTiff(FileName); + #endif + + #ifndef IL_NO_TPL + case IL_TPL: + return ilIsValidTpl(FileName); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilIsValidVtf(FileName); + #endif + + #ifndef IL_NO_XPM + case IL_XPM: + return ilIsValidXpm(FileName); + #endif + } + + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; +} + + +ILboolean ILAPIENTRY ilIsValidF(ILenum Type, ILHANDLE File) +{ + if (File == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + switch (Type) + { + #ifndef IL_NO_TGA + case IL_TGA: + return ilIsValidTgaF(File); + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + return ilIsValidJpegF(File); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilIsValidDdsF(File); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilIsValidPngF(File); + #endif + + #ifndef IL_NO_BMP + case IL_BMP: + return ilIsValidBmpF(File); + #endif + + #ifndef IL_NO_DICOM + case IL_DICOM: + return ilIsValidDicomF(File); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilIsValidExrF(File); + #endif + + #ifndef IL_NO_GIF + case IL_GIF: + return ilIsValidGifF(File); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilIsValidHdrF(File); + #endif + + #ifndef IL_NO_ICNS + case IL_ICNS: + return ilIsValidIcnsF(File); + #endif + + #ifndef IL_NO_IWI + case IL_IWI: + return ilIsValidIwiF(File); + #endif + + #ifndef IL_NO_ILBM + case IL_ILBM: + return ilIsValidIlbmF(File); + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilIsValidJp2F(File); + #endif + + #ifndef IL_NO_KTX + case IL_KTX: + return ilIsValidKtxF(File); + #endif + + #ifndef IL_NO_LIF + case IL_LIF: + return ilIsValidLifF(File); + #endif + + #ifndef IL_NO_MDL + case IL_MDL: + return ilIsValidMdlF(File); + #endif + + #ifndef IL_NO_MP3 + case IL_MP3: + return ilIsValidMp3F(File); + #endif + + #ifndef IL_NO_PCX + case IL_PCX: + return ilIsValidPcxF(File); + #endif + + #ifndef IL_NO_PIC + case IL_PIC: + return ilIsValidPicF(File); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilIsValidPnmF(File); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilIsValidPsdF(File); + #endif + + #ifndef IL_NO_PSP + case IL_PSP: + return ilIsValidPspF(File); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilIsValidSgiF(File); + #endif + + #ifndef IL_NO_SUN + case IL_SUN: + return ilIsValidSunF(File); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilIsValidTiffF(File); + #endif + + #ifndef IL_NO_TPL + case IL_TPL: + return ilIsValidTplF(File); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilIsValidVtfF(File); + #endif + + #ifndef IL_NO_XPM + case IL_XPM: + return ilIsValidXpmF(File); + #endif + } + + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; +} + + +ILboolean ILAPIENTRY ilIsValidL(ILenum Type, void *Lump, ILuint Size) +{ + if (Lump == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + switch (Type) + { + #ifndef IL_NO_TGA + case IL_TGA: + return ilIsValidTgaL(Lump, Size); + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + return ilIsValidJpegL(Lump, Size); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilIsValidDdsL(Lump, Size); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilIsValidPngL(Lump, Size); + #endif + + #ifndef IL_NO_BMP + case IL_BMP: + return ilIsValidBmpL(Lump, Size); + #endif + + #ifndef IL_NO_DICOM + case IL_DICOM: + return ilIsValidDicomL(Lump, Size); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilIsValidExrL(Lump, Size); + #endif + + #ifndef IL_NO_GIF + case IL_GIF: + return ilIsValidGifL(Lump, Size); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilIsValidHdrL(Lump, Size); + #endif + + #ifndef IL_NO_ICNS + case IL_ICNS: + return ilIsValidIcnsL(Lump, Size); + #endif + + #ifndef IL_NO_IWI + case IL_IWI: + return ilIsValidIwiL(Lump, Size); + #endif + + #ifndef IL_NO_ILBM + case IL_ILBM: + return ilIsValidIlbmL(Lump, Size); + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilIsValidJp2L(Lump, Size); + #endif + + #ifndef IL_NO_KTX + case IL_KTX: + return ilIsValidKtxL(Lump, Size); + #endif + + #ifndef IL_NO_LIF + case IL_LIF: + return ilIsValidLifL(Lump, Size); + #endif + + #ifndef IL_NO_MDL + case IL_MDL: + return ilIsValidMdlL(Lump, Size); + #endif + + #ifndef IL_NO_MP3 + case IL_MP3: + return ilIsValidMp3L(Lump, Size); + #endif + + #ifndef IL_NO_PCX + case IL_PCX: + return ilIsValidPcxL(Lump, Size); + #endif + + #ifndef IL_NO_PIC + case IL_PIC: + return ilIsValidPicL(Lump, Size); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilIsValidPnmL(Lump, Size); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilIsValidPsdL(Lump, Size); + #endif + + #ifndef IL_NO_PSP + case IL_PSP: + return ilIsValidPspL(Lump, Size); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilIsValidSgiL(Lump, Size); + #endif + + #ifndef IL_NO_SUN + case IL_SUN: + return ilIsValidSunL(Lump, Size); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilIsValidTiffL(Lump, Size); + #endif + + #ifndef IL_NO_TPL + case IL_TPL: + return ilIsValidTplL(Lump, Size); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilIsValidVtfL(Lump, Size); + #endif + + #ifndef IL_NO_XPM + case IL_XPM: + return ilIsValidXpmL(Lump, Size); + #endif + } + + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; +} + + +//! Attempts to load an image from a file. The file format is specified by the user. +/*! \param Type Format of this file. Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS, + IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS, + IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG, + IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIF, IL_TPL, + IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN. + If IL_TYPE_UNKNOWN is specified, ilLoad will try to determine the type of the file and load it. + \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives + the filename of the file to load. + \return Boolean value of failure or success. Returns IL_FALSE if all three loading methods + have been tried and failed.*/ +ILboolean ILAPIENTRY ilLoad(ILenum Type, ILconst_string FileName) +{ + ILboolean bRet; + + if (FileName == NULL || ilStrLen(FileName) < 1) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + switch (Type) + { + case IL_TYPE_UNKNOWN: + bRet = ilLoadImage(FileName); + break; + + #ifndef IL_NO_TGA + case IL_TGA: + bRet = ilLoadTarga(FileName); + break; + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + bRet = ilLoadJpeg(FileName); + break; + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + bRet = ilLoadJp2(FileName); + break; + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + bRet = ilLoadDds(FileName); + break; + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + bRet = ilLoadPng(FileName); + break; + #endif + + #ifndef IL_NO_BLP + case IL_BLP: + bRet = ilLoadBlp(FileName); + break; + #endif + + #ifndef IL_NO_BMP + case IL_BMP: + bRet = ilLoadBmp(FileName); + break; + #endif + + #ifndef IL_NO_DPX + case IL_DPX: + bRet = ilLoadDpx(FileName); + break; + #endif + + #ifndef IL_NO_GIF + case IL_GIF: + bRet = ilLoadGif(FileName); + break; + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + bRet = ilLoadHdr(FileName); + break; + #endif + + #ifndef IL_NO_CUT + case IL_CUT: + bRet = ilLoadCut(FileName); + break; + #endif + + #ifndef IL_NO_DICOM + case IL_DICOM: + bRet = ilLoadDicom(FileName); + break; + #endif + + #ifndef IL_NO_DOOM + case IL_DOOM: + bRet = ilLoadDoom(FileName); + break; + case IL_DOOM_FLAT: + bRet = ilLoadDoomFlat(FileName); + break; + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + bRet = ilLoadExr(FileName); + break; + #endif + + #ifndef IL_NO_FITS + case IL_FITS: + bRet = ilLoadFits(FileName); + break; + #endif + + #ifndef IL_NO_FTX + case IL_FTX: + bRet = ilLoadFtx(FileName); + break; + #endif + + #ifndef IL_NO_ICO + case IL_ICO: + bRet = ilLoadIcon(FileName); + break; + #endif + + #ifndef IL_NO_ICNS + case IL_ICNS: + bRet = ilLoadIcns(FileName); + break; + #endif + + #ifndef IL_NO_IFF + case IL_IFF: + bRet = ilLoadIff(FileName); + break; + #endif + + #ifndef IL_NO_ILBM + case IL_ILBM: + bRet = ilLoadIlbm(FileName); + break; + #endif + + #ifndef IL_NO_IWI + case IL_IWI: + bRet = ilLoadIwi(FileName); + break; + #endif + + #ifndef IL_NO_KTX + case IL_KTX: + bRet = ilLoadKtx(FileName); + break; + #endif + + #ifndef IL_NO_LIF + case IL_LIF: + bRet = ilLoadLif(FileName); + break; + #endif + + #ifndef IL_NO_MDL + case IL_MDL: + bRet = ilLoadMdl(FileName); + break; + #endif + + #ifndef IL_NO_MNG + case IL_MNG: + bRet = ilLoadMng(FileName); + break; + #endif + + #ifndef IL_NO_MP3 + case IL_MP3: + bRet = ilLoadMp3(FileName); + break; + #endif + + #ifndef IL_NO_PCD + case IL_PCD: + ilLoadPcd(FileName); + break; + #endif + + #ifndef IL_NO_PCX + case IL_PCX: + bRet = ilLoadPcx(FileName); + break; + #endif + + #ifndef IL_NO_PIC + case IL_PIC: + bRet = ilLoadPic(FileName); + break; + #endif + + #ifndef IL_NO_PIX + case IL_PIX: + bRet = ilLoadPix(FileName); + break; + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + bRet = ilLoadPnm(FileName); + break; + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + bRet = ilLoadPsd(FileName); + break; + #endif + + #ifndef IL_NO_PSP + case IL_PSP: + bRet = ilLoadPsp(FileName); + break; + #endif + + #ifndef IL_NO_PXR + case IL_PXR: + bRet = ilLoadPxr(FileName); + break; + #endif + + #ifndef IL_NO_RAW + case IL_RAW: + bRet = ilLoadRaw(FileName); + break; + #endif + + #ifndef IL_NO_ROT + case IL_ROT: + bRet = ilLoadRot(FileName); + break; + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + bRet = ilLoadSgi(FileName); + break; + #endif + + #ifndef IL_NO_SUN + case IL_SUN: + bRet = ilLoadSun(FileName); + break; + #endif + + #ifndef IL_NO_TEXTURE + case IL_TEXTURE: + bRet = ilLoadTexture(FileName); + break; + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + bRet = ilLoadTiff(FileName); + break; + #endif + + #ifndef IL_NO_TPL + case IL_TPL: + bRet = ilLoadTpl(FileName); + break; + #endif + + #ifndef IL_NO_UTX + case IL_UTX: + bRet = ilLoadUtx(FileName); + break; + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + bRet = ilLoadVtf(FileName); + break; + #endif + + #ifndef IL_NO_WAL + case IL_WAL: + bRet = ilLoadWal(FileName); + break; + #endif + + #ifndef IL_NO_WBMP + case IL_WBMP: + bRet = ilLoadWbmp(FileName); + break; + #endif + + #ifndef IL_NO_XPM + case IL_XPM: + bRet = ilLoadXpm(FileName); + break; + #endif + + #ifndef IL_NO_WDP + case IL_WDP: + bRet = ilLoadWdp(FileName); + break; + #endif + + default: + ilSetError(IL_INVALID_ENUM); + bRet = IL_FALSE; + } + + return bRet; +} + + +//! Attempts to load an image from a file stream. The file format is specified by the user. +/*! \param Type Format of this file. Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS, + IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS, + IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG, + IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIF, IL_TPL, + IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN. + If IL_TYPE_UNKNOWN is specified, ilLoadF will try to determine the type of the file and load it. + \param File File stream to load from. + \return Boolean value of failure or success. Returns IL_FALSE if loading fails.*/ +ILboolean ILAPIENTRY ilLoadF(ILenum Type, ILHANDLE File) +{ + if (File == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (Type == IL_TYPE_UNKNOWN) + Type = ilDetermineTypeF(File); + + switch (Type) + { + case IL_TYPE_UNKNOWN: + return IL_FALSE; + + #ifndef IL_NO_TGA + case IL_TGA: + return ilLoadTargaF(File); + #endif + + #ifndef IL_NO_JPG + #ifndef IL_USE_IJL + case IL_JPG: + return ilLoadJpegF(File); + #endif + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilLoadJp2F(File); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilLoadDdsF(File); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilLoadPngF(File); + #endif + + #ifndef IL_NO_BLP + case IL_BLP: + return ilLoadBlpF(File); + #endif + + #ifndef IL_NO_BMP + case IL_BMP: + return ilLoadBmpF(File); + #endif + + #ifndef IL_NO_CUT + case IL_CUT: + return ilLoadCutF(File); + #endif + + #ifndef IL_NO_DICOM + case IL_DICOM: + return ilLoadDicomF(File); + #endif + + #ifndef IL_NO_DOOM + case IL_DOOM: + return ilLoadDoomF(File); + case IL_DOOM_FLAT: + return ilLoadDoomFlatF(File); + #endif + + #ifndef IL_NO_DPX + case IL_DPX: + return ilLoadDpxF(File); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilLoadExrF(File); + #endif + + #ifndef IL_NO_FITS + case IL_FITS: + return ilLoadFitsF(File); + #endif + + #ifndef IL_NO_FTX + case IL_FTX: + return ilLoadFtxF(File); + #endif + + #ifndef IL_NO_GIF + case IL_GIF: + return ilLoadGifF(File); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilLoadHdrF(File); + #endif + + #ifndef IL_NO_ICO + case IL_ICO: + return ilLoadIconF(File); + #endif + + #ifndef IL_NO_ICNS + case IL_ICNS: + return ilLoadIcnsF(File); + #endif + + #ifndef IL_NO_IFF + case IL_IFF: + return ilLoadIffF(File); + #endif + + #ifndef IL_NO_ILBM + case IL_ILBM: + return ilLoadIlbmF(File); + #endif + + #ifndef IL_NO_IWI + case IL_IWI: + return ilLoadIwiF(File); + #endif + + #ifndef IL_NO_KTX + case IL_KTX: + return ilLoadKtxF(File); + #endif + + #ifndef IL_NO_LIF + case IL_LIF: + return ilLoadLifF(File); + #endif + + #ifndef IL_NO_MDL + case IL_MDL: + return ilLoadMdlF(File); + #endif + + #ifndef IL_NO_MNG + case IL_MNG: + return ilLoadMngF(File); + #endif + + #ifndef IL_NO_MP3 + case IL_MP3: + return ilLoadMp3F(File); + #endif + + #ifndef IL_NO_PCD + case IL_PCD: + return ilLoadPcdF(File); + #endif + + #ifndef IL_NO_PCX + case IL_PCX: + return ilLoadPcxF(File); + #endif + + #ifndef IL_NO_PIC + case IL_PIC: + return ilLoadPicF(File); + #endif + + #ifndef IL_NO_PIX + case IL_PIX: + return ilLoadPixF(File); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilLoadPnmF(File); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilLoadPsdF(File); + #endif + + #ifndef IL_NO_PSP + case IL_PSP: + return ilLoadPspF(File); + #endif + + #ifndef IL_NO_PXR + case IL_PXR: + return ilLoadPxrF(File); + #endif + + #ifndef IL_NO_RAW + case IL_RAW: + return ilLoadRawF(File); + #endif + + #ifndef IL_NO_ROT + case IL_ROT: + return ilLoadRotF(File); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilLoadSgiF(File); + #endif + + #ifndef IL_NO_SUN + case IL_SUN: + return ilLoadSunF(File); + #endif + + #ifndef IL_NO_TEXTURE + case IL_TEXTURE: + return ilLoadTextureF(File); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilLoadTiffF(File); + #endif + + #ifndef IL_NO_TPL + case IL_TPL: + return ilLoadTplF(File); + #endif + + #ifndef IL_NO_UTX + case IL_UTX: + return ilLoadUtxF(File); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilLoadVtfF(File); + #endif + + #ifndef IL_NO_WAL + case IL_WAL: + return ilLoadWalF(File); + #endif + + #ifndef IL_NO_WBMP + case IL_WBMP: + return ilLoadWbmpF(File); + #endif + + #ifndef IL_NO_XPM + case IL_XPM: + return ilLoadXpmF(File); + #endif + } + + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; +} + + +//! Attempts to load an image from a memory buffer. The file format is specified by the user. +/*! \param Type Format of this file. Acceptable values are IL_BLP, IL_BMP, IL_CUT, IL_DCX, IL_DDS, + IL_DICOM, IL_DOOM, IL_DOOM_FLAT, IL_DPX, IL_EXR, IL_FITS, IL_FTX, IL_GIF, IL_HDR, IL_ICO, IL_ICNS, + IL_IFF, IL_IWI, IL_JP2, IL_JPG, IL_LIF, IL_MDL, IL_MNG, IL_MP3, IL_PCD, IL_PCX, IL_PIX, IL_PNG, + IL_PNM, IL_PSD, IL_PSP, IL_PXR, IL_ROT, IL_SGI, IL_SUN, IL_TEXTURE, IL_TGA, IL_TIF, IL_TPL, + IL_UTX, IL_VTF, IL_WAL, IL_WBMP, IL_XPM, IL_RAW, IL_JASC_PAL and IL_TYPE_UNKNOWN. + If IL_TYPE_UNKNOWN is specified, ilLoadL will try to determine the type of the file and load it. + \param Lump The buffer where the file data is located + \param Size Size of the buffer + \return Boolean value of failure or success. Returns IL_FALSE if loading fails.*/ +ILboolean ILAPIENTRY ilLoadL(ILenum Type, const void *Lump, ILuint Size) +{ + if (Lump == NULL || Size == 0) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (Type == IL_TYPE_UNKNOWN) + Type = ilDetermineTypeL(Lump, Size); + + switch (Type) + { + case IL_TYPE_UNKNOWN: + return IL_FALSE; + + #ifndef IL_NO_TGA + case IL_TGA: + return ilLoadTargaL(Lump, Size); + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + return ilLoadJpegL(Lump, Size); + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilLoadJp2L(Lump, Size); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilLoadDdsL(Lump, Size); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilLoadPngL(Lump, Size); + #endif + + #ifndef IL_NO_BLP + case IL_BLP: + return ilLoadBlpL(Lump, Size); + #endif + + #ifndef IL_NO_BMP + case IL_BMP: + return ilLoadBmpL(Lump, Size); + #endif + + #ifndef IL_NO_CUT + case IL_CUT: + return ilLoadCutL(Lump, Size); + #endif + + #ifndef IL_NO_DICOM + case IL_DICOM: + return ilLoadDicomL(Lump, Size); + #endif + + #ifndef IL_NO_DOOM + case IL_DOOM: + return ilLoadDoomL(Lump, Size); + case IL_DOOM_FLAT: + return ilLoadDoomFlatL(Lump, Size); + #endif + + #ifndef IL_NO_DPX + case IL_DPX: + return ilLoadDpxL(Lump, Size); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilLoadExrL(Lump, Size); + #endif + + #ifndef IL_NO_FITS + case IL_FITS: + return ilLoadFitsL(Lump, Size); + #endif + + #ifndef IL_NO_FTX + case IL_FTX: + return ilLoadFtxL(Lump, Size); + #endif + + #ifndef IL_NO_GIF + case IL_GIF: + return ilLoadGifL(Lump, Size); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilLoadHdrL(Lump, Size); + #endif + + #ifndef IL_NO_ICO + case IL_ICO: + return ilLoadIconL(Lump, Size); + #endif + + #ifndef IL_NO_ICNS + case IL_ICNS: + return ilLoadIcnsL(Lump, Size); + #endif + + #ifndef IL_NO_IFF + case IL_IFF: + return ilLoadIffL(Lump, Size); + #endif + + #ifndef IL_NO_ILBM + case IL_ILBM: + return ilLoadIlbmL(Lump, Size); + #endif + + #ifndef IL_NO_IWI + case IL_IWI: + return ilLoadIwiL(Lump, Size); + #endif + + #ifndef IL_NO_KTX + case IL_KTX: + return ilLoadKtxL(Lump, Size); + #endif + + #ifndef IL_NO_LIF + case IL_LIF: + return ilLoadLifL(Lump, Size); + #endif + + #ifndef IL_NO_MDL + case IL_MDL: + return ilLoadMdlL(Lump, Size); + #endif + + #ifndef IL_NO_MNG + case IL_MNG: + return ilLoadMngL(Lump, Size); + #endif + + #ifndef IL_NO_MP3 + case IL_MP3: + return ilLoadMp3L(Lump, Size); + #endif + + #ifndef IL_NO_PCD + case IL_PCD: + return ilLoadPcdL(Lump, Size); + #endif + + #ifndef IL_NO_PCX + case IL_PCX: + return ilLoadPcxL(Lump, Size); + #endif + + #ifndef IL_NO_PIC + case IL_PIC: + return ilLoadPicL(Lump, Size); + #endif + + #ifndef IL_NO_PIX + case IL_PIX: + return ilLoadPixL(Lump, Size); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilLoadPnmL(Lump, Size); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilLoadPsdL(Lump, Size); + #endif + + #ifndef IL_NO_PSP + case IL_PSP: + return ilLoadPspL(Lump, Size); + #endif + + #ifndef IL_NO_PXR + case IL_PXR: + return ilLoadPxrL(Lump, Size); + #endif + + #ifndef IL_NO_RAW + case IL_RAW: + return ilLoadRawL(Lump, Size); + #endif + + #ifndef IL_NO_ROT + case IL_ROT: + return ilLoadRotL(Lump, Size); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilLoadSgiL(Lump, Size); + #endif + + #ifndef IL_NO_SUN + case IL_SUN: + return ilLoadSunL(Lump, Size); + #endif + + #ifndef IL_NO_TEXTURE + case IL_TEXTURE: + return ilLoadTextureL(Lump, Size); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilLoadTiffL(Lump, Size); + #endif + + #ifndef IL_NO_TPL + case IL_TPL: + return ilLoadTplL(Lump, Size); + #endif + + #ifndef IL_NO_UTX + case IL_UTX: + return ilLoadUtxL(Lump, Size); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilLoadVtfL(Lump, Size); + #endif + + #ifndef IL_NO_WAL + case IL_WAL: + return ilLoadWalL(Lump, Size); + #endif + + #ifndef IL_NO_WBMP + case IL_WBMP: + return ilLoadWbmpL(Lump, Size); + #endif + + #ifndef IL_NO_XPM + case IL_XPM: + return ilLoadXpmL(Lump, Size); + #endif + } + + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; +} + + +//! Attempts to load an image from a file with various different methods before failing - very generic. +/*! The ilLoadImage function allows a general interface to the specific internal file-loading + routines. First, it finds the extension and checks to see if any user-registered functions + (registered through ilRegisterLoad) match the extension. If nothing matches, it takes the + extension and determines which function to call based on it. Lastly, it attempts to identify + the image based on various image header verification functions, such as ilIsValidPngF. + If all this checking fails, IL_FALSE is returned with no modification to the current bound image. + \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives + the filename of the file to load. + \return Boolean value of failure or success. Returns IL_FALSE if all three loading methods + have been tried and failed.*/ +ILboolean ILAPIENTRY ilLoadImage(ILconst_string FileName) +{ + ILstring Ext; + ILenum Type; + ILboolean bRet = IL_FALSE; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (FileName == NULL || ilStrLen(FileName) < 1) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + Ext = iGetExtension(FileName); + + // Try registered procedures first (so users can override default lib functions). + if (Ext) { + if (iRegisterLoad(FileName)) + return IL_TRUE; + + #ifndef IL_NO_TGA + if (!iStrCmp(Ext, IL_TEXT("tga")) || !iStrCmp(Ext, IL_TEXT("vda")) || + !iStrCmp(Ext, IL_TEXT("icb")) || !iStrCmp(Ext, IL_TEXT("vst"))) { + bRet = ilLoadTarga(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_JPG + if (!iStrCmp(Ext, IL_TEXT("jpg")) || !iStrCmp(Ext, IL_TEXT("jpe")) || + !iStrCmp(Ext, IL_TEXT("jpeg")) || !iStrCmp(Ext, IL_TEXT("jif")) || !iStrCmp(Ext, IL_TEXT("jfif"))) { + bRet = ilLoadJpeg(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_JP2 + if (!iStrCmp(Ext, IL_TEXT("jp2")) || !iStrCmp(Ext, IL_TEXT("jpx")) || + !iStrCmp(Ext, IL_TEXT("j2k")) || !iStrCmp(Ext, IL_TEXT("j2c"))) { + bRet = ilLoadJp2(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_DDS + if (!iStrCmp(Ext, IL_TEXT("dds"))) { + bRet = ilLoadDds(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PNG + if (!iStrCmp(Ext, IL_TEXT("png"))) { + bRet = ilLoadPng(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_BMP + if (!iStrCmp(Ext, IL_TEXT("bmp")) || !iStrCmp(Ext, IL_TEXT("dib"))) { + bRet = ilLoadBmp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_BLP + if (!iStrCmp(Ext, IL_TEXT("blp"))) { + bRet = ilLoadBlp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_DPX + if (!iStrCmp(Ext, IL_TEXT("dpx"))) { + bRet = ilLoadDpx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_EXR + if (!iStrCmp(Ext, IL_TEXT("exr"))) { + bRet = ilLoadExr(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_GIF + if (!iStrCmp(Ext, IL_TEXT("gif"))) { + bRet = ilLoadGif(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_HDR + if (!iStrCmp(Ext, IL_TEXT("hdr"))) { + bRet = ilLoadHdr(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_CUT + if (!iStrCmp(Ext, IL_TEXT("cut"))) { + bRet = ilLoadCut(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_DCX + if (!iStrCmp(Ext, IL_TEXT("dcx"))) { + bRet = ilLoadDcx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_DICOM + if (!iStrCmp(Ext, IL_TEXT("dicom")) || !iStrCmp(Ext, IL_TEXT("dcm"))) { + bRet = ilLoadDicom(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_FITS + if (!iStrCmp(Ext, IL_TEXT("fits")) || !iStrCmp(Ext, IL_TEXT("fit"))) { + bRet = ilLoadFits(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_FTX + if (!iStrCmp(Ext, IL_TEXT("ftx"))) { + bRet = ilLoadFtx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_ICO + if (!iStrCmp(Ext, IL_TEXT("ico")) || !iStrCmp(Ext, IL_TEXT("cur"))) { + bRet = ilLoadIcon(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_ICNS + if (!iStrCmp(Ext, IL_TEXT("icns"))) { + bRet = ilLoadIcns(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_IFF + if (!iStrCmp(Ext, IL_TEXT("iff"))) { + bRet = ilLoadIff(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_ILBM + if (!iStrCmp(Ext, IL_TEXT("ilbm")) || !iStrCmp(Ext, IL_TEXT("lbm")) || + !iStrCmp(Ext, IL_TEXT("ham")) ) { + bRet = ilLoadIlbm(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_IWI + if (!iStrCmp(Ext, IL_TEXT("iwi"))) { + bRet = ilLoadIwi(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_KTX + if (!iStrCmp(Ext, IL_TEXT("ktx"))) { + bRet = ilLoadKtx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_LIF + if (!iStrCmp(Ext, IL_TEXT("lif"))) { + bRet = ilLoadLif(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_MDL + if (!iStrCmp(Ext, IL_TEXT("mdl"))) { + bRet = ilLoadMdl(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_MNG + if (!iStrCmp(Ext, IL_TEXT("mng")) || !iStrCmp(Ext, IL_TEXT("jng"))) { + bRet = ilLoadMng(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_MP3 + if (!iStrCmp(Ext, IL_TEXT("mp3"))) { + bRet = ilLoadMp3(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PCD + if (!iStrCmp(Ext, IL_TEXT("pcd"))) { + bRet = ilLoadPcd(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PCX + if (!iStrCmp(Ext, IL_TEXT("pcx"))) { + bRet = ilLoadPcx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PIC + if (!iStrCmp(Ext, IL_TEXT("pic"))) { + bRet = ilLoadPic(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PIX + if (!iStrCmp(Ext, IL_TEXT("pix"))) { + bRet = ilLoadPix(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PNM + if (!iStrCmp(Ext, IL_TEXT("pbm"))) { + bRet = ilLoadPnm(FileName); + goto finish; + } + if (!iStrCmp(Ext, IL_TEXT("pgm"))) { + bRet = ilLoadPnm(FileName); + goto finish; + } + if (!iStrCmp(Ext, IL_TEXT("pnm"))) { + bRet = ilLoadPnm(FileName); + goto finish; + } + if (!iStrCmp(Ext, IL_TEXT("ppm"))) { + bRet = ilLoadPnm(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PSD + if (!iStrCmp(Ext, IL_TEXT("psd")) || !iStrCmp(Ext, IL_TEXT("pdd"))) { + bRet = ilLoadPsd(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PSP + if (!iStrCmp(Ext, IL_TEXT("psp"))) { + bRet = ilLoadPsp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PXR + if (!iStrCmp(Ext, IL_TEXT("pxr"))) { + bRet = ilLoadPxr(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_ROT + if (!iStrCmp(Ext, IL_TEXT("rot"))) { + bRet = ilLoadRot(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_SGI + if (!iStrCmp(Ext, IL_TEXT("sgi")) || !iStrCmp(Ext, IL_TEXT("bw")) || + !iStrCmp(Ext, IL_TEXT("rgb")) || !iStrCmp(Ext, IL_TEXT("rgba"))) { + bRet = ilLoadSgi(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_SUN + if (!iStrCmp(Ext, IL_TEXT("sun")) || !iStrCmp(Ext, IL_TEXT("ras")) || + !iStrCmp(Ext, IL_TEXT("rs")) || !iStrCmp(Ext, IL_TEXT("im1")) || + !iStrCmp(Ext, IL_TEXT("im8")) || !iStrCmp(Ext, IL_TEXT("im24")) || + !iStrCmp(Ext, IL_TEXT("im32"))) { + bRet = ilLoadSun(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_TEXTURE + if (!iStrCmp(Ext, IL_TEXT("texture"))) { + bRet = ilLoadTexture(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_TIF + if (!iStrCmp(Ext, IL_TEXT("tif")) || !iStrCmp(Ext, IL_TEXT("tiff"))) { + bRet = ilLoadTiff(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_TPL + if (!iStrCmp(Ext, IL_TEXT("tpl"))) { + bRet = ilLoadTpl(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_UTX + if (!iStrCmp(Ext, IL_TEXT("utx"))) { + bRet = ilLoadUtx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_VTF + if (!iStrCmp(Ext, IL_TEXT("vtf"))) { + bRet = ilLoadVtf(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_WAL + if (!iStrCmp(Ext, IL_TEXT("wal"))) { + bRet = ilLoadWal(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_WBMP + if (!iStrCmp(Ext, IL_TEXT("wbmp"))) { + bRet = ilLoadWbmp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_WDP + if (!iStrCmp(Ext, IL_TEXT("wdp")) || !iStrCmp(Ext, IL_TEXT("hdp")) ) { + bRet = ilLoadWdp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_XPM + if (!iStrCmp(Ext, IL_TEXT("xpm"))) { + bRet = ilLoadXpm(FileName); + goto finish; + } + #endif + } + + // As a last-ditch effort, try to identify the image + Type = ilDetermineType(FileName); + if (Type == IL_TYPE_UNKNOWN) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + return ilLoad(Type, FileName); + +finish: + return bRet; +} + + +//! Attempts to save an image to a file. The file format is specified by the user. +/*! \param Type Format of this file. Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR, + IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIF, + IL_VTF, IL_WBMP and IL_JASC_PAL. + \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives + the filename to save to. + \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ +ILboolean ILAPIENTRY ilSave(ILenum Type, ILconst_string FileName) +{ + switch (Type) + { + case IL_TYPE_UNKNOWN: + return ilSaveImage(FileName); + + #ifndef IL_NO_BMP + case IL_BMP: + return ilSaveBmp(FileName); + #endif + + #ifndef IL_NO_CHEAD + case IL_CHEAD: + return ilSaveCHeader(FileName, "IL_IMAGE"); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilSaveDds(FileName); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilSaveExr(FileName); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilSaveHdr(FileName); + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilSaveJp2(FileName); + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + return ilSaveJpeg(FileName); + #endif + + /*#ifndef IL_NO_KTX + case IL_KTX: + return ilSaveKtx(FileName); + #endif*/ + + #ifndef IL_NO_PCX + case IL_PCX: + return ilSavePcx(FileName); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilSavePng(FileName); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilSavePnm(FileName); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilSavePsd(FileName); + #endif + + #ifndef IL_NO_RAW + case IL_RAW: + return ilSaveRaw(FileName); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilSaveSgi(FileName); + #endif + + #ifndef IL_NO_TGA + case IL_TGA: + return ilSaveTarga(FileName); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilSaveTiff(FileName); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilSaveVtf(FileName); + #endif + + #ifndef IL_NO_WBMP + case IL_WBMP: + return ilSaveWbmp(FileName); + #endif + + case IL_JASC_PAL: + return ilSaveJascPal(FileName); + } + + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; +} + + +//! Attempts to save an image to a file stream. The file format is specified by the user. +/*! \param Type Format of this file. Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR, + IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIF, + IL_VTF, IL_WBMP and IL_JASC_PAL. + \param File File stream to save to. + \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ +ILuint ILAPIENTRY ilSaveF(ILenum Type, ILHANDLE File) +{ + ILboolean Ret; + + if (File == NULL) { + ilSetError(IL_INVALID_PARAM); + return 0; + } + + switch (Type) + { + #ifndef IL_NO_BMP + case IL_BMP: + Ret = ilSaveBmpF(File); + break; + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + Ret = ilSaveDdsF(File); + break; + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + Ret = ilSaveExrF(File); + break; + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + Ret = ilSaveHdrF(File); + break; + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + Ret = ilSaveJp2F(File); + break; + #endif + + #ifndef IL_NO_JPG + #ifndef IL_USE_IJL + case IL_JPG: + Ret = ilSaveJpegF(File); + break; + #endif + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + Ret = ilSavePnmF(File); + break; + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + Ret = ilSavePngF(File); + break; + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + Ret = ilSavePsdF(File); + break; + #endif + + #ifndef IL_NO_RAW + case IL_RAW: + Ret = ilSaveRawF(File); + break; + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + Ret = ilSaveSgiF(File); + break; + #endif + + #ifndef IL_NO_TGA + case IL_TGA: + Ret = ilSaveTargaF(File); + break; + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + Ret = ilSaveVtfF(File); + break; + #endif + + #ifndef IL_NO_WBMP + case IL_WBMP: + Ret = ilSaveWbmpF(File); + break; + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + Ret = ilSaveTiffF(File); + break; + #endif + + default: + ilSetError(IL_INVALID_ENUM); + return 0; + } + + if (Ret == IL_FALSE) + return 0; + + return itellw(); +} + + +//! Attempts to save an image to a memory buffer. The file format is specified by the user. +/*! \param Type Format of this image file. Acceptable values are IL_BMP, IL_CHEAD, IL_DDS, IL_EXR, + IL_HDR, IL_JP2, IL_JPG, IL_PCX, IL_PNG, IL_PNM, IL_PSD, IL_RAW, IL_SGI, IL_TGA, IL_TIF, + IL_VTF, IL_WBMP and IL_JASC_PAL. + \param Lump Memory buffer to save to + \param Size Size of the memory buffer + \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ +ILuint ILAPIENTRY ilSaveL(ILenum Type, void *Lump, ILuint Size) +{ + if (Lump == NULL) { + if (Size != 0) { + ilSetError(IL_INVALID_PARAM); + return 0; + } + // The user wants to know how large of a buffer they need. + else { + return ilDetermineSize(Type); + } + } + + switch (Type) + { + #ifndef IL_NO_BMP + case IL_BMP: + return ilSaveBmpL(Lump, Size); + #endif + + #ifndef IL_NO_EXR + case IL_EXR: + return ilSaveExrL(Lump, Size); + #endif + + #ifndef IL_NO_HDR + case IL_HDR: + return ilSaveHdrL(Lump, Size); + #endif + + #ifndef IL_NO_JP2 + case IL_JP2: + return ilSaveJp2L(Lump, Size); + #endif + + #ifndef IL_NO_JPG + case IL_JPG: + return ilSaveJpegL(Lump, Size); + #endif + + #ifndef IL_NO_PNG + case IL_PNG: + return ilSavePngL(Lump, Size); + #endif + + #ifndef IL_NO_PNM + case IL_PNM: + return ilSavePnmL(Lump, Size); + #endif + + #ifndef IL_NO_PSD + case IL_PSD: + return ilSavePsdL(Lump, Size); + #endif + + #ifndef IL_NO_RAW + case IL_RAW: + return ilSaveRawL(Lump, Size); + #endif + + #ifndef IL_NO_SGI + case IL_SGI: + return ilSaveSgiL(Lump, Size); + #endif + + #ifndef IL_NO_TGA + case IL_TGA: + return ilSaveTargaL(Lump, Size); + #endif + + #ifndef IL_NO_DDS + case IL_DDS: + return ilSaveDdsL(Lump, Size); + #endif + + #ifndef IL_NO_VTF + case IL_VTF: + return ilSaveVtfL(Lump, Size); + #endif + + #ifndef IL_NO_WBMP + case IL_WBMP: + return ilSaveWbmpL(Lump, Size); + #endif + + #ifndef IL_NO_TIF + case IL_TIF: + return ilSaveTiffL(Lump, Size); + #endif + } + + ilSetError(IL_INVALID_ENUM); + return 0; +} + + +//! Saves the current image based on the extension given in FileName. +/*! \param FileName Ansi or Unicode string, depending on the compiled version of DevIL, that gives + the filename to save to. + \return Boolean value of failure or success. Returns IL_FALSE if saving failed.*/ +ILboolean ILAPIENTRY ilSaveImage(ILconst_string FileName) +{ + ILstring Ext; + ILboolean bRet = IL_FALSE; + + if (FileName == NULL || ilStrLen(FileName) < 1) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Ext = iGetExtension(FileName); + if (Ext == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + #ifndef IL_NO_BMP + if (!iStrCmp(Ext, IL_TEXT("bmp"))) { + bRet = ilSaveBmp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_CHEAD + if (!iStrCmp(Ext, IL_TEXT("h"))) { + bRet = ilSaveCHeader(FileName, "IL_IMAGE"); + goto finish; + } + #endif + + #ifndef IL_NO_DDS + if (!iStrCmp(Ext, IL_TEXT("dds"))) { + bRet = ilSaveDds(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_EXR + if (!iStrCmp(Ext, IL_TEXT("exr"))) { + bRet = ilSaveExr(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_HDR + if (!iStrCmp(Ext, IL_TEXT("hdr"))) { + bRet = ilSaveHdr(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_JP2 + if (!iStrCmp(Ext, IL_TEXT("jp2"))) { + bRet = ilSaveJp2(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_JPG + if (!iStrCmp(Ext, IL_TEXT("jpg")) || !iStrCmp(Ext, IL_TEXT("jpeg")) || !iStrCmp(Ext, IL_TEXT("jpe"))) { + bRet = ilSaveJpeg(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PCX + if (!iStrCmp(Ext, IL_TEXT("pcx"))) { + bRet = ilSavePcx(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PNG + if (!iStrCmp(Ext, IL_TEXT("png"))) { + bRet = ilSavePng(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PNM // Not sure if binary or ascii should be defaulted...maybe an option? + if (!iStrCmp(Ext, IL_TEXT("pbm"))) { + bRet = ilSavePnm(FileName); + goto finish; + } + if (!iStrCmp(Ext, IL_TEXT("pgm"))) { + bRet = ilSavePnm(FileName); + goto finish; + } + if (!iStrCmp(Ext, IL_TEXT("ppm"))) { + bRet = ilSavePnm(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_PSD + if (!iStrCmp(Ext, IL_TEXT("psd"))) { + bRet = ilSavePsd(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_RAW + if (!iStrCmp(Ext, IL_TEXT("raw"))) { + bRet = ilSaveRaw(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_SGI + if (!iStrCmp(Ext, IL_TEXT("sgi")) || !iStrCmp(Ext, IL_TEXT("bw")) || + !iStrCmp(Ext, IL_TEXT("rgb")) || !iStrCmp(Ext, IL_TEXT("rgba"))) { + bRet = ilSaveSgi(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_TGA + if (!iStrCmp(Ext, IL_TEXT("tga"))) { + bRet = ilSaveTarga(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_TIF + if (!iStrCmp(Ext, IL_TEXT("tif")) || !iStrCmp(Ext, IL_TEXT("tiff"))) { + bRet = ilSaveTiff(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_VTF + if (!iStrCmp(Ext, IL_TEXT("vtf"))) { + bRet = ilSaveVtf(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_WBMP + if (!iStrCmp(Ext, IL_TEXT("wbmp"))) { + bRet = ilSaveWbmp(FileName); + goto finish; + } + #endif + + #ifndef IL_NO_MNG + if (!iStrCmp(Ext, IL_TEXT("mng"))) { + bRet = ilSaveMng(FileName); + goto finish; + } + #endif + + // Check if we just want to save the palette. + if (!iStrCmp(Ext, IL_TEXT("pal"))) { + bRet = ilSavePal(FileName); + goto finish; + } + + // Try registered procedures + if (iRegisterSave(FileName)) + return IL_TRUE; + + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + +finish: + return bRet; +} diff --git a/DevIL/src-IL/src/il_iwi.c b/DevIL/src-IL/src/il_iwi.c deleted file mode 100644 index dac2dfcf..00000000 --- a/DevIL/src-IL/src/il_iwi.c +++ /dev/null @@ -1,401 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/04/2009 -// -// Filename: src-IL/src/il_iwi.c -// -// Description: Reads from an Infinity Ward Image (.iwi) file from Call of Duty. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_IWI -#include "il_dds.h" - -typedef struct IWIHEAD -{ - ILuint Signature; - ILubyte Format; - ILubyte Flags; - ILushort Width; - ILushort Height; -} IWIHEAD; - -#define IWI_ARGB8 0x01 -#define IWI_RGB8 0x02 -#define IWI_ARGB4 0x03 -#define IWI_A8 0x04 -#define IWI_JPG 0x07 -#define IWI_DXT1 0x0B -#define IWI_DXT3 0x0C -#define IWI_DXT5 0x0D - -ILboolean iIsValidIwi(void); -ILboolean iCheckIwi(IWIHEAD *Header); -ILboolean iLoadIwiInternal(void); -ILboolean IwiInitMipmaps(ILimage *BaseImage, ILuint *NumMips); -ILboolean IwiReadImage(ILimage *BaseImage, IWIHEAD *Header, ILuint NumMips); -ILenum IwiGetFormat(ILubyte Format, ILubyte *Bpp); - -//! Checks if the file specified in FileName is a valid IWI file. -ILboolean ilIsValidIwi(ILconst_string FileName) -{ - ILHANDLE IwiFile; - ILboolean bIwi = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("iwi"))) { - ilSetError(IL_INVALID_EXTENSION); - return bIwi; - } - - IwiFile = iopenr(FileName); - if (IwiFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIwi; - } - - bIwi = ilIsValidIwiF(IwiFile); - icloser(IwiFile); - - return bIwi; -} - - -//! Checks if the ILHANDLE contains a valid IWI file at the current position. -ILboolean ilIsValidIwiF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidIwi(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid IWI lump. -ILboolean ilIsValidIwiL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidIwi(); -} - - -// Internal function used to get the IWI header from the current file. -ILboolean iGetIwiHead(IWIHEAD *Header) -{ - Header->Signature = GetLittleUInt(); - Header->Format = igetc(); - Header->Flags = igetc(); //@TODO: Find out what the flags mean. - Header->Width = GetLittleUShort(); - Header->Height = GetLittleUShort(); - - // @TODO: Find out what is in the rest of the header. - iseek(18, IL_SEEK_CUR); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidIwi(void) -{ - IWIHEAD Header; - ILuint Pos = itell(); - - if (!iGetIwiHead(&Header)) - return IL_FALSE; - // The length of the header varies, so we just go back to the original position. - iseek(Pos, IL_SEEK_CUR); - - return iCheckIwi(&Header); -} - - -// Internal function used to check if the HEADER is a valid IWI header. -ILboolean iCheckIwi(IWIHEAD *Header) -{ - if (Header->Signature != 0x06695749 && Header->Signature != 0x05695749) // 'IWi-' (version 6, and version 5 is the second). - return IL_FALSE; - if (Header->Width == 0 || Header->Height == 0) - return IL_FALSE; - // DXT images must have power-of-2 dimensions. - if (Header->Format == IWI_DXT1 || Header->Format == IWI_DXT3 || Header->Format == IWI_DXT5) - if (Header->Width != ilNextPower2(Header->Width) || Header->Height != ilNextPower2(Header->Height)) - return IL_FALSE; - // 0x0B, 0x0C and 0x0D are DXT formats. - if (Header->Format != IWI_ARGB4 && Header->Format != IWI_RGB8 && Header->Format != IWI_ARGB8 && Header->Format != IWI_A8 - && Header->Format != IWI_DXT1 && Header->Format != IWI_DXT3 && Header->Format != IWI_DXT5) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a IWI file -ILboolean ilLoadIwi(ILconst_string FileName) -{ - ILHANDLE IwiFile; - ILboolean bIwi = IL_FALSE; - - IwiFile = iopenr(FileName); - if (IwiFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bIwi; - } - - bIwi = ilLoadIwiF(IwiFile); - icloser(IwiFile); - - return bIwi; -} - - -//! Reads an already-opened IWI file -ILboolean ilLoadIwiF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadIwiInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a IWI -ILboolean ilLoadIwiL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadIwiInternal(); -} - - -// Internal function used to load the IWI. -ILboolean iLoadIwiInternal(void) -{ - IWIHEAD Header; - ILuint NumMips = 0; - ILboolean HasMipmaps = IL_TRUE; - ILenum Format; - ILubyte Bpp; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - // Read the header and check it. - if (!iGetIwiHead(&Header)) - return IL_FALSE; - if (!iCheckIwi(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // From a post by Pointy on http://iwnation.com/forums/index.php?showtopic=27903, - // flags ending with 0x3 have no mipmaps. - HasMipmaps = ((Header.Flags & 0x03) == 0x03) ? IL_FALSE : IL_TRUE; - - // Create the image, then create the mipmaps, then finally read the image. - Format = IwiGetFormat(Header.Format, &Bpp); - if (!ilTexImage(Header.Width, Header.Height, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - if (HasMipmaps) - if (!IwiInitMipmaps(iCurImage, &NumMips)) - return IL_FALSE; - if (!IwiReadImage(iCurImage, &Header, NumMips)) - return IL_FALSE; - - return ilFixImage(); -} - - -// Helper function to convert IWI formats to DevIL formats and Bpp. -ILenum IwiGetFormat(ILubyte Format, ILubyte *Bpp) -{ - switch (Format) - { - case IWI_ARGB8: - *Bpp = 4; - return IL_BGRA; - case IWI_RGB8: - *Bpp = 3; - return IL_BGR; - case IWI_ARGB4: - *Bpp = 4; - return IL_BGRA; - case IWI_A8: - *Bpp = 1; - return IL_ALPHA; - case IWI_DXT1: - *Bpp = 4; - return IL_RGBA; - case IWI_DXT3: - *Bpp = 4; - return IL_RGBA; - case IWI_DXT5: - *Bpp = 4; - return IL_RGBA; - } - - return 0; // Will never reach this. -} - - -// Function to intialize the mipmaps and determine the number of mipmaps. -ILboolean IwiInitMipmaps(ILimage *BaseImage, ILuint *NumMips) -{ - ILimage *Image; - ILuint Width, Height, Mipmap; - - Image = BaseImage; - Width = BaseImage->Width; Height = BaseImage->Height; - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - for (Mipmap = 0; Width != 1 && Height != 1; Mipmap++) { - // 1 is the smallest dimension possible. - Width = (Width >> 1) == 0 ? 1 : (Width >> 1); - Height = (Height >> 1) == 0 ? 1 : (Height >> 1); - - Image->Mipmaps = ilNewImageFull(Width, Height, 1, BaseImage->Bpp, BaseImage->Format, BaseImage->Type, NULL); - if (Image->Mipmaps == NULL) - return IL_FALSE; - Image = Image->Mipmaps; - - // ilNewImage does not set these. - Image->Format = BaseImage->Format; - Image->Type = BaseImage->Type; - // The origin is in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - } - - *NumMips = Mipmap; - return IL_TRUE; -} - - -ILboolean IwiReadImage(ILimage *BaseImage, IWIHEAD *Header, ILuint NumMips) -{ - ILimage *Image; - ILuint SizeOfData; - ILubyte *CompData = NULL; - ILint i, j, k, m; - - for (i = NumMips; i >= 0; i--) { - Image = BaseImage; - // Go to the ith mipmap level. - // The mipmaps go from smallest to the largest. - for (j = 0; j < i; j++) - Image = Image->Mipmaps; - - switch (Header->Format) - { - case IWI_ARGB8: // These are all - case IWI_RGB8: // uncompressed data, - case IWI_A8: // so just read it. - if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) - return IL_FALSE; - break; - - case IWI_ARGB4: //@TODO: Find some test images for this. - // Data is in ARGB4 format - 4 bits per component. - SizeOfData = Image->Width * Image->Height * 2; - CompData = ialloc(SizeOfData); // Not really compressed - just in ARGB4 format. - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - ifree(CompData); - return IL_FALSE; - } - for (k = 0, m = 0; k < (ILint)Image->SizeOfData; k += 4, m += 2) { - // @TODO: Double the image data into the low and high nibbles for a better range of values. - Image->Data[k+0] = CompData[m] & 0xF0; - Image->Data[k+1] = (CompData[m] & 0x0F) << 4; - Image->Data[k+2] = CompData[m+1] & 0xF0; - Image->Data[k+3] = (CompData[m+1] & 0x0F) << 4; - } - break; - - case IWI_DXT1: - // DXT1 data has at least 8 bytes, even for one pixel. - SizeOfData = IL_MAX(Image->Width * Image->Height / 2, 8); - CompData = ialloc(SizeOfData); // Gives a 6:1 compression ratio (or 8:1 for DXT1 with alpha) - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - ifree(CompData); - return IL_FALSE; - } - - // Decompress the DXT1 data into Image (ith mipmap). - if (!DecompressDXT1(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - - // Keep a copy of the DXTC data if the user wants it. - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = SizeOfData; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT1; - CompData = NULL; - } - - break; - - case IWI_DXT3: - // DXT3 data has at least 16 bytes, even for one pixel. - SizeOfData = IL_MAX(Image->Width * Image->Height, 16); - CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - ifree(CompData); - return IL_FALSE; - } - - // Decompress the DXT3 data into Image (ith mipmap). - if (!DecompressDXT3(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - break; - - case IWI_DXT5: - // DXT5 data has at least 16 bytes, even for one pixel. - SizeOfData = IL_MAX(Image->Width * Image->Height, 16); - CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - ifree(CompData); - return IL_FALSE; - } - - // Decompress the DXT5 data into Image (ith mipmap). - if (!DecompressDXT5(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - break; - } - - ifree(CompData); - } - - return IL_TRUE; -} - - -#endif//IL_NO_IWI diff --git a/DevIL/src-IL/src/il_iwi.cpp b/DevIL/src-IL/src/il_iwi.cpp new file mode 100644 index 00000000..dac2dfcf --- /dev/null +++ b/DevIL/src-IL/src/il_iwi.cpp @@ -0,0 +1,401 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/04/2009 +// +// Filename: src-IL/src/il_iwi.c +// +// Description: Reads from an Infinity Ward Image (.iwi) file from Call of Duty. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_IWI +#include "il_dds.h" + +typedef struct IWIHEAD +{ + ILuint Signature; + ILubyte Format; + ILubyte Flags; + ILushort Width; + ILushort Height; +} IWIHEAD; + +#define IWI_ARGB8 0x01 +#define IWI_RGB8 0x02 +#define IWI_ARGB4 0x03 +#define IWI_A8 0x04 +#define IWI_JPG 0x07 +#define IWI_DXT1 0x0B +#define IWI_DXT3 0x0C +#define IWI_DXT5 0x0D + +ILboolean iIsValidIwi(void); +ILboolean iCheckIwi(IWIHEAD *Header); +ILboolean iLoadIwiInternal(void); +ILboolean IwiInitMipmaps(ILimage *BaseImage, ILuint *NumMips); +ILboolean IwiReadImage(ILimage *BaseImage, IWIHEAD *Header, ILuint NumMips); +ILenum IwiGetFormat(ILubyte Format, ILubyte *Bpp); + +//! Checks if the file specified in FileName is a valid IWI file. +ILboolean ilIsValidIwi(ILconst_string FileName) +{ + ILHANDLE IwiFile; + ILboolean bIwi = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("iwi"))) { + ilSetError(IL_INVALID_EXTENSION); + return bIwi; + } + + IwiFile = iopenr(FileName); + if (IwiFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIwi; + } + + bIwi = ilIsValidIwiF(IwiFile); + icloser(IwiFile); + + return bIwi; +} + + +//! Checks if the ILHANDLE contains a valid IWI file at the current position. +ILboolean ilIsValidIwiF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidIwi(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid IWI lump. +ILboolean ilIsValidIwiL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidIwi(); +} + + +// Internal function used to get the IWI header from the current file. +ILboolean iGetIwiHead(IWIHEAD *Header) +{ + Header->Signature = GetLittleUInt(); + Header->Format = igetc(); + Header->Flags = igetc(); //@TODO: Find out what the flags mean. + Header->Width = GetLittleUShort(); + Header->Height = GetLittleUShort(); + + // @TODO: Find out what is in the rest of the header. + iseek(18, IL_SEEK_CUR); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidIwi(void) +{ + IWIHEAD Header; + ILuint Pos = itell(); + + if (!iGetIwiHead(&Header)) + return IL_FALSE; + // The length of the header varies, so we just go back to the original position. + iseek(Pos, IL_SEEK_CUR); + + return iCheckIwi(&Header); +} + + +// Internal function used to check if the HEADER is a valid IWI header. +ILboolean iCheckIwi(IWIHEAD *Header) +{ + if (Header->Signature != 0x06695749 && Header->Signature != 0x05695749) // 'IWi-' (version 6, and version 5 is the second). + return IL_FALSE; + if (Header->Width == 0 || Header->Height == 0) + return IL_FALSE; + // DXT images must have power-of-2 dimensions. + if (Header->Format == IWI_DXT1 || Header->Format == IWI_DXT3 || Header->Format == IWI_DXT5) + if (Header->Width != ilNextPower2(Header->Width) || Header->Height != ilNextPower2(Header->Height)) + return IL_FALSE; + // 0x0B, 0x0C and 0x0D are DXT formats. + if (Header->Format != IWI_ARGB4 && Header->Format != IWI_RGB8 && Header->Format != IWI_ARGB8 && Header->Format != IWI_A8 + && Header->Format != IWI_DXT1 && Header->Format != IWI_DXT3 && Header->Format != IWI_DXT5) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a IWI file +ILboolean ilLoadIwi(ILconst_string FileName) +{ + ILHANDLE IwiFile; + ILboolean bIwi = IL_FALSE; + + IwiFile = iopenr(FileName); + if (IwiFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bIwi; + } + + bIwi = ilLoadIwiF(IwiFile); + icloser(IwiFile); + + return bIwi; +} + + +//! Reads an already-opened IWI file +ILboolean ilLoadIwiF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadIwiInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a IWI +ILboolean ilLoadIwiL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadIwiInternal(); +} + + +// Internal function used to load the IWI. +ILboolean iLoadIwiInternal(void) +{ + IWIHEAD Header; + ILuint NumMips = 0; + ILboolean HasMipmaps = IL_TRUE; + ILenum Format; + ILubyte Bpp; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + // Read the header and check it. + if (!iGetIwiHead(&Header)) + return IL_FALSE; + if (!iCheckIwi(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // From a post by Pointy on http://iwnation.com/forums/index.php?showtopic=27903, + // flags ending with 0x3 have no mipmaps. + HasMipmaps = ((Header.Flags & 0x03) == 0x03) ? IL_FALSE : IL_TRUE; + + // Create the image, then create the mipmaps, then finally read the image. + Format = IwiGetFormat(Header.Format, &Bpp); + if (!ilTexImage(Header.Width, Header.Height, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + if (HasMipmaps) + if (!IwiInitMipmaps(iCurImage, &NumMips)) + return IL_FALSE; + if (!IwiReadImage(iCurImage, &Header, NumMips)) + return IL_FALSE; + + return ilFixImage(); +} + + +// Helper function to convert IWI formats to DevIL formats and Bpp. +ILenum IwiGetFormat(ILubyte Format, ILubyte *Bpp) +{ + switch (Format) + { + case IWI_ARGB8: + *Bpp = 4; + return IL_BGRA; + case IWI_RGB8: + *Bpp = 3; + return IL_BGR; + case IWI_ARGB4: + *Bpp = 4; + return IL_BGRA; + case IWI_A8: + *Bpp = 1; + return IL_ALPHA; + case IWI_DXT1: + *Bpp = 4; + return IL_RGBA; + case IWI_DXT3: + *Bpp = 4; + return IL_RGBA; + case IWI_DXT5: + *Bpp = 4; + return IL_RGBA; + } + + return 0; // Will never reach this. +} + + +// Function to intialize the mipmaps and determine the number of mipmaps. +ILboolean IwiInitMipmaps(ILimage *BaseImage, ILuint *NumMips) +{ + ILimage *Image; + ILuint Width, Height, Mipmap; + + Image = BaseImage; + Width = BaseImage->Width; Height = BaseImage->Height; + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + for (Mipmap = 0; Width != 1 && Height != 1; Mipmap++) { + // 1 is the smallest dimension possible. + Width = (Width >> 1) == 0 ? 1 : (Width >> 1); + Height = (Height >> 1) == 0 ? 1 : (Height >> 1); + + Image->Mipmaps = ilNewImageFull(Width, Height, 1, BaseImage->Bpp, BaseImage->Format, BaseImage->Type, NULL); + if (Image->Mipmaps == NULL) + return IL_FALSE; + Image = Image->Mipmaps; + + // ilNewImage does not set these. + Image->Format = BaseImage->Format; + Image->Type = BaseImage->Type; + // The origin is in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + } + + *NumMips = Mipmap; + return IL_TRUE; +} + + +ILboolean IwiReadImage(ILimage *BaseImage, IWIHEAD *Header, ILuint NumMips) +{ + ILimage *Image; + ILuint SizeOfData; + ILubyte *CompData = NULL; + ILint i, j, k, m; + + for (i = NumMips; i >= 0; i--) { + Image = BaseImage; + // Go to the ith mipmap level. + // The mipmaps go from smallest to the largest. + for (j = 0; j < i; j++) + Image = Image->Mipmaps; + + switch (Header->Format) + { + case IWI_ARGB8: // These are all + case IWI_RGB8: // uncompressed data, + case IWI_A8: // so just read it. + if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) + return IL_FALSE; + break; + + case IWI_ARGB4: //@TODO: Find some test images for this. + // Data is in ARGB4 format - 4 bits per component. + SizeOfData = Image->Width * Image->Height * 2; + CompData = ialloc(SizeOfData); // Not really compressed - just in ARGB4 format. + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + ifree(CompData); + return IL_FALSE; + } + for (k = 0, m = 0; k < (ILint)Image->SizeOfData; k += 4, m += 2) { + // @TODO: Double the image data into the low and high nibbles for a better range of values. + Image->Data[k+0] = CompData[m] & 0xF0; + Image->Data[k+1] = (CompData[m] & 0x0F) << 4; + Image->Data[k+2] = CompData[m+1] & 0xF0; + Image->Data[k+3] = (CompData[m+1] & 0x0F) << 4; + } + break; + + case IWI_DXT1: + // DXT1 data has at least 8 bytes, even for one pixel. + SizeOfData = IL_MAX(Image->Width * Image->Height / 2, 8); + CompData = ialloc(SizeOfData); // Gives a 6:1 compression ratio (or 8:1 for DXT1 with alpha) + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + ifree(CompData); + return IL_FALSE; + } + + // Decompress the DXT1 data into Image (ith mipmap). + if (!DecompressDXT1(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + + // Keep a copy of the DXTC data if the user wants it. + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = SizeOfData; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT1; + CompData = NULL; + } + + break; + + case IWI_DXT3: + // DXT3 data has at least 16 bytes, even for one pixel. + SizeOfData = IL_MAX(Image->Width * Image->Height, 16); + CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + ifree(CompData); + return IL_FALSE; + } + + // Decompress the DXT3 data into Image (ith mipmap). + if (!DecompressDXT3(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + break; + + case IWI_DXT5: + // DXT5 data has at least 16 bytes, even for one pixel. + SizeOfData = IL_MAX(Image->Width * Image->Height, 16); + CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + ifree(CompData); + return IL_FALSE; + } + + // Decompress the DXT5 data into Image (ith mipmap). + if (!DecompressDXT5(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + break; + } + + ifree(CompData); + } + + return IL_TRUE; +} + + +#endif//IL_NO_IWI diff --git a/DevIL/src-IL/src/il_jp2.c b/DevIL/src-IL/src/il_jp2.c deleted file mode 100644 index 3fd397ba..00000000 --- a/DevIL/src-IL/src/il_jp2.c +++ /dev/null @@ -1,809 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_jp2.c -// -// Description: Jpeg-2000 (.jp2) functions -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_JP2 -#include -#include "il_jp2.h" - -#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "libjasper.lib") - #else - #pragma comment(lib, "libjasper.lib") //libjasper-d.lib - #endif - #endif -#endif - -ILboolean iIsValidJp2(void); - -ILboolean JasperInit = IL_FALSE; - - -//! Checks if the file specified in FileName is a valid .jp2 file. -ILboolean ilIsValidJp2(ILconst_string FileName) -{ - ILHANDLE Jp2File; - ILboolean bJp2 = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("jp2")) && !iCheckExtension(FileName, IL_TEXT("jpx")) && - !iCheckExtension(FileName, IL_TEXT("j2k")) && !iCheckExtension(FileName, IL_TEXT("j2c"))) { - ilSetError(IL_INVALID_EXTENSION); - return bJp2; - } - - Jp2File = iopenr(FileName); - if (Jp2File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bJp2; - } - - bJp2 = ilIsValidJp2F(Jp2File); - icloser(Jp2File); - - return bJp2; -} - - -//! Checks if the ILHANDLE contains a valid .jp2 file at the current position. -ILboolean ilIsValidJp2F(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidJp2(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .jp2 lump. -ILboolean ilIsValidJp2L(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidJp2(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidJp2(void) -{ - ILubyte Signature[4]; - - iseek(4, IL_SEEK_CUR); // Skip the 4 bytes that tell the size of the signature box. - if (iread(Signature, 1, 4) != 4) { - iseek(-4, IL_SEEK_CUR); - return IL_FALSE; // File read error - } - - iseek(-8, IL_SEEK_CUR); // Restore to previous state - - // Signature is 'jP\040\040' by the specs (or 0x6A502020). - // http://www.jpeg.org/public/fcd15444-6.pdf - if (Signature[0] != 0x6A || Signature[1] != 0x50 || - Signature[2] != 0x20 || Signature[3] != 0x20) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a Jpeg2000 file. -ILboolean ilLoadJp2(ILconst_string FileName) -{ - ILHANDLE Jp2File; - ILboolean bRet; - - Jp2File = iopenr(FileName); - if (Jp2File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - bRet = ilLoadJp2F(Jp2File); - icloser(Jp2File); - - return bRet; -} - - -//! Reads an already-opened Jpeg2000 file. -ILboolean ilLoadJp2F(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - jas_stream_t *Stream; - - iSetInputFile(File); - FirstPos = itell(); - - if (!JasperInit) { - if (jas_init()) { - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - JasperInit = IL_TRUE; - } - Stream = iJp2ReadStream(); - if (!Stream) - { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - bRet = iLoadJp2Internal(Stream, NULL); - // Close the input stream. - jas_stream_close(Stream); - - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Jpeg2000 stream. -ILboolean ilLoadJp2L(const void *Lump, ILuint Size) -{ - return ilLoadJp2LInternal(Lump, Size, NULL); -} - - -//! This is separated so that it can be called for other file types, such as .icns. -ILboolean ilLoadJp2LInternal(const void *Lump, ILuint Size, ILimage *Image) -{ - ILboolean bRet; - jas_stream_t *Stream; - - if (!JasperInit) { - if (jas_init()) { - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - JasperInit = IL_TRUE; - } - Stream = jas_stream_memopen((char*)Lump, Size); - if (!Stream) - { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - bRet = iLoadJp2Internal(Stream, Image); - // Close the input stream. - jas_stream_close(Stream); - - return bRet; -} - - -// Internal function used to load the Jpeg2000 stream. -ILboolean iLoadJp2Internal(jas_stream_t *Stream, ILimage *Image) -{ - jas_image_t *Jp2Image = NULL; - jas_matrix_t *origdata; - ILuint x, y, c, Error; - ILimage *TempImage; - - // Decode image - Jp2Image = jas_image_decode(Stream, -1, 0); - if (!Jp2Image) - { - ilSetError(IL_ILLEGAL_FILE_VALUE); - jas_stream_close(Stream); - return IL_FALSE; - } - - // JasPer likes to buffer a lot, so it may try buffering past the end - // of the file. iread naturally sets IL_FILE_READ_ERROR if it tries - // reading past the end of the file, but this actually is not an error. - Error = ilGetError(); - // Put the error back if it is not IL_FILE_READ_ERROR. - if (Error != IL_FILE_READ_ERROR) - ilSetError(Error); - - - // We're not supporting anything other than 8 bits/component yet. - if (jas_image_cmptprec(Jp2Image, 0) != 8) - { - jas_image_destroy(Jp2Image); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - switch (jas_image_numcmpts(Jp2Image)) - { - //@TODO: Can we do alpha data? jas_image_cmpttype always returns 0 for this case. - case 1: // Assuming this is luminance data. - if (Image == NULL) { - ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); - TempImage = iCurImage; - } - else { - ifree(Image->Data); // @TODO: Not really the most efficient way to do this... - ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); - TempImage = Image; - } - break; - - case 2: // Assuming this is luminance-alpha data. - if (Image == NULL) { - ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL); - TempImage = iCurImage; - } - else { - ifree(Image->Data); // @TODO: Not really the most efficient way to do this... - ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL); - TempImage = Image; - } - break; - - case 3: - if (Image == NULL) { - ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); - TempImage = iCurImage; - } - else { - ifree(Image->Data); // @TODO: Not really the most efficient way to do this... - ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); - TempImage = Image; - } - break; - case 4: - if (Image == NULL) { - ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - TempImage = iCurImage; - } - else { - ifree(Image->Data); // @TODO: Not really the most efficient way to do this... - ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - TempImage = Image; - } - break; - default: - jas_image_destroy(Jp2Image); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - TempImage->Origin = IL_ORIGIN_UPPER_LEFT; - - // JasPer stores the data channels separately. - // I am assuming RGBA format. Is it possible for other formats to be included? - for (c = 0; c < TempImage->Bpp; c++) - { - origdata = jas_matrix_create(TempImage->Height, TempImage->Width); - if (!origdata) - { - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; // @TODO: Error - } - // Have to convert data into an intermediate matrix format. - if (jas_image_readcmpt(Jp2Image, c, 0, 0, TempImage->Width, TempImage->Height, origdata)) - { - return IL_FALSE; - } - - for (y = 0; y < TempImage->Height; y++) - { - for (x = 0; x < TempImage->Width; x++) - { - TempImage->Data[y * TempImage->Width * TempImage->Bpp + x * TempImage->Bpp + c] = origdata->data_[y * origdata->numcols_ + x]; - } - } - - jas_matrix_destroy(origdata); - } - - jas_image_destroy(Jp2Image); - - return ilFixImage(); -} - - - -static int iJp2_file_read(jas_stream_obj_t *obj, char *buf, int cnt) -{ - obj; - return iread(buf, 1, cnt); -} - -static int iJp2_file_write(jas_stream_obj_t *obj, char *buf, int cnt) -{ - obj; - return iwrite(buf, 1, cnt); -} - -static long iJp2_file_seek(jas_stream_obj_t *obj, long offset, int origin) -{ - obj; - - // We could just pass origin to iseek, but this is probably more portable. - switch (origin) - { - case SEEK_SET: - return iseek(offset, IL_SEEK_SET); - case SEEK_CUR: - return iseek(offset, IL_SEEK_CUR); - case SEEK_END: - return iseek(offset, IL_SEEK_END); - } - return 0; // Failed -} - -static int iJp2_file_close(jas_stream_obj_t *obj) -{ - obj; - return 0; // We choose when we want to close the file. -} - -static jas_stream_ops_t jas_stream_devilops = { - iJp2_file_read, - iJp2_file_write, - iJp2_file_seek, - iJp2_file_close -}; - -static jas_stream_t *jas_stream_create(void); -static void jas_stream_destroy(jas_stream_t *stream); -static void jas_stream_initbuf(jas_stream_t *stream, int bufmode ); - - -// Modified version of jas_stream_fopen and jas_stream_memopen from jas_stream.c of JasPer -// so that we can use our own file routines. -jas_stream_t *iJp2ReadStream() -{ - jas_stream_t *stream; - jas_stream_memobj_t *obj; - - if (!(stream = jas_stream_create())) { - return 0; - } - - /* A stream associated with a memory buffer is always opened - for both reading and writing in binary mode. */ - stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_BINARY; - - /* We use buffering whether it is from memory or a file. */ - jas_stream_initbuf(stream, JAS_STREAM_FULLBUF); - - /* Select the operations for a memory stream. */ - stream->ops_ = &jas_stream_devilops; - - /* Allocate memory for the underlying memory stream object. */ - if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) { - jas_stream_destroy(stream); - return 0; - } - stream->obj_ = (void *) obj; - - /* Initialize a few important members of the memory stream object. */ - obj->myalloc_ = 0; - obj->buf_ = 0; - - // Shouldn't need any of this. - - ///* If the buffer size specified is nonpositive, then the buffer - //is allocated internally and automatically grown as needed. */ - //if (bufsize <= 0) { - // obj->bufsize_ = 1024; - // obj->growable_ = 1; - //} else { - // obj->bufsize_ = bufsize; - // obj->growable_ = 0; - //} - //if (buf) { - // obj->buf_ = (unsigned char *) buf; - //} else { - // obj->buf_ = jas_malloc(obj->bufsize_ * sizeof(char)); - // obj->myalloc_ = 1; - //} - //if (!obj->buf_) { - // jas_stream_close(stream); - // return 0; - //} - - //if (bufsize > 0 && buf) { - // /* If a buffer was supplied by the caller and its length is positive, - // make the associated buffer data appear in the stream initially. */ - // obj->len_ = bufsize; - //} else { - // /* The stream is initially empty. */ - // obj->len_ = 0; - //} - //obj->pos_ = 0; - - return stream; -} - - -// The following functions are taken directly from jas_stream.c of JasPer, -// since they are designed to be used within JasPer only. - -static void jas_stream_initbuf(jas_stream_t *stream, int bufmode ) -{ - /* If this function is being called, the buffer should not have been - initialized yet. */ - assert(!stream->bufbase_); - - if (bufmode != JAS_STREAM_UNBUF) { - /* The full- or line-buffered mode is being employed. */ - if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE + - JAS_STREAM_MAXPUTBACK))) { - stream->bufmode_ |= JAS_STREAM_FREEBUF; - stream->bufsize_ = JAS_STREAM_BUFSIZE; - } else { - /* The buffer allocation has failed. Resort to unbuffered - operation. */ - stream->bufbase_ = stream->tinybuf_; - stream->bufsize_ = 1; - } - } else { - /* The unbuffered mode is being employed. */ - /* Use a trivial one-character buffer. */ - stream->bufbase_ = stream->tinybuf_; - stream->bufsize_ = 1; - } - stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK]; - stream->ptr_ = stream->bufstart_; - stream->cnt_ = 0; - stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK; -} - -static jas_stream_t *jas_stream_create() -{ - jas_stream_t *stream; - - if (!(stream = jas_malloc(sizeof(jas_stream_t)))) { - return 0; - } - stream->openmode_ = 0; - stream->bufmode_ = 0; - stream->flags_ = 0; - stream->bufbase_ = 0; - stream->bufstart_ = 0; - stream->bufsize_ = 0; - stream->ptr_ = 0; - stream->cnt_ = 0; - stream->ops_ = 0; - stream->obj_ = 0; - stream->rwcnt_ = 0; - stream->rwlimit_ = -1; - - return stream; -} - -static void jas_stream_destroy(jas_stream_t *stream) -{ - /* If the memory for the buffer was allocated with malloc, free - this memory. */ - if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { - jas_free(stream->bufbase_); - stream->bufbase_ = 0; - } - jas_free(stream); -} - - - - -jas_stream_t *iJp2WriteStream() -{ - jas_stream_t *stream; - jas_stream_memobj_t *obj; - - if (!(stream = jas_stream_create())) { - return 0; - } - - /* A stream associated with a memory buffer is always opened - for both reading and writing in binary mode. */ - stream->openmode_ = JAS_STREAM_WRITE | JAS_STREAM_BINARY; - - /* We use buffering whether it is from memory or a file. */ - jas_stream_initbuf(stream, JAS_STREAM_FULLBUF); - - /* Select the operations for a memory stream. */ - stream->ops_ = &jas_stream_devilops; - - /* Allocate memory for the underlying memory stream object. */ - if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) { - jas_stream_destroy(stream); - return 0; - } - stream->obj_ = (void *) obj; - - /* Initialize a few important members of the memory stream object. */ - obj->myalloc_ = 0; - obj->buf_ = 0; - - return stream; -} - - - -//! Writes a Jp2 file -ILboolean ilSaveJp2(const ILstring FileName) -{ - ILHANDLE Jp2File; - ILuint Jp2Size; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - Jp2File = iopenw(FileName); - if (Jp2File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - Jp2Size = ilSaveJp2F(Jp2File); - iclosew(Jp2File); - - if (Jp2Size == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Jp2 to an already-opened file -ILuint ilSaveJp2F(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveJp2Internal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Jp2 to a memory "lump" -ILuint ilSaveJp2L(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveJp2Internal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - - -// Function from OpenSceneGraph (originally called getdata in their sources): -// http://openscenegraph.sourcearchive.com/documentation/2.2.0/ReaderWriterJP2_8cpp-source.html -ILint Jp2ConvertData(jas_stream_t *in, jas_image_t *image) -{ - int ret; - int numcmpts; - int cmptno; - jas_matrix_t *data[4]; - int x; - int y; - int width, height; - - width = jas_image_cmptwidth(image, 0); - height = jas_image_cmptheight(image, 0); - numcmpts = jas_image_numcmpts(image); - - ret = -1; - - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - for (cmptno = 0; cmptno < numcmpts; ++cmptno) { - if (!(data[cmptno] = jas_matrix_create(1, width))) { - goto done; - } - } - - for (y = height - 1; y >= 0; --y) - // for (y = 0; y < height; ++y) - { - for (x = 0; x < width; ++x) - { - for (cmptno = 0; cmptno < numcmpts; ++cmptno) - { - // The sample data is unsigned. - int c; - if ((c = jas_stream_getc(in)) == EOF) { - return -1; - } - jas_matrix_set(data[cmptno], 0, x, c); - } - } - for (cmptno = 0; cmptno < numcmpts; ++cmptno) { - if (jas_image_writecmpt(image, cmptno, 0, y, width, 1, - data[cmptno])) { - goto done; - } - } - } - - jas_stream_flush(in); - ret = 0; - -done: - for (cmptno = 0; cmptno < numcmpts; ++cmptno) { - if (data[cmptno]) { - jas_matrix_destroy(data[cmptno]); - } - } - - return ret; -} - - -// Internal function used to save the Jp2. -// Since the JasPer documentation is extremely incomplete, I had to look at how OpenSceneGraph uses it: -// http://openscenegraph.sourcearchive.com/documentation/2.2.0/ReaderWriterJP2_8cpp-source.html - -//@TODO: Do we need to worry about images with depths > 1? -ILboolean iSaveJp2Internal() -{ - jas_image_t *Jp2Image; - jas_image_cmptparm_t cmptparm[4]; - jas_stream_t *Mem, *Stream; - ILuint NumChans, i; - ILenum NewFormat, NewType = IL_UNSIGNED_BYTE; - ILimage *TempImage = iCurImage; - - if (!JasperInit) { - if (jas_init()) { - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - JasperInit = IL_TRUE; - } - - if (iCurImage->Type != IL_UNSIGNED_BYTE) { //@TODO: Support greater than 1 bpc. - NewType = IL_UNSIGNED_BYTE; - } - //@TODO: Do luminance/luminance-alpha/alpha separately. - switch (iCurImage->Format) - { - case IL_LUMINANCE: - NewFormat = IL_LUMINANCE; - NumChans = 1; - break; - case IL_ALPHA: - NewFormat = IL_ALPHA; - NumChans = 1; - break; - case IL_LUMINANCE_ALPHA: - NewFormat = IL_LUMINANCE_ALPHA; - NumChans = 2; - break; - case IL_COLOUR_INDEX: // Assuming the color palette does not have an alpha value. - //@TODO: Check for this in the future. - case IL_RGB: - case IL_BGR: - NewFormat = IL_RGB; - NumChans = 3; - break; - case IL_RGBA: - case IL_BGRA: - NewFormat = IL_RGBA; - NumChans = 4; - break; - } - - if (NewType != iCurImage->Type || NewFormat != iCurImage->Format) { - TempImage = iConvertImage(iCurImage, NewFormat, NewType); - if (TempImage == NULL) - return IL_FALSE; - } - - // The origin is always in the lower left corner. Flip the buffer if it is not. - if (TempImage->Origin == IL_ORIGIN_UPPER_LEFT) - iFlipBuffer(TempImage->Data, TempImage->Depth, TempImage->Bps, TempImage->Height); - - // Have to tell JasPer about each channel. In our case, they all have the same information. - for (i = 0; i < NumChans; i++) { - cmptparm[i].width = iCurImage->Width; - cmptparm[i].height = iCurImage->Height; - cmptparm[i].hstep = 1; - cmptparm[i].vstep = 1; - cmptparm[i].tlx = 0; - cmptparm[i].tly = 0; - cmptparm[i].prec = 8; - cmptparm[i].sgnd = 0; // Unsigned data - } - - // Using the unknown color space, since we have not determined the space yet. - // This is done in the following switch statement. - Jp2Image = jas_image_create(NumChans, cmptparm, JAS_CLRSPC_UNKNOWN); - if (Jp2Image == NULL) { - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - - switch (NumChans) - { - case 1: - jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SGRAY); - if (NewFormat == IL_LUMINANCE) - jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); - else // IL_ALPHA - jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); - break; - case 2: - jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SGRAY); - jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); - jas_image_setcmpttype(Jp2Image, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); - break; - case 3: - jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SRGB); - jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); - jas_image_setcmpttype(Jp2Image, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); - jas_image_setcmpttype(Jp2Image, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); - break; - case 4: - jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SRGB); - jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); - jas_image_setcmpttype(Jp2Image, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); - jas_image_setcmpttype(Jp2Image, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); - jas_image_setcmpttype(Jp2Image, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); - break; - } - - Mem = jas_stream_memopen((char*)TempImage->Data, TempImage->SizeOfData); - if (Mem == NULL) { - jas_image_destroy(Jp2Image); - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - Stream = iJp2WriteStream(); - if (Stream == NULL) { - jas_stream_close(Mem); - jas_image_destroy(Jp2Image); - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - - // Puts data in the format that JasPer wants it in. - Jp2ConvertData(Mem, Jp2Image); - - // Does all of the encoding. - if (jas_image_encode(Jp2Image, Stream, jas_image_strtofmt("jp2"), NULL)) { //@TODO: Do we want to use any options? - jas_stream_close(Mem); - jas_stream_close(Stream); - jas_image_destroy(Jp2Image); - ilSetError(IL_LIB_JP2_ERROR); - return IL_FALSE; - } - jas_stream_flush(Stream); // Do any final writing. - - // Close the memory and output streams. - jas_stream_close(Mem); - jas_stream_close(Stream); - // Destroy the JasPer image. - jas_image_destroy(Jp2Image); - - // Destroy our temporary image if we used one. - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return IL_TRUE; -} - - -#endif//IL_NO_JP2 diff --git a/DevIL/src-IL/src/il_jp2.cpp b/DevIL/src-IL/src/il_jp2.cpp new file mode 100644 index 00000000..3fd397ba --- /dev/null +++ b/DevIL/src-IL/src/il_jp2.cpp @@ -0,0 +1,809 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_jp2.c +// +// Description: Jpeg-2000 (.jp2) functions +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_JP2 +#include +#include "il_jp2.h" + +#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "libjasper.lib") + #else + #pragma comment(lib, "libjasper.lib") //libjasper-d.lib + #endif + #endif +#endif + +ILboolean iIsValidJp2(void); + +ILboolean JasperInit = IL_FALSE; + + +//! Checks if the file specified in FileName is a valid .jp2 file. +ILboolean ilIsValidJp2(ILconst_string FileName) +{ + ILHANDLE Jp2File; + ILboolean bJp2 = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("jp2")) && !iCheckExtension(FileName, IL_TEXT("jpx")) && + !iCheckExtension(FileName, IL_TEXT("j2k")) && !iCheckExtension(FileName, IL_TEXT("j2c"))) { + ilSetError(IL_INVALID_EXTENSION); + return bJp2; + } + + Jp2File = iopenr(FileName); + if (Jp2File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bJp2; + } + + bJp2 = ilIsValidJp2F(Jp2File); + icloser(Jp2File); + + return bJp2; +} + + +//! Checks if the ILHANDLE contains a valid .jp2 file at the current position. +ILboolean ilIsValidJp2F(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidJp2(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .jp2 lump. +ILboolean ilIsValidJp2L(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidJp2(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidJp2(void) +{ + ILubyte Signature[4]; + + iseek(4, IL_SEEK_CUR); // Skip the 4 bytes that tell the size of the signature box. + if (iread(Signature, 1, 4) != 4) { + iseek(-4, IL_SEEK_CUR); + return IL_FALSE; // File read error + } + + iseek(-8, IL_SEEK_CUR); // Restore to previous state + + // Signature is 'jP\040\040' by the specs (or 0x6A502020). + // http://www.jpeg.org/public/fcd15444-6.pdf + if (Signature[0] != 0x6A || Signature[1] != 0x50 || + Signature[2] != 0x20 || Signature[3] != 0x20) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a Jpeg2000 file. +ILboolean ilLoadJp2(ILconst_string FileName) +{ + ILHANDLE Jp2File; + ILboolean bRet; + + Jp2File = iopenr(FileName); + if (Jp2File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + bRet = ilLoadJp2F(Jp2File); + icloser(Jp2File); + + return bRet; +} + + +//! Reads an already-opened Jpeg2000 file. +ILboolean ilLoadJp2F(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + jas_stream_t *Stream; + + iSetInputFile(File); + FirstPos = itell(); + + if (!JasperInit) { + if (jas_init()) { + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + JasperInit = IL_TRUE; + } + Stream = iJp2ReadStream(); + if (!Stream) + { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + bRet = iLoadJp2Internal(Stream, NULL); + // Close the input stream. + jas_stream_close(Stream); + + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Jpeg2000 stream. +ILboolean ilLoadJp2L(const void *Lump, ILuint Size) +{ + return ilLoadJp2LInternal(Lump, Size, NULL); +} + + +//! This is separated so that it can be called for other file types, such as .icns. +ILboolean ilLoadJp2LInternal(const void *Lump, ILuint Size, ILimage *Image) +{ + ILboolean bRet; + jas_stream_t *Stream; + + if (!JasperInit) { + if (jas_init()) { + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + JasperInit = IL_TRUE; + } + Stream = jas_stream_memopen((char*)Lump, Size); + if (!Stream) + { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + bRet = iLoadJp2Internal(Stream, Image); + // Close the input stream. + jas_stream_close(Stream); + + return bRet; +} + + +// Internal function used to load the Jpeg2000 stream. +ILboolean iLoadJp2Internal(jas_stream_t *Stream, ILimage *Image) +{ + jas_image_t *Jp2Image = NULL; + jas_matrix_t *origdata; + ILuint x, y, c, Error; + ILimage *TempImage; + + // Decode image + Jp2Image = jas_image_decode(Stream, -1, 0); + if (!Jp2Image) + { + ilSetError(IL_ILLEGAL_FILE_VALUE); + jas_stream_close(Stream); + return IL_FALSE; + } + + // JasPer likes to buffer a lot, so it may try buffering past the end + // of the file. iread naturally sets IL_FILE_READ_ERROR if it tries + // reading past the end of the file, but this actually is not an error. + Error = ilGetError(); + // Put the error back if it is not IL_FILE_READ_ERROR. + if (Error != IL_FILE_READ_ERROR) + ilSetError(Error); + + + // We're not supporting anything other than 8 bits/component yet. + if (jas_image_cmptprec(Jp2Image, 0) != 8) + { + jas_image_destroy(Jp2Image); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + switch (jas_image_numcmpts(Jp2Image)) + { + //@TODO: Can we do alpha data? jas_image_cmpttype always returns 0 for this case. + case 1: // Assuming this is luminance data. + if (Image == NULL) { + ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); + TempImage = iCurImage; + } + else { + ifree(Image->Data); // @TODO: Not really the most efficient way to do this... + ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); + TempImage = Image; + } + break; + + case 2: // Assuming this is luminance-alpha data. + if (Image == NULL) { + ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL); + TempImage = iCurImage; + } + else { + ifree(Image->Data); // @TODO: Not really the most efficient way to do this... + ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE, NULL); + TempImage = Image; + } + break; + + case 3: + if (Image == NULL) { + ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); + TempImage = iCurImage; + } + else { + ifree(Image->Data); // @TODO: Not really the most efficient way to do this... + ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); + TempImage = Image; + } + break; + case 4: + if (Image == NULL) { + ilTexImage(jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + TempImage = iCurImage; + } + else { + ifree(Image->Data); // @TODO: Not really the most efficient way to do this... + ilInitImage(Image, jas_image_width(Jp2Image), jas_image_height(Jp2Image), 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + TempImage = Image; + } + break; + default: + jas_image_destroy(Jp2Image); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + TempImage->Origin = IL_ORIGIN_UPPER_LEFT; + + // JasPer stores the data channels separately. + // I am assuming RGBA format. Is it possible for other formats to be included? + for (c = 0; c < TempImage->Bpp; c++) + { + origdata = jas_matrix_create(TempImage->Height, TempImage->Width); + if (!origdata) + { + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; // @TODO: Error + } + // Have to convert data into an intermediate matrix format. + if (jas_image_readcmpt(Jp2Image, c, 0, 0, TempImage->Width, TempImage->Height, origdata)) + { + return IL_FALSE; + } + + for (y = 0; y < TempImage->Height; y++) + { + for (x = 0; x < TempImage->Width; x++) + { + TempImage->Data[y * TempImage->Width * TempImage->Bpp + x * TempImage->Bpp + c] = origdata->data_[y * origdata->numcols_ + x]; + } + } + + jas_matrix_destroy(origdata); + } + + jas_image_destroy(Jp2Image); + + return ilFixImage(); +} + + + +static int iJp2_file_read(jas_stream_obj_t *obj, char *buf, int cnt) +{ + obj; + return iread(buf, 1, cnt); +} + +static int iJp2_file_write(jas_stream_obj_t *obj, char *buf, int cnt) +{ + obj; + return iwrite(buf, 1, cnt); +} + +static long iJp2_file_seek(jas_stream_obj_t *obj, long offset, int origin) +{ + obj; + + // We could just pass origin to iseek, but this is probably more portable. + switch (origin) + { + case SEEK_SET: + return iseek(offset, IL_SEEK_SET); + case SEEK_CUR: + return iseek(offset, IL_SEEK_CUR); + case SEEK_END: + return iseek(offset, IL_SEEK_END); + } + return 0; // Failed +} + +static int iJp2_file_close(jas_stream_obj_t *obj) +{ + obj; + return 0; // We choose when we want to close the file. +} + +static jas_stream_ops_t jas_stream_devilops = { + iJp2_file_read, + iJp2_file_write, + iJp2_file_seek, + iJp2_file_close +}; + +static jas_stream_t *jas_stream_create(void); +static void jas_stream_destroy(jas_stream_t *stream); +static void jas_stream_initbuf(jas_stream_t *stream, int bufmode ); + + +// Modified version of jas_stream_fopen and jas_stream_memopen from jas_stream.c of JasPer +// so that we can use our own file routines. +jas_stream_t *iJp2ReadStream() +{ + jas_stream_t *stream; + jas_stream_memobj_t *obj; + + if (!(stream = jas_stream_create())) { + return 0; + } + + /* A stream associated with a memory buffer is always opened + for both reading and writing in binary mode. */ + stream->openmode_ = JAS_STREAM_READ | JAS_STREAM_BINARY; + + /* We use buffering whether it is from memory or a file. */ + jas_stream_initbuf(stream, JAS_STREAM_FULLBUF); + + /* Select the operations for a memory stream. */ + stream->ops_ = &jas_stream_devilops; + + /* Allocate memory for the underlying memory stream object. */ + if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) { + jas_stream_destroy(stream); + return 0; + } + stream->obj_ = (void *) obj; + + /* Initialize a few important members of the memory stream object. */ + obj->myalloc_ = 0; + obj->buf_ = 0; + + // Shouldn't need any of this. + + ///* If the buffer size specified is nonpositive, then the buffer + //is allocated internally and automatically grown as needed. */ + //if (bufsize <= 0) { + // obj->bufsize_ = 1024; + // obj->growable_ = 1; + //} else { + // obj->bufsize_ = bufsize; + // obj->growable_ = 0; + //} + //if (buf) { + // obj->buf_ = (unsigned char *) buf; + //} else { + // obj->buf_ = jas_malloc(obj->bufsize_ * sizeof(char)); + // obj->myalloc_ = 1; + //} + //if (!obj->buf_) { + // jas_stream_close(stream); + // return 0; + //} + + //if (bufsize > 0 && buf) { + // /* If a buffer was supplied by the caller and its length is positive, + // make the associated buffer data appear in the stream initially. */ + // obj->len_ = bufsize; + //} else { + // /* The stream is initially empty. */ + // obj->len_ = 0; + //} + //obj->pos_ = 0; + + return stream; +} + + +// The following functions are taken directly from jas_stream.c of JasPer, +// since they are designed to be used within JasPer only. + +static void jas_stream_initbuf(jas_stream_t *stream, int bufmode ) +{ + /* If this function is being called, the buffer should not have been + initialized yet. */ + assert(!stream->bufbase_); + + if (bufmode != JAS_STREAM_UNBUF) { + /* The full- or line-buffered mode is being employed. */ + if ((stream->bufbase_ = jas_malloc(JAS_STREAM_BUFSIZE + + JAS_STREAM_MAXPUTBACK))) { + stream->bufmode_ |= JAS_STREAM_FREEBUF; + stream->bufsize_ = JAS_STREAM_BUFSIZE; + } else { + /* The buffer allocation has failed. Resort to unbuffered + operation. */ + stream->bufbase_ = stream->tinybuf_; + stream->bufsize_ = 1; + } + } else { + /* The unbuffered mode is being employed. */ + /* Use a trivial one-character buffer. */ + stream->bufbase_ = stream->tinybuf_; + stream->bufsize_ = 1; + } + stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK]; + stream->ptr_ = stream->bufstart_; + stream->cnt_ = 0; + stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK; +} + +static jas_stream_t *jas_stream_create() +{ + jas_stream_t *stream; + + if (!(stream = jas_malloc(sizeof(jas_stream_t)))) { + return 0; + } + stream->openmode_ = 0; + stream->bufmode_ = 0; + stream->flags_ = 0; + stream->bufbase_ = 0; + stream->bufstart_ = 0; + stream->bufsize_ = 0; + stream->ptr_ = 0; + stream->cnt_ = 0; + stream->ops_ = 0; + stream->obj_ = 0; + stream->rwcnt_ = 0; + stream->rwlimit_ = -1; + + return stream; +} + +static void jas_stream_destroy(jas_stream_t *stream) +{ + /* If the memory for the buffer was allocated with malloc, free + this memory. */ + if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) { + jas_free(stream->bufbase_); + stream->bufbase_ = 0; + } + jas_free(stream); +} + + + + +jas_stream_t *iJp2WriteStream() +{ + jas_stream_t *stream; + jas_stream_memobj_t *obj; + + if (!(stream = jas_stream_create())) { + return 0; + } + + /* A stream associated with a memory buffer is always opened + for both reading and writing in binary mode. */ + stream->openmode_ = JAS_STREAM_WRITE | JAS_STREAM_BINARY; + + /* We use buffering whether it is from memory or a file. */ + jas_stream_initbuf(stream, JAS_STREAM_FULLBUF); + + /* Select the operations for a memory stream. */ + stream->ops_ = &jas_stream_devilops; + + /* Allocate memory for the underlying memory stream object. */ + if (!(obj = jas_malloc(sizeof(jas_stream_memobj_t)))) { + jas_stream_destroy(stream); + return 0; + } + stream->obj_ = (void *) obj; + + /* Initialize a few important members of the memory stream object. */ + obj->myalloc_ = 0; + obj->buf_ = 0; + + return stream; +} + + + +//! Writes a Jp2 file +ILboolean ilSaveJp2(const ILstring FileName) +{ + ILHANDLE Jp2File; + ILuint Jp2Size; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + Jp2File = iopenw(FileName); + if (Jp2File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + Jp2Size = ilSaveJp2F(Jp2File); + iclosew(Jp2File); + + if (Jp2Size == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Jp2 to an already-opened file +ILuint ilSaveJp2F(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveJp2Internal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Jp2 to a memory "lump" +ILuint ilSaveJp2L(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveJp2Internal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + + +// Function from OpenSceneGraph (originally called getdata in their sources): +// http://openscenegraph.sourcearchive.com/documentation/2.2.0/ReaderWriterJP2_8cpp-source.html +ILint Jp2ConvertData(jas_stream_t *in, jas_image_t *image) +{ + int ret; + int numcmpts; + int cmptno; + jas_matrix_t *data[4]; + int x; + int y; + int width, height; + + width = jas_image_cmptwidth(image, 0); + height = jas_image_cmptheight(image, 0); + numcmpts = jas_image_numcmpts(image); + + ret = -1; + + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0; + for (cmptno = 0; cmptno < numcmpts; ++cmptno) { + if (!(data[cmptno] = jas_matrix_create(1, width))) { + goto done; + } + } + + for (y = height - 1; y >= 0; --y) + // for (y = 0; y < height; ++y) + { + for (x = 0; x < width; ++x) + { + for (cmptno = 0; cmptno < numcmpts; ++cmptno) + { + // The sample data is unsigned. + int c; + if ((c = jas_stream_getc(in)) == EOF) { + return -1; + } + jas_matrix_set(data[cmptno], 0, x, c); + } + } + for (cmptno = 0; cmptno < numcmpts; ++cmptno) { + if (jas_image_writecmpt(image, cmptno, 0, y, width, 1, + data[cmptno])) { + goto done; + } + } + } + + jas_stream_flush(in); + ret = 0; + +done: + for (cmptno = 0; cmptno < numcmpts; ++cmptno) { + if (data[cmptno]) { + jas_matrix_destroy(data[cmptno]); + } + } + + return ret; +} + + +// Internal function used to save the Jp2. +// Since the JasPer documentation is extremely incomplete, I had to look at how OpenSceneGraph uses it: +// http://openscenegraph.sourcearchive.com/documentation/2.2.0/ReaderWriterJP2_8cpp-source.html + +//@TODO: Do we need to worry about images with depths > 1? +ILboolean iSaveJp2Internal() +{ + jas_image_t *Jp2Image; + jas_image_cmptparm_t cmptparm[4]; + jas_stream_t *Mem, *Stream; + ILuint NumChans, i; + ILenum NewFormat, NewType = IL_UNSIGNED_BYTE; + ILimage *TempImage = iCurImage; + + if (!JasperInit) { + if (jas_init()) { + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + JasperInit = IL_TRUE; + } + + if (iCurImage->Type != IL_UNSIGNED_BYTE) { //@TODO: Support greater than 1 bpc. + NewType = IL_UNSIGNED_BYTE; + } + //@TODO: Do luminance/luminance-alpha/alpha separately. + switch (iCurImage->Format) + { + case IL_LUMINANCE: + NewFormat = IL_LUMINANCE; + NumChans = 1; + break; + case IL_ALPHA: + NewFormat = IL_ALPHA; + NumChans = 1; + break; + case IL_LUMINANCE_ALPHA: + NewFormat = IL_LUMINANCE_ALPHA; + NumChans = 2; + break; + case IL_COLOUR_INDEX: // Assuming the color palette does not have an alpha value. + //@TODO: Check for this in the future. + case IL_RGB: + case IL_BGR: + NewFormat = IL_RGB; + NumChans = 3; + break; + case IL_RGBA: + case IL_BGRA: + NewFormat = IL_RGBA; + NumChans = 4; + break; + } + + if (NewType != iCurImage->Type || NewFormat != iCurImage->Format) { + TempImage = iConvertImage(iCurImage, NewFormat, NewType); + if (TempImage == NULL) + return IL_FALSE; + } + + // The origin is always in the lower left corner. Flip the buffer if it is not. + if (TempImage->Origin == IL_ORIGIN_UPPER_LEFT) + iFlipBuffer(TempImage->Data, TempImage->Depth, TempImage->Bps, TempImage->Height); + + // Have to tell JasPer about each channel. In our case, they all have the same information. + for (i = 0; i < NumChans; i++) { + cmptparm[i].width = iCurImage->Width; + cmptparm[i].height = iCurImage->Height; + cmptparm[i].hstep = 1; + cmptparm[i].vstep = 1; + cmptparm[i].tlx = 0; + cmptparm[i].tly = 0; + cmptparm[i].prec = 8; + cmptparm[i].sgnd = 0; // Unsigned data + } + + // Using the unknown color space, since we have not determined the space yet. + // This is done in the following switch statement. + Jp2Image = jas_image_create(NumChans, cmptparm, JAS_CLRSPC_UNKNOWN); + if (Jp2Image == NULL) { + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + + switch (NumChans) + { + case 1: + jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SGRAY); + if (NewFormat == IL_LUMINANCE) + jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); + else // IL_ALPHA + jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); + break; + case 2: + jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SGRAY); + jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); + jas_image_setcmpttype(Jp2Image, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); + break; + case 3: + jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SRGB); + jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); + jas_image_setcmpttype(Jp2Image, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); + jas_image_setcmpttype(Jp2Image, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); + break; + case 4: + jas_image_setclrspc(Jp2Image, JAS_CLRSPC_SRGB); + jas_image_setcmpttype(Jp2Image, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); + jas_image_setcmpttype(Jp2Image, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); + jas_image_setcmpttype(Jp2Image, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); + jas_image_setcmpttype(Jp2Image, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); + break; + } + + Mem = jas_stream_memopen((char*)TempImage->Data, TempImage->SizeOfData); + if (Mem == NULL) { + jas_image_destroy(Jp2Image); + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + Stream = iJp2WriteStream(); + if (Stream == NULL) { + jas_stream_close(Mem); + jas_image_destroy(Jp2Image); + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + + // Puts data in the format that JasPer wants it in. + Jp2ConvertData(Mem, Jp2Image); + + // Does all of the encoding. + if (jas_image_encode(Jp2Image, Stream, jas_image_strtofmt("jp2"), NULL)) { //@TODO: Do we want to use any options? + jas_stream_close(Mem); + jas_stream_close(Stream); + jas_image_destroy(Jp2Image); + ilSetError(IL_LIB_JP2_ERROR); + return IL_FALSE; + } + jas_stream_flush(Stream); // Do any final writing. + + // Close the memory and output streams. + jas_stream_close(Mem); + jas_stream_close(Stream); + // Destroy the JasPer image. + jas_image_destroy(Jp2Image); + + // Destroy our temporary image if we used one. + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return IL_TRUE; +} + + +#endif//IL_NO_JP2 diff --git a/DevIL/src-IL/src/il_jpeg.c b/DevIL/src-IL/src/il_jpeg.c deleted file mode 100644 index 54e18756..00000000 --- a/DevIL/src-IL/src/il_jpeg.c +++ /dev/null @@ -1,1001 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/14/2009 -// -// Filename: src-IL/src/il_jpeg.c -// -// Description: Jpeg (.jpg) functions -// -//----------------------------------------------------------------------------- -// -// Most of the comments here are sufficient, as we're just using libjpeg. -// I have left most of the libjpeg example's comments intact, though. -// - -#include "il_internal.h" - -#ifndef IL_NO_JPG - #ifndef IL_USE_IJL - #ifdef RGB_RED - #undef RGB_RED - #undef RGB_GREEN - #undef RGB_BLUE - #endif - #define RGB_RED 0 - #define RGB_GREEN 1 - #define RGB_BLUE 2 - - #if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable : 4005) // Redefinitions in - #pragma warning(disable : 4142) // jmorecfg.h - #endif - - #include "jpeglib.h" - - #if JPEG_LIB_VERSION < 62 - #warning DevIL was designed with libjpeg 6b or higher in mind. Consider upgrading at www.ijg.org - #endif - #else - #include - #include - #endif - -#include "il_jpeg.h" -#include - - -#if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifdef IL_USE_IJL - //pragma comment(lib, "ijl15.lib") - #else - #ifndef _DEBUG - #pragma comment(lib, "libjpeg.lib") - #else - //#pragma comment(lib, "libjpeg-d.lib") - #pragma comment(lib, "libjpeg.lib") - #endif - #endif//IL_USE_IJL - #endif -#endif - - -static ILboolean jpgErrorOccured = IL_FALSE; - -// define a protype of ilLoadFromJpegStruct -ILboolean ilLoadFromJpegStruct(void *_JpegInfo); - -// Internal function used to get the .jpg header from the current file. -void iGetJpgHead(ILubyte *Header) -{ - Header[0] = igetc(); - Header[1] = igetc(); - return; -} - - -// Internal function used to check if the HEADER is a valid .Jpg header. -ILboolean iCheckJpg(ILubyte Header[2]) -{ - if (Header[0] != 0xFF || Header[1] != 0xD8) - return IL_FALSE; - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidJpeg() -{ - ILubyte Head[2]; - - iGetJpgHead(Head); - iseek(-2, IL_SEEK_CUR); // Go ahead and restore to previous state - - return iCheckJpg(Head); -} - - -//! Checks if the file specified in FileName is a valid .jpg file. -ILboolean ilIsValidJpeg(ILconst_string FileName) -{ - ILHANDLE JpegFile; - ILboolean bJpeg = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("jpg")) && - !iCheckExtension(FileName, IL_TEXT("jpe")) && - !iCheckExtension(FileName, IL_TEXT("jpeg")) && - !iCheckExtension(FileName, IL_TEXT("jif")) && - !iCheckExtension(FileName, IL_TEXT("jfif"))) - { - ilSetError(IL_INVALID_EXTENSION); - return bJpeg; - } - - JpegFile = iopenr(FileName); - if (JpegFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bJpeg; - } - - bJpeg = ilIsValidJpegF(JpegFile); - icloser(JpegFile); - - return bJpeg; -} - - -//! Checks if the ILHANDLE contains a valid .jpg file at the current position. -ILboolean ilIsValidJpegF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidJpeg(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -ILboolean ilIsValidJpegL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidJpeg(); -} - - -#ifndef IL_USE_IJL // Use libjpeg instead of the IJL. - -// Overrides libjpeg's stupid error/warning handlers. =P -void ExitErrorHandle (struct jpeg_common_struct *JpegInfo) -{ - ilSetError(IL_LIB_JPEG_ERROR); - jpgErrorOccured = IL_TRUE; - return; -} -void OutputMsg(struct jpeg_common_struct *JpegInfo) -{ - return; -} - - -//! Reads a jpeg file -ILboolean ilLoadJpeg(ILconst_string FileName) -{ - ILHANDLE JpegFile; - ILboolean bJpeg = IL_FALSE; - - JpegFile = iopenr(FileName); - if (JpegFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bJpeg; - } - - bJpeg = ilLoadJpegF(JpegFile); - icloser(JpegFile); - - return bJpeg; -} - - -//! Reads an already-opened jpeg file -ILboolean ilLoadJpegF(ILHANDLE File) -{ - ILboolean bRet; - ILuint FirstPos; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadJpegInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -// Reads from a memory "lump" containing a jpeg -ILboolean ilLoadJpegL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadJpegInternal(); -} - - -typedef struct { - struct jpeg_source_mgr pub; /* public fields */ - - JOCTET * buffer; /* start of buffer */ - boolean start_of_file; /* have we gotten any data yet? */ -} iread_mgr; - -typedef iread_mgr * iread_ptr; - -#define INPUT_BUF_SIZE 4096 // choose an efficiently iread'able size - - -METHODDEF(void) -init_source (j_decompress_ptr cinfo) -{ - iread_ptr src = (iread_ptr) cinfo->src; - src->start_of_file = TRUE; -} - - -METHODDEF(boolean) -fill_input_buffer (j_decompress_ptr cinfo) -{ - iread_ptr src = (iread_ptr) cinfo->src; - ILint nbytes; - - nbytes = iread(src->buffer, 1, INPUT_BUF_SIZE); - - if (nbytes <= 0) { - if (src->start_of_file) { // Treat empty input file as fatal error - //ERREXIT(cinfo, JERR_INPUT_EMPTY); - jpgErrorOccured = IL_TRUE; - } - //WARNMS(cinfo, JWRN_JPEG_EOF); - // Insert a fake EOI marker - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - return IL_FALSE; - } - if (nbytes < INPUT_BUF_SIZE) { - ilGetError(); // Gets rid of the IL_FILE_READ_ERROR. - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = IL_FALSE; - - return IL_TRUE; -} - - -METHODDEF(void) -skip_input_data (j_decompress_ptr cinfo, long num_bytes) -{ - iread_ptr src = (iread_ptr) cinfo->src; - - if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } -} - - -METHODDEF(void) -term_source (j_decompress_ptr cinfo) -{ - // no work necessary here -} - - -GLOBAL(void) -devil_jpeg_read_init (j_decompress_ptr cinfo) -{ - iread_ptr src; - - if ( cinfo->src == NULL ) { // first time for this JPEG object? - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(iread_mgr) ); - src = (iread_ptr) cinfo->src; - src->buffer = (JOCTET *) - (*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * sizeof(JOCTET) ); - } - - src = (iread_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method - src->pub.term_source = term_source; - src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read - src->pub.next_input_byte = NULL; // until buffer loaded -} - - -jmp_buf JpegJumpBuffer; - -static void iJpegErrorExit( j_common_ptr cinfo ) -{ - ilSetError( IL_LIB_JPEG_ERROR ); - jpeg_destroy( cinfo ); - longjmp( JpegJumpBuffer, 1 ); -} - -// Internal function used to load the jpeg. -ILboolean iLoadJpegInternal() -{ - struct jpeg_error_mgr Error; - struct jpeg_decompress_struct JpegInfo; - ILboolean result; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - JpegInfo.err = jpeg_std_error(&Error); // init standard error handlers - Error.error_exit = iJpegErrorExit; // add our exit handler - Error.output_message = OutputMsg; - - if ((result = setjmp(JpegJumpBuffer) == 0) != IL_FALSE) { - jpeg_create_decompress(&JpegInfo); - JpegInfo.do_block_smoothing = IL_TRUE; - JpegInfo.do_fancy_upsampling = IL_TRUE; - - //jpeg_stdio_src(&JpegInfo, iGetFile()); - - devil_jpeg_read_init(&JpegInfo); - jpeg_read_header(&JpegInfo, IL_TRUE); - - result = ilLoadFromJpegStruct(&JpegInfo); - - jpeg_finish_decompress(&JpegInfo); - jpeg_destroy_decompress(&JpegInfo); - - } - else - { - jpeg_destroy_decompress(&JpegInfo); - } - - //return ilFixImage(); // No need to call it again (called first in ilLoadFromJpegStruct). - return result; -} - - - -typedef struct -{ - struct jpeg_destination_mgr pub; - JOCTET *buffer; - ILboolean bah; -} iwrite_mgr; - -typedef iwrite_mgr *iwrite_ptr; - -#define OUTPUT_BUF_SIZE 4096 - - -METHODDEF(void) -init_destination(j_compress_ptr cinfo) -{ - iwrite_ptr dest = (iwrite_ptr)cinfo->dest; - dest->buffer = (JOCTET *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - OUTPUT_BUF_SIZE * sizeof(JOCTET)); - - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - return; -} - -METHODDEF(boolean) -empty_output_buffer (j_compress_ptr cinfo) -{ - iwrite_ptr dest = (iwrite_ptr)cinfo->dest; - iwrite(dest->buffer, 1, OUTPUT_BUF_SIZE); - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - return IL_TRUE; -} - -METHODDEF(void) -term_destination (j_compress_ptr cinfo) -{ - iwrite_ptr dest = (iwrite_ptr)cinfo->dest; - iwrite(dest->buffer, 1, OUTPUT_BUF_SIZE - (ILuint)dest->pub.free_in_buffer); - return; -} - - -GLOBAL(void) -devil_jpeg_write_init(j_compress_ptr cinfo) -{ - iwrite_ptr dest; - - if (cinfo->dest == NULL) { // first time for this JPEG object? - cinfo->dest = (struct jpeg_destination_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof(iwrite_mgr)); - dest = (iwrite_ptr)cinfo->dest; - } - - dest = (iwrite_ptr)cinfo->dest; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; - - return; -} - - -//! Writes a Jpeg file -ILboolean ilSaveJpeg(const ILstring FileName) -{ - ILHANDLE JpegFile; - ILuint JpegSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - JpegFile = iopenw(FileName); - if (JpegFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - JpegSize = ilSaveJpegF(JpegFile); - iclosew(JpegFile); - - if (JpegSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Jpeg to an already-opened file -ILuint ilSaveJpegF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveJpegInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Jpeg to a memory "lump" -ILuint ilSaveJpegL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveJpegInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the Jpeg. -ILboolean iSaveJpegInternal() -{ - struct jpeg_compress_struct JpegInfo; - struct jpeg_error_mgr Error; - JSAMPROW row_pointer[1]; - ILimage *TempImage; - ILubyte *TempData; - ILenum Type = 0; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - /*if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) - Quality = 85; // Not sure how low we should dare go... - else - Quality = 99;*/ - - if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) { - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - if (TempImage == NULL) { - return IL_FALSE; - } - } - else { - TempImage = iCurImage; - } - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - } - else { - TempData = TempImage->Data; - } - - - JpegInfo.err = jpeg_std_error(&Error); - // Now we can initialize the JPEG compression object. - jpeg_create_compress(&JpegInfo); - - //jpeg_stdio_dest(&JpegInfo, JpegFile); - devil_jpeg_write_init(&JpegInfo); - - JpegInfo.image_width = TempImage->Width; // image width and height, in pixels - JpegInfo.image_height = TempImage->Height; - JpegInfo.input_components = TempImage->Bpp; // # of color components per pixel - - // John Villar's addition - if (TempImage->Bpp == 1) - JpegInfo.in_color_space = JCS_GRAYSCALE; - else - JpegInfo.in_color_space = JCS_RGB; - - jpeg_set_defaults(&JpegInfo); - -/*#ifndef IL_USE_JPEGLIB_UNMODIFIED - Type = iGetInt(IL_JPG_SAVE_FORMAT); - if (Type == IL_EXIF) { - JpegInfo.write_JFIF_header = FALSE; - JpegInfo.write_EXIF_header = TRUE; - } - else if (Type == IL_JFIF) { - JpegInfo.write_JFIF_header = TRUE; - JpegInfo.write_EXIF_header = FALSE; - } //EXIF not present in libjpeg... -#else*/ - Type = Type; - JpegInfo.write_JFIF_header = TRUE; -//#endif//IL_USE_JPEGLIB_UNMODIFIED - - // Set the quality output - jpeg_set_quality(&JpegInfo, iGetInt(IL_JPG_QUALITY), IL_TRUE); - // Sets progressive saving here - if (ilGetBoolean(IL_JPG_PROGRESSIVE)) - jpeg_simple_progression(&JpegInfo); - - jpeg_start_compress(&JpegInfo, IL_TRUE); - - //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer - - while (JpegInfo.next_scanline < JpegInfo.image_height) { - // jpeg_write_scanlines expects an array of pointers to scanlines. - // Here the array is only one element long, but you could pass - // more than one scanline at a time if that's more convenient. - row_pointer[0] = &TempData[JpegInfo.next_scanline * TempImage->Bps]; - (void) jpeg_write_scanlines(&JpegInfo, row_pointer, 1); - } - - // Step 6: Finish compression - jpeg_finish_compress(&JpegInfo); - - // Step 7: release JPEG compression object - - // This is an important step since it will release a good deal of memory. - jpeg_destroy_compress(&JpegInfo); - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) - ifree(TempData); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return IL_TRUE; -} - - - -#else // Use the IJL instead of libjpeg. - - - -//! Reads a jpeg file -ILboolean ilLoadJpeg(ILconst_string FileName) -{ - if (!iFileExists(FileName)) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - return iLoadJpegInternal(FileName, NULL, 0); -} - - -// Reads from a memory "lump" containing a jpeg -ILboolean ilLoadJpegL(void *Lump, ILuint Size) -{ - return iLoadJpegInternal(NULL, Lump, Size); -} - - -// Internal function used to load the jpeg. -ILboolean iLoadJpegInternal(ILstring FileName, void *Lump, ILuint Size) -{ - JPEG_CORE_PROPERTIES Image; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (ijlInit(&Image) != IJL_OK) { - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - - if (FileName != NULL) { - Image.JPGFile = FileName; - if (ijlRead(&Image, IJL_JFILE_READPARAMS) != IJL_OK) { - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - } - else { - Image.JPGBytes = Lump; - Image.JPGSizeBytes = Size > 0 ? Size : UINT_MAX; - if (ijlRead(&Image, IJL_JBUFF_READPARAMS) != IJL_OK) { - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - } - - switch (Image.JPGChannels) - { - case 1: - Image.JPGColor = IJL_G; - Image.DIBChannels = 1; - Image.DIBColor = IJL_G; - iCurImage->Format = IL_LUMINANCE; - break; - - case 3: - Image.JPGColor = IJL_YCBCR; - Image.DIBChannels = 3; - Image.DIBColor = IJL_RGB; - iCurImage->Format = IL_RGB; - break; - - case 4: - Image.JPGColor = IJL_YCBCRA_FPX; - Image.DIBChannels = 4; - Image.DIBColor = IJL_RGBA_FPX; - iCurImage->Format = IL_RGBA; - break; - - default: - // This catches everything else, but no - // color twist will be performed by the IJL. - /*Image.DIBColor = (IJL_COLOR)IJL_OTHER; - Image.JPGColor = (IJL_COLOR)IJL_OTHER; - Image.DIBChannels = Image.JPGChannels; - break;*/ - ijlFree(&Image); - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - - if (!ilTexImage(Image.JPGWidth, Image.JPGHeight, 1, (ILubyte)Image.DIBChannels, iCurImage->Format, IL_UNSIGNED_BYTE, NULL)) { - ijlFree(&Image); - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - Image.DIBWidth = Image.JPGWidth; - Image.DIBHeight = Image.JPGHeight; - Image.DIBPadBytes = 0; - Image.DIBBytes = iCurImage->Data; - - if (FileName != NULL) { - if (ijlRead(&Image, IJL_JFILE_READWHOLEIMAGE) != IJL_OK) { - ijlFree(&Image); - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - } - else { - if (ijlRead(&Image, IJL_JBUFF_READWHOLEIMAGE) != IJL_OK) { - ijlFree(&Image); - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - } - - ijlFree(&Image); - return ilFixImage(); -} - - -//! Writes a Jpeg file -ILboolean ilSaveJpeg(ILconst_string FileName) -{ - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - return iSaveJpegInternal(FileName, NULL, 0); -} - - -//! Writes a Jpeg to a memory "lump" -ILboolean ilSaveJpegL(void *Lump, ILuint Size) -{ - return iSaveJpegInternal(NULL, Lump, Size); -} - - -// Internal function used to save the Jpeg. -ILboolean iSaveJpegInternal(ILstring FileName, void *Lump, ILuint Size) -{ - JPEG_CORE_PROPERTIES Image; - ILuint Quality; - ILimage *TempImage; - ILubyte *TempData; - - imemclear(&Image, sizeof(JPEG_CORE_PROPERTIES)); - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - if (FileName == NULL && Lump == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) - Quality = 85; // Not sure how low we should dare go... - else - Quality = 99; - - if (ijlInit(&Image) != IJL_OK) { - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - - if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_RGBA && iCurImage->Format != IL_LUMINANCE) - || iCurImage->Bpc != 1) { - if (iCurImage->Format == IL_BGRA) - Temp = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); - else - Temp = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - if (Temp == NULL) { - return IL_FALSE; - } - } - else { - Temp = iCurImage; - } - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - } - else { - TempData = TempImage->Data; - } - - // Setup DIB - Image.DIBWidth = TempImage->Width; - Image.DIBHeight = TempImage->Height; - Image.DIBChannels = TempImage->Bpp; - Image.DIBBytes = TempData; - Image.DIBPadBytes = 0; - - // Setup JPEG - Image.JPGWidth = TempImage->Width; - Image.JPGHeight = TempImage->Height; - Image.JPGChannels = TempImage->Bpp; - - switch (Temp->Bpp) - { - case 1: - Image.DIBColor = IJL_G; - Image.JPGColor = IJL_G; - Image.JPGSubsampling = IJL_NONE; - break; - case 3: - Image.DIBColor = IJL_RGB; - Image.JPGColor = IJL_YCBCR; - Image.JPGSubsampling = IJL_411; - break; - case 4: - Image.DIBColor = IJL_RGBA_FPX; - Image.JPGColor = IJL_YCBCRA_FPX; - Image.JPGSubsampling = IJL_4114; - break; - } - - if (FileName != NULL) { - Image.JPGFile = FileName; - if (ijlWrite(&Image, IJL_JFILE_WRITEWHOLEIMAGE) != IJL_OK) { - if (TempImage != iCurImage) - ilCloseImage(TempImage); - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - } - else { - Image.JPGBytes = Lump; - Image.JPGSizeBytes = Size; - if (ijlWrite(&Image, IJL_JBUFF_WRITEWHOLEIMAGE) != IJL_OK) { - if (TempImage != iCurImage) - ilCloseImage(TempImage); - ilSetError(IL_LIB_JPEG_ERROR); - return IL_FALSE; - } - } - - ijlFree(&Image); - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) - ifree(TempData); - if (Temp != iCurImage) - ilCloseImage(Temp); - - return IL_TRUE; -} - -#endif//IL_USE_IJL - - -// Access point for applications wishing to use the jpeg library directly in -// conjunction with DevIL. -// -// The decompressor must be set up with an input source and all desired parameters -// this function is called. The caller must call jpeg_finish_decompress because -// the caller may still need decompressor after calling this for e.g. examining -// saved markers. -ILboolean ilLoadFromJpegStruct(void *_JpegInfo) -{ -#ifndef IL_NO_JPG -#ifndef IL_USE_IJL - // sam. void (*errorHandler)(j_common_ptr); - ILubyte *TempPtr[1]; - ILuint Returned; - j_decompress_ptr JpegInfo = (j_decompress_ptr)_JpegInfo; - - //added on 2003-08-31 as explained in sf bug 596793 - jpgErrorOccured = IL_FALSE; - - // sam. errorHandler = JpegInfo->err->error_exit; - // sam. JpegInfo->err->error_exit = ExitErrorHandle; - jpeg_start_decompress((j_decompress_ptr)JpegInfo); - - if (!ilTexImage(JpegInfo->output_width, JpegInfo->output_height, 1, (ILubyte)JpegInfo->output_components, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - switch (iCurImage->Bpp) - { - case 1: - iCurImage->Format = IL_LUMINANCE; - break; - case 3: - iCurImage->Format = IL_RGB; - break; - case 4: - iCurImage->Format = IL_RGBA; - break; - default: - //@TODO: Anyway to get here? Need to error out or something... - break; - } - - TempPtr[0] = iCurImage->Data; - while (JpegInfo->output_scanline < JpegInfo->output_height) { - Returned = jpeg_read_scanlines(JpegInfo, TempPtr, 1); // anyway to make it read all at once? - TempPtr[0] += iCurImage->Bps; - if (Returned == 0) - break; - } - - // sam. JpegInfo->err->error_exit = errorHandler; - - if (jpgErrorOccured) - return IL_FALSE; - - return ilFixImage(); -#endif -#endif - return IL_FALSE; -} - - - -// Access point for applications wishing to use the jpeg library directly in -// conjunction with DevIL. -// -// The caller must set up the desired parameters by e.g. calling -// jpeg_set_defaults and overriding the parameters the caller wishes -// to change, such as quality, before calling this function. The caller -// is also responsible for calling jpeg_finish_compress in case the -// caller still needs to compressor for something. -// -ILboolean ilSaveFromJpegStruct(void *_JpegInfo) -{ -#ifndef IL_NO_JPG -#ifndef IL_USE_IJL - void (*errorHandler)(); - JSAMPROW row_pointer[1]; - ILimage *TempImage; - ILubyte *TempData; - j_compress_ptr JpegInfo = (j_compress_ptr)_JpegInfo; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - //added on 2003-08-31 as explained in SF bug 596793 - jpgErrorOccured = IL_FALSE; - - errorHandler = JpegInfo->err->error_exit; - JpegInfo->err->error_exit = ExitErrorHandle; - - - if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) { - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - if (TempImage == NULL) { - return IL_FALSE; - } - } - else { - TempImage = iCurImage; - } - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - } - else { - TempData = TempImage->Data; - } - - JpegInfo->image_width = TempImage->Width; // image width and height, in pixels - JpegInfo->image_height = TempImage->Height; - JpegInfo->input_components = TempImage->Bpp; // # of color components per pixel - - jpeg_start_compress(JpegInfo, IL_TRUE); - - //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer - - while (JpegInfo->next_scanline < JpegInfo->image_height) { - // jpeg_write_scanlines expects an array of pointers to scanlines. - // Here the array is only one element long, but you could pass - // more than one scanline at a time if that's more convenient. - row_pointer[0] = &TempData[JpegInfo->next_scanline * TempImage->Bps]; - (void) jpeg_write_scanlines(JpegInfo, row_pointer, 1); - } - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) - ifree(TempData); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return (!jpgErrorOccured); -#endif//IL_USE_IJL -#endif//IL_NO_JPG - return IL_FALSE; -} - - -#if defined(_MSC_VER) - #pragma warning(pop) - //#pragma warning(disable : 4756) // Disables 'named type definition in parentheses' warning -#endif - -#endif//IL_NO_JPG diff --git a/DevIL/src-IL/src/il_jpeg.cpp b/DevIL/src-IL/src/il_jpeg.cpp new file mode 100644 index 00000000..54e18756 --- /dev/null +++ b/DevIL/src-IL/src/il_jpeg.cpp @@ -0,0 +1,1001 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/14/2009 +// +// Filename: src-IL/src/il_jpeg.c +// +// Description: Jpeg (.jpg) functions +// +//----------------------------------------------------------------------------- +// +// Most of the comments here are sufficient, as we're just using libjpeg. +// I have left most of the libjpeg example's comments intact, though. +// + +#include "il_internal.h" + +#ifndef IL_NO_JPG + #ifndef IL_USE_IJL + #ifdef RGB_RED + #undef RGB_RED + #undef RGB_GREEN + #undef RGB_BLUE + #endif + #define RGB_RED 0 + #define RGB_GREEN 1 + #define RGB_BLUE 2 + + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4005) // Redefinitions in + #pragma warning(disable : 4142) // jmorecfg.h + #endif + + #include "jpeglib.h" + + #if JPEG_LIB_VERSION < 62 + #warning DevIL was designed with libjpeg 6b or higher in mind. Consider upgrading at www.ijg.org + #endif + #else + #include + #include + #endif + +#include "il_jpeg.h" +#include + + +#if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifdef IL_USE_IJL + //pragma comment(lib, "ijl15.lib") + #else + #ifndef _DEBUG + #pragma comment(lib, "libjpeg.lib") + #else + //#pragma comment(lib, "libjpeg-d.lib") + #pragma comment(lib, "libjpeg.lib") + #endif + #endif//IL_USE_IJL + #endif +#endif + + +static ILboolean jpgErrorOccured = IL_FALSE; + +// define a protype of ilLoadFromJpegStruct +ILboolean ilLoadFromJpegStruct(void *_JpegInfo); + +// Internal function used to get the .jpg header from the current file. +void iGetJpgHead(ILubyte *Header) +{ + Header[0] = igetc(); + Header[1] = igetc(); + return; +} + + +// Internal function used to check if the HEADER is a valid .Jpg header. +ILboolean iCheckJpg(ILubyte Header[2]) +{ + if (Header[0] != 0xFF || Header[1] != 0xD8) + return IL_FALSE; + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidJpeg() +{ + ILubyte Head[2]; + + iGetJpgHead(Head); + iseek(-2, IL_SEEK_CUR); // Go ahead and restore to previous state + + return iCheckJpg(Head); +} + + +//! Checks if the file specified in FileName is a valid .jpg file. +ILboolean ilIsValidJpeg(ILconst_string FileName) +{ + ILHANDLE JpegFile; + ILboolean bJpeg = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("jpg")) && + !iCheckExtension(FileName, IL_TEXT("jpe")) && + !iCheckExtension(FileName, IL_TEXT("jpeg")) && + !iCheckExtension(FileName, IL_TEXT("jif")) && + !iCheckExtension(FileName, IL_TEXT("jfif"))) + { + ilSetError(IL_INVALID_EXTENSION); + return bJpeg; + } + + JpegFile = iopenr(FileName); + if (JpegFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bJpeg; + } + + bJpeg = ilIsValidJpegF(JpegFile); + icloser(JpegFile); + + return bJpeg; +} + + +//! Checks if the ILHANDLE contains a valid .jpg file at the current position. +ILboolean ilIsValidJpegF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidJpeg(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +ILboolean ilIsValidJpegL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidJpeg(); +} + + +#ifndef IL_USE_IJL // Use libjpeg instead of the IJL. + +// Overrides libjpeg's stupid error/warning handlers. =P +void ExitErrorHandle (struct jpeg_common_struct *JpegInfo) +{ + ilSetError(IL_LIB_JPEG_ERROR); + jpgErrorOccured = IL_TRUE; + return; +} +void OutputMsg(struct jpeg_common_struct *JpegInfo) +{ + return; +} + + +//! Reads a jpeg file +ILboolean ilLoadJpeg(ILconst_string FileName) +{ + ILHANDLE JpegFile; + ILboolean bJpeg = IL_FALSE; + + JpegFile = iopenr(FileName); + if (JpegFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bJpeg; + } + + bJpeg = ilLoadJpegF(JpegFile); + icloser(JpegFile); + + return bJpeg; +} + + +//! Reads an already-opened jpeg file +ILboolean ilLoadJpegF(ILHANDLE File) +{ + ILboolean bRet; + ILuint FirstPos; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadJpegInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +// Reads from a memory "lump" containing a jpeg +ILboolean ilLoadJpegL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadJpegInternal(); +} + + +typedef struct { + struct jpeg_source_mgr pub; /* public fields */ + + JOCTET * buffer; /* start of buffer */ + boolean start_of_file; /* have we gotten any data yet? */ +} iread_mgr; + +typedef iread_mgr * iread_ptr; + +#define INPUT_BUF_SIZE 4096 // choose an efficiently iread'able size + + +METHODDEF(void) +init_source (j_decompress_ptr cinfo) +{ + iread_ptr src = (iread_ptr) cinfo->src; + src->start_of_file = TRUE; +} + + +METHODDEF(boolean) +fill_input_buffer (j_decompress_ptr cinfo) +{ + iread_ptr src = (iread_ptr) cinfo->src; + ILint nbytes; + + nbytes = iread(src->buffer, 1, INPUT_BUF_SIZE); + + if (nbytes <= 0) { + if (src->start_of_file) { // Treat empty input file as fatal error + //ERREXIT(cinfo, JERR_INPUT_EMPTY); + jpgErrorOccured = IL_TRUE; + } + //WARNMS(cinfo, JWRN_JPEG_EOF); + // Insert a fake EOI marker + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + return IL_FALSE; + } + if (nbytes < INPUT_BUF_SIZE) { + ilGetError(); // Gets rid of the IL_FILE_READ_ERROR. + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = IL_FALSE; + + return IL_TRUE; +} + + +METHODDEF(void) +skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + iread_ptr src = (iread_ptr) cinfo->src; + + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +METHODDEF(void) +term_source (j_decompress_ptr cinfo) +{ + // no work necessary here +} + + +GLOBAL(void) +devil_jpeg_read_init (j_decompress_ptr cinfo) +{ + iread_ptr src; + + if ( cinfo->src == NULL ) { // first time for this JPEG object? + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(iread_mgr) ); + src = (iread_ptr) cinfo->src; + src->buffer = (JOCTET *) + (*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_PERMANENT, + INPUT_BUF_SIZE * sizeof(JOCTET) ); + } + + src = (iread_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method + src->pub.term_source = term_source; + src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read + src->pub.next_input_byte = NULL; // until buffer loaded +} + + +jmp_buf JpegJumpBuffer; + +static void iJpegErrorExit( j_common_ptr cinfo ) +{ + ilSetError( IL_LIB_JPEG_ERROR ); + jpeg_destroy( cinfo ); + longjmp( JpegJumpBuffer, 1 ); +} + +// Internal function used to load the jpeg. +ILboolean iLoadJpegInternal() +{ + struct jpeg_error_mgr Error; + struct jpeg_decompress_struct JpegInfo; + ILboolean result; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + JpegInfo.err = jpeg_std_error(&Error); // init standard error handlers + Error.error_exit = iJpegErrorExit; // add our exit handler + Error.output_message = OutputMsg; + + if ((result = setjmp(JpegJumpBuffer) == 0) != IL_FALSE) { + jpeg_create_decompress(&JpegInfo); + JpegInfo.do_block_smoothing = IL_TRUE; + JpegInfo.do_fancy_upsampling = IL_TRUE; + + //jpeg_stdio_src(&JpegInfo, iGetFile()); + + devil_jpeg_read_init(&JpegInfo); + jpeg_read_header(&JpegInfo, IL_TRUE); + + result = ilLoadFromJpegStruct(&JpegInfo); + + jpeg_finish_decompress(&JpegInfo); + jpeg_destroy_decompress(&JpegInfo); + + } + else + { + jpeg_destroy_decompress(&JpegInfo); + } + + //return ilFixImage(); // No need to call it again (called first in ilLoadFromJpegStruct). + return result; +} + + + +typedef struct +{ + struct jpeg_destination_mgr pub; + JOCTET *buffer; + ILboolean bah; +} iwrite_mgr; + +typedef iwrite_mgr *iwrite_ptr; + +#define OUTPUT_BUF_SIZE 4096 + + +METHODDEF(void) +init_destination(j_compress_ptr cinfo) +{ + iwrite_ptr dest = (iwrite_ptr)cinfo->dest; + dest->buffer = (JOCTET *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + OUTPUT_BUF_SIZE * sizeof(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + return; +} + +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + iwrite_ptr dest = (iwrite_ptr)cinfo->dest; + iwrite(dest->buffer, 1, OUTPUT_BUF_SIZE); + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + return IL_TRUE; +} + +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + iwrite_ptr dest = (iwrite_ptr)cinfo->dest; + iwrite(dest->buffer, 1, OUTPUT_BUF_SIZE - (ILuint)dest->pub.free_in_buffer); + return; +} + + +GLOBAL(void) +devil_jpeg_write_init(j_compress_ptr cinfo) +{ + iwrite_ptr dest; + + if (cinfo->dest == NULL) { // first time for this JPEG object? + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(iwrite_mgr)); + dest = (iwrite_ptr)cinfo->dest; + } + + dest = (iwrite_ptr)cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + + return; +} + + +//! Writes a Jpeg file +ILboolean ilSaveJpeg(const ILstring FileName) +{ + ILHANDLE JpegFile; + ILuint JpegSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + JpegFile = iopenw(FileName); + if (JpegFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + JpegSize = ilSaveJpegF(JpegFile); + iclosew(JpegFile); + + if (JpegSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Jpeg to an already-opened file +ILuint ilSaveJpegF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveJpegInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Jpeg to a memory "lump" +ILuint ilSaveJpegL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveJpegInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the Jpeg. +ILboolean iSaveJpegInternal() +{ + struct jpeg_compress_struct JpegInfo; + struct jpeg_error_mgr Error; + JSAMPROW row_pointer[1]; + ILimage *TempImage; + ILubyte *TempData; + ILenum Type = 0; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + /*if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) + Quality = 85; // Not sure how low we should dare go... + else + Quality = 99;*/ + + if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) { + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + if (TempImage == NULL) { + return IL_FALSE; + } + } + else { + TempImage = iCurImage; + } + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + } + else { + TempData = TempImage->Data; + } + + + JpegInfo.err = jpeg_std_error(&Error); + // Now we can initialize the JPEG compression object. + jpeg_create_compress(&JpegInfo); + + //jpeg_stdio_dest(&JpegInfo, JpegFile); + devil_jpeg_write_init(&JpegInfo); + + JpegInfo.image_width = TempImage->Width; // image width and height, in pixels + JpegInfo.image_height = TempImage->Height; + JpegInfo.input_components = TempImage->Bpp; // # of color components per pixel + + // John Villar's addition + if (TempImage->Bpp == 1) + JpegInfo.in_color_space = JCS_GRAYSCALE; + else + JpegInfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&JpegInfo); + +/*#ifndef IL_USE_JPEGLIB_UNMODIFIED + Type = iGetInt(IL_JPG_SAVE_FORMAT); + if (Type == IL_EXIF) { + JpegInfo.write_JFIF_header = FALSE; + JpegInfo.write_EXIF_header = TRUE; + } + else if (Type == IL_JFIF) { + JpegInfo.write_JFIF_header = TRUE; + JpegInfo.write_EXIF_header = FALSE; + } //EXIF not present in libjpeg... +#else*/ + Type = Type; + JpegInfo.write_JFIF_header = TRUE; +//#endif//IL_USE_JPEGLIB_UNMODIFIED + + // Set the quality output + jpeg_set_quality(&JpegInfo, iGetInt(IL_JPG_QUALITY), IL_TRUE); + // Sets progressive saving here + if (ilGetBoolean(IL_JPG_PROGRESSIVE)) + jpeg_simple_progression(&JpegInfo); + + jpeg_start_compress(&JpegInfo, IL_TRUE); + + //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer + + while (JpegInfo.next_scanline < JpegInfo.image_height) { + // jpeg_write_scanlines expects an array of pointers to scanlines. + // Here the array is only one element long, but you could pass + // more than one scanline at a time if that's more convenient. + row_pointer[0] = &TempData[JpegInfo.next_scanline * TempImage->Bps]; + (void) jpeg_write_scanlines(&JpegInfo, row_pointer, 1); + } + + // Step 6: Finish compression + jpeg_finish_compress(&JpegInfo); + + // Step 7: release JPEG compression object + + // This is an important step since it will release a good deal of memory. + jpeg_destroy_compress(&JpegInfo); + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) + ifree(TempData); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return IL_TRUE; +} + + + +#else // Use the IJL instead of libjpeg. + + + +//! Reads a jpeg file +ILboolean ilLoadJpeg(ILconst_string FileName) +{ + if (!iFileExists(FileName)) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + return iLoadJpegInternal(FileName, NULL, 0); +} + + +// Reads from a memory "lump" containing a jpeg +ILboolean ilLoadJpegL(void *Lump, ILuint Size) +{ + return iLoadJpegInternal(NULL, Lump, Size); +} + + +// Internal function used to load the jpeg. +ILboolean iLoadJpegInternal(ILstring FileName, void *Lump, ILuint Size) +{ + JPEG_CORE_PROPERTIES Image; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (ijlInit(&Image) != IJL_OK) { + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + + if (FileName != NULL) { + Image.JPGFile = FileName; + if (ijlRead(&Image, IJL_JFILE_READPARAMS) != IJL_OK) { + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + } + else { + Image.JPGBytes = Lump; + Image.JPGSizeBytes = Size > 0 ? Size : UINT_MAX; + if (ijlRead(&Image, IJL_JBUFF_READPARAMS) != IJL_OK) { + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + } + + switch (Image.JPGChannels) + { + case 1: + Image.JPGColor = IJL_G; + Image.DIBChannels = 1; + Image.DIBColor = IJL_G; + iCurImage->Format = IL_LUMINANCE; + break; + + case 3: + Image.JPGColor = IJL_YCBCR; + Image.DIBChannels = 3; + Image.DIBColor = IJL_RGB; + iCurImage->Format = IL_RGB; + break; + + case 4: + Image.JPGColor = IJL_YCBCRA_FPX; + Image.DIBChannels = 4; + Image.DIBColor = IJL_RGBA_FPX; + iCurImage->Format = IL_RGBA; + break; + + default: + // This catches everything else, but no + // color twist will be performed by the IJL. + /*Image.DIBColor = (IJL_COLOR)IJL_OTHER; + Image.JPGColor = (IJL_COLOR)IJL_OTHER; + Image.DIBChannels = Image.JPGChannels; + break;*/ + ijlFree(&Image); + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + + if (!ilTexImage(Image.JPGWidth, Image.JPGHeight, 1, (ILubyte)Image.DIBChannels, iCurImage->Format, IL_UNSIGNED_BYTE, NULL)) { + ijlFree(&Image); + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + Image.DIBWidth = Image.JPGWidth; + Image.DIBHeight = Image.JPGHeight; + Image.DIBPadBytes = 0; + Image.DIBBytes = iCurImage->Data; + + if (FileName != NULL) { + if (ijlRead(&Image, IJL_JFILE_READWHOLEIMAGE) != IJL_OK) { + ijlFree(&Image); + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + } + else { + if (ijlRead(&Image, IJL_JBUFF_READWHOLEIMAGE) != IJL_OK) { + ijlFree(&Image); + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + } + + ijlFree(&Image); + return ilFixImage(); +} + + +//! Writes a Jpeg file +ILboolean ilSaveJpeg(ILconst_string FileName) +{ + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + return iSaveJpegInternal(FileName, NULL, 0); +} + + +//! Writes a Jpeg to a memory "lump" +ILboolean ilSaveJpegL(void *Lump, ILuint Size) +{ + return iSaveJpegInternal(NULL, Lump, Size); +} + + +// Internal function used to save the Jpeg. +ILboolean iSaveJpegInternal(ILstring FileName, void *Lump, ILuint Size) +{ + JPEG_CORE_PROPERTIES Image; + ILuint Quality; + ILimage *TempImage; + ILubyte *TempData; + + imemclear(&Image, sizeof(JPEG_CORE_PROPERTIES)); + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + if (FileName == NULL && Lump == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) + Quality = 85; // Not sure how low we should dare go... + else + Quality = 99; + + if (ijlInit(&Image) != IJL_OK) { + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + + if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_RGBA && iCurImage->Format != IL_LUMINANCE) + || iCurImage->Bpc != 1) { + if (iCurImage->Format == IL_BGRA) + Temp = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); + else + Temp = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + if (Temp == NULL) { + return IL_FALSE; + } + } + else { + Temp = iCurImage; + } + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + } + else { + TempData = TempImage->Data; + } + + // Setup DIB + Image.DIBWidth = TempImage->Width; + Image.DIBHeight = TempImage->Height; + Image.DIBChannels = TempImage->Bpp; + Image.DIBBytes = TempData; + Image.DIBPadBytes = 0; + + // Setup JPEG + Image.JPGWidth = TempImage->Width; + Image.JPGHeight = TempImage->Height; + Image.JPGChannels = TempImage->Bpp; + + switch (Temp->Bpp) + { + case 1: + Image.DIBColor = IJL_G; + Image.JPGColor = IJL_G; + Image.JPGSubsampling = IJL_NONE; + break; + case 3: + Image.DIBColor = IJL_RGB; + Image.JPGColor = IJL_YCBCR; + Image.JPGSubsampling = IJL_411; + break; + case 4: + Image.DIBColor = IJL_RGBA_FPX; + Image.JPGColor = IJL_YCBCRA_FPX; + Image.JPGSubsampling = IJL_4114; + break; + } + + if (FileName != NULL) { + Image.JPGFile = FileName; + if (ijlWrite(&Image, IJL_JFILE_WRITEWHOLEIMAGE) != IJL_OK) { + if (TempImage != iCurImage) + ilCloseImage(TempImage); + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + } + else { + Image.JPGBytes = Lump; + Image.JPGSizeBytes = Size; + if (ijlWrite(&Image, IJL_JBUFF_WRITEWHOLEIMAGE) != IJL_OK) { + if (TempImage != iCurImage) + ilCloseImage(TempImage); + ilSetError(IL_LIB_JPEG_ERROR); + return IL_FALSE; + } + } + + ijlFree(&Image); + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) + ifree(TempData); + if (Temp != iCurImage) + ilCloseImage(Temp); + + return IL_TRUE; +} + +#endif//IL_USE_IJL + + +// Access point for applications wishing to use the jpeg library directly in +// conjunction with DevIL. +// +// The decompressor must be set up with an input source and all desired parameters +// this function is called. The caller must call jpeg_finish_decompress because +// the caller may still need decompressor after calling this for e.g. examining +// saved markers. +ILboolean ilLoadFromJpegStruct(void *_JpegInfo) +{ +#ifndef IL_NO_JPG +#ifndef IL_USE_IJL + // sam. void (*errorHandler)(j_common_ptr); + ILubyte *TempPtr[1]; + ILuint Returned; + j_decompress_ptr JpegInfo = (j_decompress_ptr)_JpegInfo; + + //added on 2003-08-31 as explained in sf bug 596793 + jpgErrorOccured = IL_FALSE; + + // sam. errorHandler = JpegInfo->err->error_exit; + // sam. JpegInfo->err->error_exit = ExitErrorHandle; + jpeg_start_decompress((j_decompress_ptr)JpegInfo); + + if (!ilTexImage(JpegInfo->output_width, JpegInfo->output_height, 1, (ILubyte)JpegInfo->output_components, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + switch (iCurImage->Bpp) + { + case 1: + iCurImage->Format = IL_LUMINANCE; + break; + case 3: + iCurImage->Format = IL_RGB; + break; + case 4: + iCurImage->Format = IL_RGBA; + break; + default: + //@TODO: Anyway to get here? Need to error out or something... + break; + } + + TempPtr[0] = iCurImage->Data; + while (JpegInfo->output_scanline < JpegInfo->output_height) { + Returned = jpeg_read_scanlines(JpegInfo, TempPtr, 1); // anyway to make it read all at once? + TempPtr[0] += iCurImage->Bps; + if (Returned == 0) + break; + } + + // sam. JpegInfo->err->error_exit = errorHandler; + + if (jpgErrorOccured) + return IL_FALSE; + + return ilFixImage(); +#endif +#endif + return IL_FALSE; +} + + + +// Access point for applications wishing to use the jpeg library directly in +// conjunction with DevIL. +// +// The caller must set up the desired parameters by e.g. calling +// jpeg_set_defaults and overriding the parameters the caller wishes +// to change, such as quality, before calling this function. The caller +// is also responsible for calling jpeg_finish_compress in case the +// caller still needs to compressor for something. +// +ILboolean ilSaveFromJpegStruct(void *_JpegInfo) +{ +#ifndef IL_NO_JPG +#ifndef IL_USE_IJL + void (*errorHandler)(); + JSAMPROW row_pointer[1]; + ILimage *TempImage; + ILubyte *TempData; + j_compress_ptr JpegInfo = (j_compress_ptr)_JpegInfo; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + //added on 2003-08-31 as explained in SF bug 596793 + jpgErrorOccured = IL_FALSE; + + errorHandler = JpegInfo->err->error_exit; + JpegInfo->err->error_exit = ExitErrorHandle; + + + if ((iCurImage->Format != IL_RGB && iCurImage->Format != IL_LUMINANCE) || iCurImage->Bpc != 1) { + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + if (TempImage == NULL) { + return IL_FALSE; + } + } + else { + TempImage = iCurImage; + } + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + } + else { + TempData = TempImage->Data; + } + + JpegInfo->image_width = TempImage->Width; // image width and height, in pixels + JpegInfo->image_height = TempImage->Height; + JpegInfo->input_components = TempImage->Bpp; // # of color components per pixel + + jpeg_start_compress(JpegInfo, IL_TRUE); + + //row_stride = image_width * 3; // JSAMPLEs per row in image_buffer + + while (JpegInfo->next_scanline < JpegInfo->image_height) { + // jpeg_write_scanlines expects an array of pointers to scanlines. + // Here the array is only one element long, but you could pass + // more than one scanline at a time if that's more convenient. + row_pointer[0] = &TempData[JpegInfo->next_scanline * TempImage->Bps]; + (void) jpeg_write_scanlines(JpegInfo, row_pointer, 1); + } + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) + ifree(TempData); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return (!jpgErrorOccured); +#endif//IL_USE_IJL +#endif//IL_NO_JPG + return IL_FALSE; +} + + +#if defined(_MSC_VER) + #pragma warning(pop) + //#pragma warning(disable : 4756) // Disables 'named type definition in parentheses' warning +#endif + +#endif//IL_NO_JPG diff --git a/DevIL/src-IL/src/il_ktx.c b/DevIL/src-IL/src/il_ktx.c deleted file mode 100644 index 407ebb16..00000000 --- a/DevIL/src-IL/src/il_ktx.c +++ /dev/null @@ -1,271 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2016 by Denton Woods -// Last modified: 05/15/2016 -// -// Filename: src-IL/src/il_ktx.c -// -// Description: Reads a Khronos Texture .ktx file -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_KTX -#include "il_bits.h" - - -ILboolean iIsValidKtx(void); -ILboolean iLoadKtxInternal(); - - -#ifdef _MSC_VER -#pragma pack(push, packed_struct, 1) -#endif -typedef struct KTX_HEAD -{ - ILubyte identifier[12]; - ILuint endianness; - ILuint glType; - ILuint glTypeSize; - ILuint glFormat; - ILuint glInternalFormat; - ILuint glBaseInternalFormat; - ILuint pixelWidth; - ILuint pixelHeight; - ILuint pixelDepth; - ILuint numberOfArrayElements; - ILuint numberOfFaces; - ILuint numberOfMipmapLevels; - ILuint bytesOfKeyValueData; -} IL_PACKSTRUCT KTX_HEAD; -#ifdef _MSC_VER -#pragma pack(pop, packed_struct) -#endif - - -// From GL/GL.h -#define I_GL_BYTE 0x1400 -#define I_GL_UNSIGNED_BYTE 0x1401 -#define I_GL_SHORT 0x1402 -#define I_GL_UNSIGNED_SHORT 0x1403 -#define I_GL_INT 0x1404 -#define I_GL_UNSIGNED_INT 0x1405 -#define I_GL_FLOAT 0x1406 -//#define I_GL_2_BYTES 0x1407 -//#define I_GL_3_BYTES 0x1408 -//#define I_GL_4_BYTES 0x1409 -#define I_GL_DOUBLE 0x140A -#define I_GL_ALPHA 0x1906 -#define I_GL_RGB 0x1907 -#define I_GL_RGBA 0x1908 -#define I_GL_LUMINANCE 0x1909 -#define I_GL_LUMINANCE_ALPHA 0x190A - - - -ILboolean ilIsValidKtx(ILconst_string FileName) -{ - ILHANDLE KtxFile; - ILboolean bKtx = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("ktx"))) { - ilSetError(IL_INVALID_EXTENSION); - return bKtx; - } - - KtxFile = iopenr(FileName); - if (KtxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bKtx; - } - - bKtx = ilIsValidKtxF(KtxFile); - icloser(KtxFile); - - return bKtx; -} - - -ILboolean ilIsValidKtxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidKtx(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -ILboolean ilIsValidKtxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidKtx(); -} - - -ILboolean iIsValidKtx() -{ - ILubyte Signature[8]; - ILint Read; - - /*Read = iread(Signature, 1, 8); - iseek(-Read, IL_SEEK_CUR);*/ - - return IL_FALSE; -} - - -//! Reads a .ktx file -ILboolean ilLoadKtx(ILconst_string FileName) -{ - ILHANDLE KtxFile; - ILboolean bKtx = IL_FALSE; - - KtxFile = iopenr(FileName); - if (KtxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bKtx; - } - - bKtx = ilLoadKtxF(KtxFile); - icloser(KtxFile); - - return bKtx; -} - - -//! Reads an already-opened .ktx file -ILboolean ilLoadKtxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadKtxInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .ktx -ILboolean ilLoadKtxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadKtxInternal(); -} - - -// Note: .Ktx support has not been tested yet! -// https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ -ILboolean iLoadKtxInternal() -{ - KTX_HEAD Header; - ILuint imageSize; - ILenum Format; - ILubyte Bpp; - ILubyte FileIdentifier[12] = { - //0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A - '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' - }; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - /*Header.Width = GetLittleShort(); - Header.Height = GetLittleShort(); - Header.Dummy = GetLittleInt();*/ - - if (iread(Header.identifier, 1, 12) != 12) - return IL_FALSE; - Header.endianness = GetLittleUInt(); - Header.glType = GetLittleUInt(); - Header.glTypeSize = GetLittleUInt(); - Header.glFormat = GetLittleUInt(); - Header.glInternalFormat = GetLittleUInt(); - Header.glBaseInternalFormat = GetLittleUInt(); - Header.pixelWidth = GetLittleUInt(); - Header.pixelHeight = GetLittleUInt(); - Header.pixelDepth = GetLittleUInt(); - Header.numberOfArrayElements = GetLittleUInt(); - Header.numberOfFaces = GetLittleUInt(); - Header.numberOfMipmapLevels = GetLittleUInt(); - Header.bytesOfKeyValueData = GetLittleUInt(); - - - if (memcmp(Header.identifier, FileIdentifier, 12) || Header.endianness != 0x04030201) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - //@TODO: Additional types - if (Header.glType != I_GL_UNSIGNED_BYTE || Header.glTypeSize != 1) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - //@TODO: Additional formats - if (Header.glFormat <= I_GL_ALPHA || Header.glFormat >= I_GL_LUMINANCE_ALPHA || Header.glInternalFormat != Header.glFormat /*|| Header.glBaseInternalFormat != Header.glFormat*/) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - //@TODO: Mipmaps, etc. - if (Header.numberOfArrayElements != 0 || Header.numberOfFaces != 1 || Header.numberOfMipmapLevels != 1) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - //@TODO: Parse this data - if (iseek(Header.bytesOfKeyValueData, IL_SEEK_CUR)) - return IL_FALSE; - - switch (Header.glFormat) - { - case I_GL_LUMINANCE: - Bpp = 1; - Format = IL_LUMINANCE; - break; - case IL_LUMINANCE_ALPHA: - Bpp = 2; - Format = IL_LUMINANCE_ALPHA; - break; - case I_GL_RGB: - Bpp = 3; - Format = IL_RGB; - break; - case I_GL_RGBA: - Bpp = 4; - Format = IL_RGBA; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - //@TODO: More than just RGBA - if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - imageSize = GetLittleUInt(); - if (imageSize != Header.pixelWidth * Header.pixelHeight * Bpp) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - if (iread(iCurImage->Data, Bpp, Header.pixelWidth * Header.pixelHeight) != Header.pixelWidth * Header.pixelHeight) - return IL_FALSE; - - return ilFixImage(); -} - - -#endif//IL_NO_KTX diff --git a/DevIL/src-IL/src/il_ktx.cpp b/DevIL/src-IL/src/il_ktx.cpp new file mode 100644 index 00000000..407ebb16 --- /dev/null +++ b/DevIL/src-IL/src/il_ktx.cpp @@ -0,0 +1,271 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2016 by Denton Woods +// Last modified: 05/15/2016 +// +// Filename: src-IL/src/il_ktx.c +// +// Description: Reads a Khronos Texture .ktx file +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_KTX +#include "il_bits.h" + + +ILboolean iIsValidKtx(void); +ILboolean iLoadKtxInternal(); + + +#ifdef _MSC_VER +#pragma pack(push, packed_struct, 1) +#endif +typedef struct KTX_HEAD +{ + ILubyte identifier[12]; + ILuint endianness; + ILuint glType; + ILuint glTypeSize; + ILuint glFormat; + ILuint glInternalFormat; + ILuint glBaseInternalFormat; + ILuint pixelWidth; + ILuint pixelHeight; + ILuint pixelDepth; + ILuint numberOfArrayElements; + ILuint numberOfFaces; + ILuint numberOfMipmapLevels; + ILuint bytesOfKeyValueData; +} IL_PACKSTRUCT KTX_HEAD; +#ifdef _MSC_VER +#pragma pack(pop, packed_struct) +#endif + + +// From GL/GL.h +#define I_GL_BYTE 0x1400 +#define I_GL_UNSIGNED_BYTE 0x1401 +#define I_GL_SHORT 0x1402 +#define I_GL_UNSIGNED_SHORT 0x1403 +#define I_GL_INT 0x1404 +#define I_GL_UNSIGNED_INT 0x1405 +#define I_GL_FLOAT 0x1406 +//#define I_GL_2_BYTES 0x1407 +//#define I_GL_3_BYTES 0x1408 +//#define I_GL_4_BYTES 0x1409 +#define I_GL_DOUBLE 0x140A +#define I_GL_ALPHA 0x1906 +#define I_GL_RGB 0x1907 +#define I_GL_RGBA 0x1908 +#define I_GL_LUMINANCE 0x1909 +#define I_GL_LUMINANCE_ALPHA 0x190A + + + +ILboolean ilIsValidKtx(ILconst_string FileName) +{ + ILHANDLE KtxFile; + ILboolean bKtx = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("ktx"))) { + ilSetError(IL_INVALID_EXTENSION); + return bKtx; + } + + KtxFile = iopenr(FileName); + if (KtxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bKtx; + } + + bKtx = ilIsValidKtxF(KtxFile); + icloser(KtxFile); + + return bKtx; +} + + +ILboolean ilIsValidKtxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidKtx(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +ILboolean ilIsValidKtxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidKtx(); +} + + +ILboolean iIsValidKtx() +{ + ILubyte Signature[8]; + ILint Read; + + /*Read = iread(Signature, 1, 8); + iseek(-Read, IL_SEEK_CUR);*/ + + return IL_FALSE; +} + + +//! Reads a .ktx file +ILboolean ilLoadKtx(ILconst_string FileName) +{ + ILHANDLE KtxFile; + ILboolean bKtx = IL_FALSE; + + KtxFile = iopenr(FileName); + if (KtxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bKtx; + } + + bKtx = ilLoadKtxF(KtxFile); + icloser(KtxFile); + + return bKtx; +} + + +//! Reads an already-opened .ktx file +ILboolean ilLoadKtxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadKtxInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .ktx +ILboolean ilLoadKtxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadKtxInternal(); +} + + +// Note: .Ktx support has not been tested yet! +// https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ +ILboolean iLoadKtxInternal() +{ + KTX_HEAD Header; + ILuint imageSize; + ILenum Format; + ILubyte Bpp; + ILubyte FileIdentifier[12] = { + //0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A + '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' + }; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + /*Header.Width = GetLittleShort(); + Header.Height = GetLittleShort(); + Header.Dummy = GetLittleInt();*/ + + if (iread(Header.identifier, 1, 12) != 12) + return IL_FALSE; + Header.endianness = GetLittleUInt(); + Header.glType = GetLittleUInt(); + Header.glTypeSize = GetLittleUInt(); + Header.glFormat = GetLittleUInt(); + Header.glInternalFormat = GetLittleUInt(); + Header.glBaseInternalFormat = GetLittleUInt(); + Header.pixelWidth = GetLittleUInt(); + Header.pixelHeight = GetLittleUInt(); + Header.pixelDepth = GetLittleUInt(); + Header.numberOfArrayElements = GetLittleUInt(); + Header.numberOfFaces = GetLittleUInt(); + Header.numberOfMipmapLevels = GetLittleUInt(); + Header.bytesOfKeyValueData = GetLittleUInt(); + + + if (memcmp(Header.identifier, FileIdentifier, 12) || Header.endianness != 0x04030201) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + //@TODO: Additional types + if (Header.glType != I_GL_UNSIGNED_BYTE || Header.glTypeSize != 1) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + //@TODO: Additional formats + if (Header.glFormat <= I_GL_ALPHA || Header.glFormat >= I_GL_LUMINANCE_ALPHA || Header.glInternalFormat != Header.glFormat /*|| Header.glBaseInternalFormat != Header.glFormat*/) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + //@TODO: Mipmaps, etc. + if (Header.numberOfArrayElements != 0 || Header.numberOfFaces != 1 || Header.numberOfMipmapLevels != 1) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + //@TODO: Parse this data + if (iseek(Header.bytesOfKeyValueData, IL_SEEK_CUR)) + return IL_FALSE; + + switch (Header.glFormat) + { + case I_GL_LUMINANCE: + Bpp = 1; + Format = IL_LUMINANCE; + break; + case IL_LUMINANCE_ALPHA: + Bpp = 2; + Format = IL_LUMINANCE_ALPHA; + break; + case I_GL_RGB: + Bpp = 3; + Format = IL_RGB; + break; + case I_GL_RGBA: + Bpp = 4; + Format = IL_RGBA; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + //@TODO: More than just RGBA + if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + imageSize = GetLittleUInt(); + if (imageSize != Header.pixelWidth * Header.pixelHeight * Bpp) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + if (iread(iCurImage->Data, Bpp, Header.pixelWidth * Header.pixelHeight) != Header.pixelWidth * Header.pixelHeight) + return IL_FALSE; + + return ilFixImage(); +} + + +#endif//IL_NO_KTX diff --git a/DevIL/src-IL/src/il_lif.c b/DevIL/src-IL/src/il_lif.c deleted file mode 100644 index 456975e6..00000000 --- a/DevIL/src-IL/src/il_lif.c +++ /dev/null @@ -1,198 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_lif.c -// -// Description: Reads a Homeworld image. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_LIF -#include "il_lif.h" - - -//! Checks if the file specified in FileName is a valid Lif file. -ILboolean ilIsValidLif(ILconst_string FileName) -{ - ILHANDLE LifFile; - ILboolean bLif = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("lif"))) { - ilSetError(IL_INVALID_EXTENSION); - return bLif; - } - - LifFile = iopenr(FileName); - if (LifFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bLif; - } - - bLif = ilIsValidLifF(LifFile); - icloser(LifFile); - - return bLif; -} - - -//! Checks if the ILHANDLE contains a valid Lif file at the current position. -ILboolean ilIsValidLifF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidLif(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid Lif lump. -ILboolean ilIsValidLifL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidLif(); -} - - -// Internal function used to get the Lif header from the current file. -ILboolean iGetLifHead(LIF_HEAD *Header) -{ - - iread(Header->Id, 1, 8); - - Header->Version = GetLittleUInt(); - - Header->Flags = GetLittleUInt(); - - Header->Width = GetLittleUInt(); - - Header->Height = GetLittleUInt(); - - Header->PaletteCRC = GetLittleUInt(); - - Header->ImageCRC = GetLittleUInt(); - - Header->PalOffset = GetLittleUInt(); - - Header->TeamEffect0 = GetLittleUInt(); - - Header->TeamEffect1 = GetLittleUInt(); - - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidLif() -{ - LIF_HEAD Head; - - if (!iGetLifHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(LIF_HEAD), IL_SEEK_CUR); - - return iCheckLif(&Head); -} - - -// Internal function used to check if the HEADER is a valid Lif header. -ILboolean iCheckLif(LIF_HEAD *Header) -{ - if (Header->Version != 260 || Header->Flags != 50) - return IL_FALSE; - if (stricmp(Header->Id, "Willy 7")) - return IL_FALSE; - return IL_TRUE; -} - - -//! Reads a .Lif file -ILboolean ilLoadLif(ILconst_string FileName) -{ - ILHANDLE LifFile; - ILboolean bLif = IL_FALSE; - - LifFile = iopenr(FileName); - if (LifFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bLif; - } - - bLif = ilLoadLifF(LifFile); - icloser(LifFile); - - return bLif; -} - - -//! Reads an already-opened .Lif file -ILboolean ilLoadLifF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadLifInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .Lif -ILboolean ilLoadLifL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadLifInternal(); -} - - -ILboolean iLoadLifInternal() -{ - LIF_HEAD LifHead; - ILuint i; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetLifHead(&LifHead)) - return IL_FALSE; - - if (!ilTexImage(LifHead.Width, LifHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(1024); - if (iCurImage->Pal.Palette == NULL) - return IL_FALSE; - iCurImage->Pal.PalSize = 1024; - iCurImage->Pal.PalType = IL_PAL_RGBA32; - - if (iread(iCurImage->Data, LifHead.Width * LifHead.Height, 1) != 1) - return IL_FALSE; - if (iread(iCurImage->Pal.Palette, 1, 1024) != 1024) - return IL_FALSE; - - // Each data offset is offset by -1, so we add one. - for (i = 0; i < iCurImage->SizeOfData; i++) { - iCurImage->Data[i]++; - } - - return ilFixImage(); -} - -#endif//IL_NO_LIF diff --git a/DevIL/src-IL/src/il_lif.cpp b/DevIL/src-IL/src/il_lif.cpp new file mode 100644 index 00000000..456975e6 --- /dev/null +++ b/DevIL/src-IL/src/il_lif.cpp @@ -0,0 +1,198 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_lif.c +// +// Description: Reads a Homeworld image. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_LIF +#include "il_lif.h" + + +//! Checks if the file specified in FileName is a valid Lif file. +ILboolean ilIsValidLif(ILconst_string FileName) +{ + ILHANDLE LifFile; + ILboolean bLif = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("lif"))) { + ilSetError(IL_INVALID_EXTENSION); + return bLif; + } + + LifFile = iopenr(FileName); + if (LifFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bLif; + } + + bLif = ilIsValidLifF(LifFile); + icloser(LifFile); + + return bLif; +} + + +//! Checks if the ILHANDLE contains a valid Lif file at the current position. +ILboolean ilIsValidLifF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidLif(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid Lif lump. +ILboolean ilIsValidLifL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidLif(); +} + + +// Internal function used to get the Lif header from the current file. +ILboolean iGetLifHead(LIF_HEAD *Header) +{ + + iread(Header->Id, 1, 8); + + Header->Version = GetLittleUInt(); + + Header->Flags = GetLittleUInt(); + + Header->Width = GetLittleUInt(); + + Header->Height = GetLittleUInt(); + + Header->PaletteCRC = GetLittleUInt(); + + Header->ImageCRC = GetLittleUInt(); + + Header->PalOffset = GetLittleUInt(); + + Header->TeamEffect0 = GetLittleUInt(); + + Header->TeamEffect1 = GetLittleUInt(); + + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidLif() +{ + LIF_HEAD Head; + + if (!iGetLifHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(LIF_HEAD), IL_SEEK_CUR); + + return iCheckLif(&Head); +} + + +// Internal function used to check if the HEADER is a valid Lif header. +ILboolean iCheckLif(LIF_HEAD *Header) +{ + if (Header->Version != 260 || Header->Flags != 50) + return IL_FALSE; + if (stricmp(Header->Id, "Willy 7")) + return IL_FALSE; + return IL_TRUE; +} + + +//! Reads a .Lif file +ILboolean ilLoadLif(ILconst_string FileName) +{ + ILHANDLE LifFile; + ILboolean bLif = IL_FALSE; + + LifFile = iopenr(FileName); + if (LifFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bLif; + } + + bLif = ilLoadLifF(LifFile); + icloser(LifFile); + + return bLif; +} + + +//! Reads an already-opened .Lif file +ILboolean ilLoadLifF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadLifInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .Lif +ILboolean ilLoadLifL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadLifInternal(); +} + + +ILboolean iLoadLifInternal() +{ + LIF_HEAD LifHead; + ILuint i; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetLifHead(&LifHead)) + return IL_FALSE; + + if (!ilTexImage(LifHead.Width, LifHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(1024); + if (iCurImage->Pal.Palette == NULL) + return IL_FALSE; + iCurImage->Pal.PalSize = 1024; + iCurImage->Pal.PalType = IL_PAL_RGBA32; + + if (iread(iCurImage->Data, LifHead.Width * LifHead.Height, 1) != 1) + return IL_FALSE; + if (iread(iCurImage->Pal.Palette, 1, 1024) != 1024) + return IL_FALSE; + + // Each data offset is offset by -1, so we add one. + for (i = 0; i < iCurImage->SizeOfData; i++) { + iCurImage->Data[i]++; + } + + return ilFixImage(); +} + +#endif//IL_NO_LIF diff --git a/DevIL/src-IL/src/il_main.c b/DevIL/src-IL/src/il_main.c deleted file mode 100644 index ffde2052..00000000 --- a/DevIL/src-IL/src/il_main.c +++ /dev/null @@ -1,30 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2002 by Denton Woods -// Last modified: 02/16/2002 <--Y2K Compliant! =] -// -// Filename: src-IL/src/il_main.c -// -// Description: Startup function -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" - -/* Only needed for MSVC++ unless extended to actually do something =) */ -#if defined(_WIN32) && defined(_MSC_VER) -BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) -{ - hModule; ul_reason_for_call; lpReserved; - - if (ul_reason_for_call == DLL_PROCESS_ATTACH) { - //ilInit(); - } - - return TRUE; -} -#endif - - diff --git a/DevIL/src-IL/src/il_main.cpp b/DevIL/src-IL/src/il_main.cpp new file mode 100644 index 00000000..ffde2052 --- /dev/null +++ b/DevIL/src-IL/src/il_main.cpp @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2002 by Denton Woods +// Last modified: 02/16/2002 <--Y2K Compliant! =] +// +// Filename: src-IL/src/il_main.c +// +// Description: Startup function +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" + +/* Only needed for MSVC++ unless extended to actually do something =) */ +#if defined(_WIN32) && defined(_MSC_VER) +BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + hModule; ul_reason_for_call; lpReserved; + + if (ul_reason_for_call == DLL_PROCESS_ATTACH) { + //ilInit(); + } + + return TRUE; +} +#endif + + diff --git a/DevIL/src-IL/src/il_manip.c b/DevIL/src-IL/src/il_manip.c deleted file mode 100644 index 76985554..00000000 --- a/DevIL/src-IL/src/il_manip.c +++ /dev/null @@ -1,1154 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 01/24/2009 -// -// Filename: src-IL/src/il_manip.c -// -// Description: Image manipulation -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" - -ILfloat /*ILAPIENTRY*/ ilFloatToHalfOverflow() { - ILfloat f = 1e10; - ILint j; - for (j = 0; j < 10; j++) - f *= f; // this will overflow before - // the for loop terminates - return f; -} - -//----------------------------------------------------- -// Float-to-half conversion -- general case, including -// zeroes, denormalized numbers and exponent overflows. -//----------------------------------------------------- -ILushort ILAPIENTRY ilFloatToHalf(ILuint i) { - // - // Our floating point number, f, is represented by the bit - // pattern in integer i. Disassemble that bit pattern into - // the sign, s, the exponent, e, and the significand, m. - // Shift s into the position where it will go in in the - // resulting half number. - // Adjust e, accounting for the different exponent bias - // of float and half (127 versus 15). - // - - register int s = (i >> 16) & 0x00008000; - register int e = ((i >> 23) & 0x000000ff) - (127 - 15); - register int m = i & 0x007fffff; - - // - // Now reassemble s, e and m into a half: - // - - if (e <= 0) - { - if (e < -10) - { - // - // E is less than -10. The absolute value of f is - // less than HALF_MIN (f may be a small normalized - // float, a denormalized float or a zero). - // - // We convert f to a half zero. - // - - return 0; - } - - // - // E is between -10 and 0. F is a normalized float, - // whose magnitude is less than HALF_NRM_MIN. - // - // We convert f to a denormalized half. - // - - m = (m | 0x00800000) >> (1 - e); - - // - // Round to nearest, round "0.5" up. - // - // Rounding may cause the significand to overflow and make - // our number normalized. Because of the way a half's bits - // are laid out, we don't have to treat this case separately; - // the code below will handle it correctly. - // - - if (m & 0x00001000) - m += 0x00002000; - - // - // Assemble the half from s, e (zero) and m. - // - - return s | (m >> 13); - } - else if (e == 0xff - (127 - 15)) - { - if (m == 0) - { - // - // F is an infinity; convert f to a half - // infinity with the same sign as f. - // - - return s | 0x7c00; - } - else - { - // - // F is a NAN; we produce a half NAN that preserves - // the sign bit and the 10 leftmost bits of the - // significand of f, with one exception: If the 10 - // leftmost bits are all zero, the NAN would turn - // into an infinity, so we have to set at least one - // bit in the significand. - // - - m >>= 13; - return s | 0x7c00 | m | (m == 0); - } - } - else - { - // - // E is greater than zero. F is a normalized float. - // We try to convert f to a normalized half. - // - - // - // Round to nearest, round "0.5" up - // - - if (m & 0x00001000) - { - m += 0x00002000; - - if (m & 0x00800000) - { - m = 0; // overflow in significand, - e += 1; // adjust exponent - } - } - - // - // Handle exponent overflow - // - - if (e > 30) - { - ilFloatToHalfOverflow(); // Cause a hardware floating point overflow; - return s | 0x7c00; // if this returns, the half becomes an - } // infinity with the same sign as f. - - // - // Assemble the half from s, e and m. - // - - return s | (e << 10) | (m >> 13); - } -} - -// Taken from OpenEXR -INLINE ILuint ILAPIENTRY ilHalfToFloat (ILushort y) { - - int s = (y >> 15) & 0x00000001; - int e = (y >> 10) & 0x0000001f; - int m = y & 0x000003ff; - - if (e == 0) - { - if (m == 0) - { - // - // Plus or minus zero - // - - return s << 31; - } - else - { - // - // Denormalized number -- renormalize it - // - - while (!(m & 0x00000400)) - { - m <<= 1; - e -= 1; - } - - e += 1; - m &= ~0x00000400; - } - } - else if (e == 31) - { - if (m == 0) - { - // - // Positive or negative infinity - // - - return (s << 31) | 0x7f800000; - } - else - { - // - // Nan -- preserve sign and significand bits - // - - return (s << 31) | 0x7f800000 | (m << 13); - } - } - - // - // Normalized number - // - - e = e + (127 - 15); - m = m << 13; - - // - // Assemble s, e and m. - // - - return (s << 31) | (e << 23) | m; -} - -void ILAPIENTRY iFlipBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num) -{ - ILubyte *StartPtr, *EndPtr; - ILuint y, d; - const ILuint size = line_num * line_size; - - for (d = 0; d < depth; d++) { - StartPtr = buff + d * size; - EndPtr = buff + d * size + size; - - for (y = 0; y < (line_num/2); y++) { - EndPtr -= line_size; - iMemSwap(StartPtr, EndPtr, line_size); - StartPtr += line_size; - } - } -} - -// Just created for internal use. -ILubyte* iFlipNewBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num) -{ - ILubyte *data; - ILubyte *s1, *s2; - ILuint y, d; - const ILuint size = line_num * line_size; - - if ((data = (ILubyte*)ialloc(depth*size)) == NULL) - return IL_FALSE; - - for (d = 0; d < depth; d++) { - s1 = buff + d * size; - s2 = data + d * size+size; - - for (y = 0; y < line_num; y++) { - s2 -= line_size; - memcpy(s2,s1,line_size); - s1 += line_size; - } - } - return data; -} - - -// Flips an image over its x axis -ILboolean ilFlipImage() -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iCurImage->Origin = (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) ? - IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT; - - iFlipBuffer(iCurImage->Data,iCurImage->Depth,iCurImage->Bps,iCurImage->Height); - - return IL_TRUE; -} - -// Just created for internal use. -ILubyte* ILAPIENTRY iGetFlipped(ILimage *img) -{ - if (img == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - return iFlipNewBuffer(img->Data,img->Depth,img->Bps,img->Height); -} - - -//@JASON New routine created 28/03/2001 -//! Mirrors an image over its y axis -ILboolean ILAPIENTRY iMirror() { - ILubyte *Data, *DataPtr, *Temp; - ILuint y, d, PixLine; - ILint x, c; - ILushort *ShortPtr, *TempShort; - ILuint *IntPtr, *TempInt; - ILdouble *DblPtr, *TempDbl; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Data = (ILubyte*)ialloc(iCurImage->SizeOfData); - if (Data == NULL) - return IL_FALSE; - - PixLine = iCurImage->Bps / iCurImage->Bpc; - switch (iCurImage->Bpc) - { - case 1: - Temp = iCurImage->Data; - for (d = 0; d < iCurImage->Depth; d++) { - DataPtr = Data + d * iCurImage->SizeOfPlane; - for (y = 0; y < iCurImage->Height; y++) { - for (x = iCurImage->Width - 1; x >= 0; x--) { - for (c = 0; c < iCurImage->Bpp; c++, Temp++) { - DataPtr[y * PixLine + x * iCurImage->Bpp + c] = *Temp; - } - } - } - } - break; - - case 2: - TempShort = (ILushort*)iCurImage->Data; - for (d = 0; d < iCurImage->Depth; d++) { - ShortPtr = (ILushort*)(Data + d * iCurImage->SizeOfPlane); - for (y = 0; y < iCurImage->Height; y++) { - for (x = iCurImage->Width - 1; x >= 0; x--) { - for (c = 0; c < iCurImage->Bpp; c++, TempShort++) { - ShortPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempShort; - } - } - } - } - break; - - case 4: - TempInt = (ILuint*)iCurImage->Data; - for (d = 0; d < iCurImage->Depth; d++) { - IntPtr = (ILuint*)(Data + d * iCurImage->SizeOfPlane); - for (y = 0; y < iCurImage->Height; y++) { - for (x = iCurImage->Width - 1; x >= 0; x--) { - for (c = 0; c < iCurImage->Bpp; c++, TempInt++) { - IntPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempInt; - } - } - } - } - break; - - case 8: - TempDbl = (ILdouble*)iCurImage->Data; - for (d = 0; d < iCurImage->Depth; d++) { - DblPtr = (ILdouble*)(Data + d * iCurImage->SizeOfPlane); - for (y = 0; y < iCurImage->Height; y++) { - for (x = iCurImage->Width - 1; x >= 0; x--) { - for (c = 0; c < iCurImage->Bpp; c++, TempDbl++) { - DblPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempDbl; - } - } - } - } - break; - } - - ifree(iCurImage->Data); - iCurImage->Data = Data; - - return IL_TRUE; -} - - -// Should we add type to the parameter list? -// Copies a 1d block of pixels to the buffer pointed to by Data. -ILboolean ilCopyPixels1D(ILuint XOff, ILuint Width, void *Data) -{ - ILuint x, c, NewBps, NewOff, PixBpp; - ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - TempData = iGetFlipped(iCurImage); - if (TempData == NULL) - return IL_FALSE; - } - } - - PixBpp = iCurImage->Bpp * iCurImage->Bpc; - - if (iCurImage->Width < XOff + Width) { - NewBps = (iCurImage->Width - XOff) * PixBpp; - } - else { - NewBps = Width * PixBpp; - } - NewOff = XOff * PixBpp; - - for (x = 0; x < NewBps; x += PixBpp) { - for (c = 0; c < PixBpp; c++) { - Temp[x + c] = TempData[(x + NewOff) + c]; - } - } - - if (TempData != iCurImage->Data) - ifree(TempData); - - return IL_TRUE; -} - - -// Copies a 2d block of pixels to the buffer pointed to by Data. -ILboolean ilCopyPixels2D(ILuint XOff, ILuint YOff, ILuint Width, ILuint Height, void *Data) -{ - ILuint x, y, c, NewBps, DataBps, NewXOff, NewHeight, PixBpp; - ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - TempData = iGetFlipped(iCurImage); - if (TempData == NULL) - return IL_FALSE; - } - } - - PixBpp = iCurImage->Bpp * iCurImage->Bpc; - - if (iCurImage->Width < XOff + Width) - NewBps = (iCurImage->Width - XOff) * PixBpp; - else - NewBps = Width * PixBpp; - - if (iCurImage->Height < YOff + Height) - NewHeight = iCurImage->Height - YOff; - else - NewHeight = Height; - - DataBps = Width * PixBpp; - NewXOff = XOff * PixBpp; - - for (y = 0; y < NewHeight; y++) { - for (x = 0; x < NewBps; x += PixBpp) { - for (c = 0; c < PixBpp; c++) { - Temp[y * DataBps + x + c] = - TempData[(y + YOff) * iCurImage->Bps + x + NewXOff + c]; - } - } - } - - if (TempData != iCurImage->Data) - ifree(TempData); - - return IL_TRUE; -} - - -// Copies a 3d block of pixels to the buffer pointed to by Data. -ILboolean ilCopyPixels3D(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, void *Data) -{ - ILuint x, y, z, c, NewBps, DataBps, NewSizePlane, NewH, NewD, NewXOff, PixBpp; - ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - TempData = iGetFlipped(iCurImage); - if (TempData == NULL) - return IL_FALSE; - } - } - - PixBpp = iCurImage->Bpp * iCurImage->Bpc; - - if (iCurImage->Width < XOff + Width) - NewBps = (iCurImage->Width - XOff) * PixBpp; - else - NewBps = Width * PixBpp; - - if (iCurImage->Height < YOff + Height) - NewH = iCurImage->Height - YOff; - else - NewH = Height; - - if (iCurImage->Depth < ZOff + Depth) - NewD = iCurImage->Depth - ZOff; - else - NewD = Depth; - - DataBps = Width * PixBpp; - NewSizePlane = NewBps * NewH; - - NewXOff = XOff * PixBpp; - - for (z = 0; z < NewD; z++) { - for (y = 0; y < NewH; y++) { - for (x = 0; x < NewBps; x += PixBpp) { - for (c = 0; c < PixBpp; c++) { - Temp[z * NewSizePlane + y * DataBps + x + c] = - TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + x + NewXOff + c]; - //TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * iCurImage->Bpp + c]; - } - } - } - } - - if (TempData != iCurImage->Data) - ifree(TempData); - - return IL_TRUE; -} - - -ILuint ILAPIENTRY ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data) -{ - void *Converted = NULL; - ILubyte *TempBuff = NULL; - ILuint SrcSize, DestSize; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return 0; - } - DestSize = Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type); - if (DestSize == 0) { - return DestSize; - } - if (Data == NULL || Format == IL_COLOUR_INDEX) { - ilSetError(IL_INVALID_PARAM); - return 0; - } - SrcSize = Width * Height * Depth * iCurImage->Bpp * iCurImage->Bpc; - - if (Format == iCurImage->Format && Type == iCurImage->Type) { - TempBuff = (ILubyte*)Data; - } - else { - TempBuff = (ILubyte*)ialloc(SrcSize); - if (TempBuff == NULL) { - return 0; - } - } - - if (YOff + Height <= 1) { - if (!ilCopyPixels1D(XOff, Width, TempBuff)) { - goto failed; - } - } - else if (ZOff + Depth <= 1) { - if (!ilCopyPixels2D(XOff, YOff, Width, Height, TempBuff)) { - goto failed; - } - } - else { - if (!ilCopyPixels3D(XOff, YOff, ZOff, Width, Height, Depth, TempBuff)) { - goto failed; - } - } - - if (Format == iCurImage->Format && Type == iCurImage->Type) { - return DestSize; - } - - Converted = ilConvertBuffer(SrcSize, iCurImage->Format, Format, iCurImage->Type, Type, &iCurImage->Pal, TempBuff); - if (Converted == NULL) - goto failed; - - memcpy(Data, Converted, DestSize); - - ifree(Converted); - if (TempBuff != Data) - ifree(TempBuff); - - return DestSize; - -failed: - if (TempBuff != Data) - ifree(TempBuff); - ifree(Converted); - return 0; -} - - -ILboolean ilSetPixels1D(ILint XOff, ILuint Width, void *Data) -{ - ILuint c, SkipX = 0, PixBpp; - ILint x, NewWidth; - ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - TempData = iGetFlipped(iCurImage); - if (TempData == NULL) - return IL_FALSE; - } - } - - PixBpp = iCurImage->Bpp * iCurImage->Bpc; - - if (XOff < 0) { - SkipX = abs(XOff); - XOff = 0; - } - - if (iCurImage->Width < XOff + Width) { - NewWidth = iCurImage->Width - XOff; - } - else { - NewWidth = Width; - } - - NewWidth -= SkipX; - - for (x = 0; x < NewWidth; x++) { - for (c = 0; c < PixBpp; c++) { - TempData[(x + XOff) * PixBpp + c] = Temp[(x + SkipX) * PixBpp + c]; - } - } - - if (TempData != iCurImage->Data) { - ifree(iCurImage->Data); - iCurImage->Data = TempData; - } - - return IL_TRUE; -} - - -ILboolean ilSetPixels2D(ILint XOff, ILint YOff, ILuint Width, ILuint Height, void *Data) -{ - ILuint c, SkipX = 0, SkipY = 0, NewBps, PixBpp; - ILint x, y, NewWidth, NewHeight; - ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - TempData = iGetFlipped(iCurImage); - if (TempData == NULL) - return IL_FALSE; - } - } - - PixBpp = iCurImage->Bpp * iCurImage->Bpc; - - if (XOff < 0) { - SkipX = abs(XOff); - XOff = 0; - } - if (YOff < 0) { - SkipY = abs(YOff); - YOff = 0; - } - - if (iCurImage->Width < XOff + Width) - NewWidth = iCurImage->Width - XOff; - else - NewWidth = Width; - NewBps = Width * PixBpp; - - if (iCurImage->Height < YOff + Height) - NewHeight = iCurImage->Height - YOff; - else - NewHeight = Height; - - NewWidth -= SkipX; - NewHeight -= SkipY; - - for (y = 0; y < NewHeight; y++) { - for (x = 0; x < NewWidth; x++) { - for (c = 0; c < PixBpp; c++) { - TempData[(y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] = - Temp[(y + SkipY) * NewBps + (x + SkipX) * PixBpp + c]; - } - } - } - - if (TempData != iCurImage->Data) { - ifree(iCurImage->Data); - iCurImage->Data = TempData; - } - - return IL_TRUE; -} - - -ILboolean ilSetPixels3D(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, void *Data) -{ - ILuint SkipX = 0, SkipY = 0, SkipZ = 0, c, NewBps, NewSizePlane, PixBpp; - ILint x, y, z, NewW, NewH, NewD; - ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { - TempData = iGetFlipped(iCurImage); - if (TempData == NULL) - return IL_FALSE; - } - } - - PixBpp = iCurImage->Bpp * iCurImage->Bpc; - - if (XOff < 0) { - SkipX = abs(XOff); - XOff = 0; - } - if (YOff < 0) { - SkipY = abs(YOff); - YOff = 0; - } - if (ZOff < 0) { - SkipZ = abs(ZOff); - ZOff = 0; - } - - if (iCurImage->Width < XOff + Width) - NewW = iCurImage->Width - XOff; - else - NewW = Width; - NewBps = Width * PixBpp; - - if (iCurImage->Height < YOff + Height) - NewH = iCurImage->Height - YOff; - else - NewH = Height; - - if (iCurImage->Depth < ZOff + Depth) - NewD = iCurImage->Depth - ZOff; - else - NewD = Depth; - NewSizePlane = NewBps * Height; - - NewW -= SkipX; - NewH -= SkipY; - NewD -= SkipZ; - - for (z = 0; z < NewD; z++) { - for (y = 0; y < NewH; y++) { - for (x = 0; x < NewW; x++) { - for (c = 0; c < PixBpp; c++) { - TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] = - Temp[(z + SkipZ) * NewSizePlane + (y + SkipY) * NewBps + (x + SkipX) * PixBpp + c]; - } - } - } - } - - if (TempData != iCurImage->Data) { - ifree(iCurImage->Data); - iCurImage->Data = TempData; - } - - return IL_TRUE; -} - - -void ILAPIENTRY ilSetPixels(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data) -{ - void *Converted; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return; - } - if (Data == NULL) { - ilSetError(IL_INVALID_PARAM); - return; - } - - if (Format == iCurImage->Format && Type == iCurImage->Type) { - Converted = (void*)Data; - } - else { - Converted = ilConvertBuffer(Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type), Format, iCurImage->Format, Type, iCurImage->Type, NULL, Data); - if (!Converted) - return; - } - - if (YOff + Height <= 1) { - ilSetPixels1D(XOff, Width, Converted); - } - else if (ZOff + Depth <= 1) { - ilSetPixels2D(XOff, YOff, Width, Height, Converted); - } - else { - ilSetPixels3D(XOff, YOff, ZOff, Width, Height, Depth, Converted); - } - - if (Format == iCurImage->Format && Type == iCurImage->Type) { - return; - } - - if (Converted != Data) - ifree(Converted); - - return; -} - - - -// Ripped from Platinum (Denton's sources) -// This could very well easily be changed to a 128x128 image instead...needed? - -//! Creates an ugly 64x64 black and yellow checkerboard image. -ILboolean ILAPIENTRY ilDefaultImage() -{ - ILubyte *TempData; - ILubyte Yellow[3] = { 18, 246, 243 }; - ILubyte Black[3] = { 0, 0, 0 }; - ILubyte *ColorPtr = Yellow; // The start color - ILboolean Color = IL_TRUE; - - // Loop Variables - ILint v, w, x, y; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!ilTexImage(64, 64, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - TempData = iCurImage->Data; - - for (v = 0; v < 8; v++) { - // We do this because after a "block" line ends, the next row of blocks - // above starts with the ending colour, but the very inner loop switches them. - if (Color) { - Color = IL_FALSE; - ColorPtr = Black; - } - else { - Color = IL_TRUE; - ColorPtr = Yellow; - } - - for (w = 0; w < 8; w++) { - for (x = 0; x < 8; x++) { - for (y = 0; y < 8; y++, TempData += iCurImage->Bpp) { - TempData[0] = ColorPtr[0]; - TempData[1] = ColorPtr[1]; - TempData[2] = ColorPtr[2]; - } - - // Switch to alternate between black and yellow - if (Color) { - Color = IL_FALSE; - ColorPtr = Black; - } - else { - Color = IL_TRUE; - ColorPtr = Yellow; - } - } - } - } - - return IL_TRUE; -} - - -ILubyte* ILAPIENTRY ilGetAlpha(ILenum Type) -{ - ILimage *TempImage; - ILubyte *Alpha; - ILushort *AlphaShort; - ILuint *AlphaInt; - ILdouble *AlphaDbl; - ILuint i, j, Bpc, Size, AlphaOff; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Bpc = ilGetBpcType(Type); - if (Bpc == 0) { - ilSetError(IL_INVALID_PARAM); - return NULL; - } - - if (iCurImage->Type == Type) { - TempImage = iCurImage; - } else { - TempImage = iConvertImage(iCurImage, iCurImage->Format, Type); - if (TempImage == NULL) - return NULL; - } - - Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * TempImage->Bpp; - Alpha = (ILubyte*)ialloc(Size / TempImage->Bpp * Bpc); - if (Alpha == NULL) { - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return NULL; - } - - switch (TempImage->Format) - { - case IL_RGB: - case IL_BGR: - case IL_LUMINANCE: - case IL_COLOUR_INDEX: // @TODO: Make IL_COLOUR_INDEX separate. - memset(Alpha, 0xFF, Size / TempImage->Bpp * Bpc); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return Alpha; - } - - // If our format is alpha, just return a copy. - if (TempImage->Format == IL_ALPHA) { - memcpy(Alpha, TempImage->Data, TempImage->SizeOfData); - return Alpha; - } - - if (TempImage->Format == IL_LUMINANCE_ALPHA) - AlphaOff = 2; - else - AlphaOff = 4; - - switch (TempImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - Alpha[j] = TempImage->Data[i]; - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - AlphaShort = (ILushort*)Alpha; - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - AlphaShort[j] = ((ILushort*)TempImage->Data)[i]; - break; - - case IL_INT: - case IL_UNSIGNED_INT: - case IL_FLOAT: // Can throw float in here, because it's the same size. - AlphaInt = (ILuint*)Alpha; - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - AlphaInt[j] = ((ILuint*)TempImage->Data)[i]; - break; - - case IL_DOUBLE: - AlphaDbl = (ILdouble*)Alpha; - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - AlphaDbl[j] = ((ILdouble*)TempImage->Data)[i]; - break; - } - - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return Alpha; -} - -// sets the Alpha value to a specific value for each pixel in the image -ILboolean ILAPIENTRY ilSetAlpha(ILdouble AlphaValue) -{ - ILboolean ret = IL_TRUE; - ILuint i,Size; - ILimage *Image = iCurImage; - ILuint AlphaOff; - - if (Image == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - AlphaValue = IL_CLAMP(AlphaValue); - - switch (Image->Format) - { - case IL_RGB: - ret = ilConvertImage(IL_RGBA, Image->Type); - case IL_RGBA: - AlphaOff = 4; - break; - case IL_BGR: - ret = ilConvertImage(IL_BGRA, Image->Type); - case IL_BGRA: - AlphaOff = 4; - break; - case IL_LUMINANCE: - ret = ilConvertImage(IL_LUMINANCE_ALPHA, Image->Type); - case IL_LUMINANCE_ALPHA: - AlphaOff = 2; - break; - case IL_ALPHA: - AlphaOff = 1; - case IL_COLOUR_INDEX: //@TODO use palette with alpha - ret = ilConvertImage(IL_RGBA, Image->Type); - AlphaOff = 4; - break; - } - if (ret == IL_FALSE) { - // Error has been set by ilConvertImage. - return IL_FALSE; - } - Size = Image->Width * Image->Height * Image->Depth * Image->Bpp; - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: { - const ILbyte alpha = (ILubyte)(AlphaValue * IL_MAX_UNSIGNED_BYTE + .5); - for (i = AlphaOff-1; i < Size; i += AlphaOff) - Image->Data[i] = alpha; - break; - } - case IL_SHORT: - case IL_UNSIGNED_SHORT: { - const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_SHORT + .5); - for (i = AlphaOff-1; i < Size; i += AlphaOff) - ((ILushort*)Image->Data)[i] = alpha; - break; - } - case IL_INT: - case IL_UNSIGNED_INT: { - const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_INT + .5); - for (i = AlphaOff-1; i < Size; i += AlphaOff) - ((ILuint*)Image->Data)[i] = alpha; - break; - } - case IL_FLOAT: { - const ILfloat alpha = (ILfloat)AlphaValue; - for (i = AlphaOff-1; i < Size; i += AlphaOff) - ((ILfloat*)Image->Data)[i] = alpha; - break; - } - case IL_DOUBLE: { - const ILdouble alpha = AlphaValue; - for (i = AlphaOff-1; i < Size; i += AlphaOff) - ((ILdouble*)Image->Data)[i] = alpha; - break; - } - } - - return IL_TRUE; -} - -void ILAPIENTRY ilModAlpha(ILdouble AlphaValue) -{ - ILuint AlphaOff = 0; - ILboolean ret = IL_FALSE; - ILuint i,j,Size; - - union { - ILubyte alpha_byte; - ILushort alpha_short; - ILuint alpha_int; - ILfloat alpha_float; - ILdouble alpha_double; - } Alpha; - - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return; - } - - switch (iCurImage->Format) - { - case IL_RGB: - ret = ilConvertImage(IL_RGBA,iCurImage->Type); - AlphaOff = 4; - break; - case IL_BGR: - ret = ilConvertImage(IL_BGRA,iCurImage->Type); - AlphaOff = 4; - break; - case IL_LUMINANCE: - ret = ilConvertImage(IL_LUMINANCE_ALPHA,iCurImage->Type); - AlphaOff = 2; - break; - case IL_COLOUR_INDEX: - ret = ilConvertImage(IL_RGBA,iCurImage->Type); - AlphaOff = 4; - break; - } - Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * iCurImage->Bpp; - - if (!ret) - return; - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - Alpha.alpha_byte = (ILubyte)(AlphaValue * 0x000000FF + .5); - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - iCurImage->Data[i] = Alpha.alpha_byte; - break; - case IL_SHORT: - case IL_UNSIGNED_SHORT: - Alpha.alpha_short = (ILushort)(AlphaValue * 0x0000FFFF + .5); - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - ((ILushort*)iCurImage->Data)[i] = Alpha.alpha_short; - break; - case IL_INT: - case IL_UNSIGNED_INT: - Alpha.alpha_int = (ILuint)(AlphaValue * 0xFFFFFFFF + .5); - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - ((ILuint*)iCurImage->Data)[i] = Alpha.alpha_int; - break; - case IL_FLOAT: - Alpha.alpha_float = (ILfloat)AlphaValue; - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - ((ILfloat*)iCurImage->Data)[i] = Alpha.alpha_float; - break; - case IL_DOUBLE: - Alpha.alpha_double = AlphaValue; - for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) - ((ILdouble*)iCurImage->Data)[i] = Alpha.alpha_double; - break; - } - - return; -} - - -//! Clamps data values of unsigned bytes from 16 to 235 for display on an -// NTSC television. Reasoning for this is given at -// http://msdn.microsoft.com/en-us/library/bb174608.aspx. -ILboolean ILAPIENTRY ilClampNTSC(void) -{ - ILuint x, y, z, c; - ILuint Offset = 0; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (iCurImage->Type != IL_UNSIGNED_BYTE) // Should we set an error here? - return IL_FALSE; - - for (z = 0; z < iCurImage->Depth; z++) { - for (y = 0; y < iCurImage->Height; y++) { - for (x = 0; x < iCurImage->Width; x++) { - for (c = 0; c < iCurImage->Bpp; c++) { - iCurImage->Data[Offset + c] = IL_LIMIT(iCurImage->Data[Offset + c], 16, 235); - } - Offset += iCurImage->Bpp; - } - } - } - - return IL_TRUE; -} diff --git a/DevIL/src-IL/src/il_manip.cpp b/DevIL/src-IL/src/il_manip.cpp new file mode 100644 index 00000000..76985554 --- /dev/null +++ b/DevIL/src-IL/src/il_manip.cpp @@ -0,0 +1,1154 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 01/24/2009 +// +// Filename: src-IL/src/il_manip.c +// +// Description: Image manipulation +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" + +ILfloat /*ILAPIENTRY*/ ilFloatToHalfOverflow() { + ILfloat f = 1e10; + ILint j; + for (j = 0; j < 10; j++) + f *= f; // this will overflow before + // the for loop terminates + return f; +} + +//----------------------------------------------------- +// Float-to-half conversion -- general case, including +// zeroes, denormalized numbers and exponent overflows. +//----------------------------------------------------- +ILushort ILAPIENTRY ilFloatToHalf(ILuint i) { + // + // Our floating point number, f, is represented by the bit + // pattern in integer i. Disassemble that bit pattern into + // the sign, s, the exponent, e, and the significand, m. + // Shift s into the position where it will go in in the + // resulting half number. + // Adjust e, accounting for the different exponent bias + // of float and half (127 versus 15). + // + + register int s = (i >> 16) & 0x00008000; + register int e = ((i >> 23) & 0x000000ff) - (127 - 15); + register int m = i & 0x007fffff; + + // + // Now reassemble s, e and m into a half: + // + + if (e <= 0) + { + if (e < -10) + { + // + // E is less than -10. The absolute value of f is + // less than HALF_MIN (f may be a small normalized + // float, a denormalized float or a zero). + // + // We convert f to a half zero. + // + + return 0; + } + + // + // E is between -10 and 0. F is a normalized float, + // whose magnitude is less than HALF_NRM_MIN. + // + // We convert f to a denormalized half. + // + + m = (m | 0x00800000) >> (1 - e); + + // + // Round to nearest, round "0.5" up. + // + // Rounding may cause the significand to overflow and make + // our number normalized. Because of the way a half's bits + // are laid out, we don't have to treat this case separately; + // the code below will handle it correctly. + // + + if (m & 0x00001000) + m += 0x00002000; + + // + // Assemble the half from s, e (zero) and m. + // + + return s | (m >> 13); + } + else if (e == 0xff - (127 - 15)) + { + if (m == 0) + { + // + // F is an infinity; convert f to a half + // infinity with the same sign as f. + // + + return s | 0x7c00; + } + else + { + // + // F is a NAN; we produce a half NAN that preserves + // the sign bit and the 10 leftmost bits of the + // significand of f, with one exception: If the 10 + // leftmost bits are all zero, the NAN would turn + // into an infinity, so we have to set at least one + // bit in the significand. + // + + m >>= 13; + return s | 0x7c00 | m | (m == 0); + } + } + else + { + // + // E is greater than zero. F is a normalized float. + // We try to convert f to a normalized half. + // + + // + // Round to nearest, round "0.5" up + // + + if (m & 0x00001000) + { + m += 0x00002000; + + if (m & 0x00800000) + { + m = 0; // overflow in significand, + e += 1; // adjust exponent + } + } + + // + // Handle exponent overflow + // + + if (e > 30) + { + ilFloatToHalfOverflow(); // Cause a hardware floating point overflow; + return s | 0x7c00; // if this returns, the half becomes an + } // infinity with the same sign as f. + + // + // Assemble the half from s, e and m. + // + + return s | (e << 10) | (m >> 13); + } +} + +// Taken from OpenEXR +INLINE ILuint ILAPIENTRY ilHalfToFloat (ILushort y) { + + int s = (y >> 15) & 0x00000001; + int e = (y >> 10) & 0x0000001f; + int m = y & 0x000003ff; + + if (e == 0) + { + if (m == 0) + { + // + // Plus or minus zero + // + + return s << 31; + } + else + { + // + // Denormalized number -- renormalize it + // + + while (!(m & 0x00000400)) + { + m <<= 1; + e -= 1; + } + + e += 1; + m &= ~0x00000400; + } + } + else if (e == 31) + { + if (m == 0) + { + // + // Positive or negative infinity + // + + return (s << 31) | 0x7f800000; + } + else + { + // + // Nan -- preserve sign and significand bits + // + + return (s << 31) | 0x7f800000 | (m << 13); + } + } + + // + // Normalized number + // + + e = e + (127 - 15); + m = m << 13; + + // + // Assemble s, e and m. + // + + return (s << 31) | (e << 23) | m; +} + +void ILAPIENTRY iFlipBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num) +{ + ILubyte *StartPtr, *EndPtr; + ILuint y, d; + const ILuint size = line_num * line_size; + + for (d = 0; d < depth; d++) { + StartPtr = buff + d * size; + EndPtr = buff + d * size + size; + + for (y = 0; y < (line_num/2); y++) { + EndPtr -= line_size; + iMemSwap(StartPtr, EndPtr, line_size); + StartPtr += line_size; + } + } +} + +// Just created for internal use. +ILubyte* iFlipNewBuffer(ILubyte *buff, ILuint depth, ILuint line_size, ILuint line_num) +{ + ILubyte *data; + ILubyte *s1, *s2; + ILuint y, d; + const ILuint size = line_num * line_size; + + if ((data = (ILubyte*)ialloc(depth*size)) == NULL) + return IL_FALSE; + + for (d = 0; d < depth; d++) { + s1 = buff + d * size; + s2 = data + d * size+size; + + for (y = 0; y < line_num; y++) { + s2 -= line_size; + memcpy(s2,s1,line_size); + s1 += line_size; + } + } + return data; +} + + +// Flips an image over its x axis +ILboolean ilFlipImage() +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iCurImage->Origin = (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT) ? + IL_ORIGIN_UPPER_LEFT : IL_ORIGIN_LOWER_LEFT; + + iFlipBuffer(iCurImage->Data,iCurImage->Depth,iCurImage->Bps,iCurImage->Height); + + return IL_TRUE; +} + +// Just created for internal use. +ILubyte* ILAPIENTRY iGetFlipped(ILimage *img) +{ + if (img == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + return iFlipNewBuffer(img->Data,img->Depth,img->Bps,img->Height); +} + + +//@JASON New routine created 28/03/2001 +//! Mirrors an image over its y axis +ILboolean ILAPIENTRY iMirror() { + ILubyte *Data, *DataPtr, *Temp; + ILuint y, d, PixLine; + ILint x, c; + ILushort *ShortPtr, *TempShort; + ILuint *IntPtr, *TempInt; + ILdouble *DblPtr, *TempDbl; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Data = (ILubyte*)ialloc(iCurImage->SizeOfData); + if (Data == NULL) + return IL_FALSE; + + PixLine = iCurImage->Bps / iCurImage->Bpc; + switch (iCurImage->Bpc) + { + case 1: + Temp = iCurImage->Data; + for (d = 0; d < iCurImage->Depth; d++) { + DataPtr = Data + d * iCurImage->SizeOfPlane; + for (y = 0; y < iCurImage->Height; y++) { + for (x = iCurImage->Width - 1; x >= 0; x--) { + for (c = 0; c < iCurImage->Bpp; c++, Temp++) { + DataPtr[y * PixLine + x * iCurImage->Bpp + c] = *Temp; + } + } + } + } + break; + + case 2: + TempShort = (ILushort*)iCurImage->Data; + for (d = 0; d < iCurImage->Depth; d++) { + ShortPtr = (ILushort*)(Data + d * iCurImage->SizeOfPlane); + for (y = 0; y < iCurImage->Height; y++) { + for (x = iCurImage->Width - 1; x >= 0; x--) { + for (c = 0; c < iCurImage->Bpp; c++, TempShort++) { + ShortPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempShort; + } + } + } + } + break; + + case 4: + TempInt = (ILuint*)iCurImage->Data; + for (d = 0; d < iCurImage->Depth; d++) { + IntPtr = (ILuint*)(Data + d * iCurImage->SizeOfPlane); + for (y = 0; y < iCurImage->Height; y++) { + for (x = iCurImage->Width - 1; x >= 0; x--) { + for (c = 0; c < iCurImage->Bpp; c++, TempInt++) { + IntPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempInt; + } + } + } + } + break; + + case 8: + TempDbl = (ILdouble*)iCurImage->Data; + for (d = 0; d < iCurImage->Depth; d++) { + DblPtr = (ILdouble*)(Data + d * iCurImage->SizeOfPlane); + for (y = 0; y < iCurImage->Height; y++) { + for (x = iCurImage->Width - 1; x >= 0; x--) { + for (c = 0; c < iCurImage->Bpp; c++, TempDbl++) { + DblPtr[y * PixLine + x * iCurImage->Bpp + c] = *TempDbl; + } + } + } + } + break; + } + + ifree(iCurImage->Data); + iCurImage->Data = Data; + + return IL_TRUE; +} + + +// Should we add type to the parameter list? +// Copies a 1d block of pixels to the buffer pointed to by Data. +ILboolean ilCopyPixels1D(ILuint XOff, ILuint Width, void *Data) +{ + ILuint x, c, NewBps, NewOff, PixBpp; + ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + TempData = iGetFlipped(iCurImage); + if (TempData == NULL) + return IL_FALSE; + } + } + + PixBpp = iCurImage->Bpp * iCurImage->Bpc; + + if (iCurImage->Width < XOff + Width) { + NewBps = (iCurImage->Width - XOff) * PixBpp; + } + else { + NewBps = Width * PixBpp; + } + NewOff = XOff * PixBpp; + + for (x = 0; x < NewBps; x += PixBpp) { + for (c = 0; c < PixBpp; c++) { + Temp[x + c] = TempData[(x + NewOff) + c]; + } + } + + if (TempData != iCurImage->Data) + ifree(TempData); + + return IL_TRUE; +} + + +// Copies a 2d block of pixels to the buffer pointed to by Data. +ILboolean ilCopyPixels2D(ILuint XOff, ILuint YOff, ILuint Width, ILuint Height, void *Data) +{ + ILuint x, y, c, NewBps, DataBps, NewXOff, NewHeight, PixBpp; + ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + TempData = iGetFlipped(iCurImage); + if (TempData == NULL) + return IL_FALSE; + } + } + + PixBpp = iCurImage->Bpp * iCurImage->Bpc; + + if (iCurImage->Width < XOff + Width) + NewBps = (iCurImage->Width - XOff) * PixBpp; + else + NewBps = Width * PixBpp; + + if (iCurImage->Height < YOff + Height) + NewHeight = iCurImage->Height - YOff; + else + NewHeight = Height; + + DataBps = Width * PixBpp; + NewXOff = XOff * PixBpp; + + for (y = 0; y < NewHeight; y++) { + for (x = 0; x < NewBps; x += PixBpp) { + for (c = 0; c < PixBpp; c++) { + Temp[y * DataBps + x + c] = + TempData[(y + YOff) * iCurImage->Bps + x + NewXOff + c]; + } + } + } + + if (TempData != iCurImage->Data) + ifree(TempData); + + return IL_TRUE; +} + + +// Copies a 3d block of pixels to the buffer pointed to by Data. +ILboolean ilCopyPixels3D(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, void *Data) +{ + ILuint x, y, z, c, NewBps, DataBps, NewSizePlane, NewH, NewD, NewXOff, PixBpp; + ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + TempData = iGetFlipped(iCurImage); + if (TempData == NULL) + return IL_FALSE; + } + } + + PixBpp = iCurImage->Bpp * iCurImage->Bpc; + + if (iCurImage->Width < XOff + Width) + NewBps = (iCurImage->Width - XOff) * PixBpp; + else + NewBps = Width * PixBpp; + + if (iCurImage->Height < YOff + Height) + NewH = iCurImage->Height - YOff; + else + NewH = Height; + + if (iCurImage->Depth < ZOff + Depth) + NewD = iCurImage->Depth - ZOff; + else + NewD = Depth; + + DataBps = Width * PixBpp; + NewSizePlane = NewBps * NewH; + + NewXOff = XOff * PixBpp; + + for (z = 0; z < NewD; z++) { + for (y = 0; y < NewH; y++) { + for (x = 0; x < NewBps; x += PixBpp) { + for (c = 0; c < PixBpp; c++) { + Temp[z * NewSizePlane + y * DataBps + x + c] = + TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + x + NewXOff + c]; + //TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * iCurImage->Bpp + c]; + } + } + } + } + + if (TempData != iCurImage->Data) + ifree(TempData); + + return IL_TRUE; +} + + +ILuint ILAPIENTRY ilCopyPixels(ILuint XOff, ILuint YOff, ILuint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data) +{ + void *Converted = NULL; + ILubyte *TempBuff = NULL; + ILuint SrcSize, DestSize; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return 0; + } + DestSize = Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type); + if (DestSize == 0) { + return DestSize; + } + if (Data == NULL || Format == IL_COLOUR_INDEX) { + ilSetError(IL_INVALID_PARAM); + return 0; + } + SrcSize = Width * Height * Depth * iCurImage->Bpp * iCurImage->Bpc; + + if (Format == iCurImage->Format && Type == iCurImage->Type) { + TempBuff = (ILubyte*)Data; + } + else { + TempBuff = (ILubyte*)ialloc(SrcSize); + if (TempBuff == NULL) { + return 0; + } + } + + if (YOff + Height <= 1) { + if (!ilCopyPixels1D(XOff, Width, TempBuff)) { + goto failed; + } + } + else if (ZOff + Depth <= 1) { + if (!ilCopyPixels2D(XOff, YOff, Width, Height, TempBuff)) { + goto failed; + } + } + else { + if (!ilCopyPixels3D(XOff, YOff, ZOff, Width, Height, Depth, TempBuff)) { + goto failed; + } + } + + if (Format == iCurImage->Format && Type == iCurImage->Type) { + return DestSize; + } + + Converted = ilConvertBuffer(SrcSize, iCurImage->Format, Format, iCurImage->Type, Type, &iCurImage->Pal, TempBuff); + if (Converted == NULL) + goto failed; + + memcpy(Data, Converted, DestSize); + + ifree(Converted); + if (TempBuff != Data) + ifree(TempBuff); + + return DestSize; + +failed: + if (TempBuff != Data) + ifree(TempBuff); + ifree(Converted); + return 0; +} + + +ILboolean ilSetPixels1D(ILint XOff, ILuint Width, void *Data) +{ + ILuint c, SkipX = 0, PixBpp; + ILint x, NewWidth; + ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + TempData = iGetFlipped(iCurImage); + if (TempData == NULL) + return IL_FALSE; + } + } + + PixBpp = iCurImage->Bpp * iCurImage->Bpc; + + if (XOff < 0) { + SkipX = abs(XOff); + XOff = 0; + } + + if (iCurImage->Width < XOff + Width) { + NewWidth = iCurImage->Width - XOff; + } + else { + NewWidth = Width; + } + + NewWidth -= SkipX; + + for (x = 0; x < NewWidth; x++) { + for (c = 0; c < PixBpp; c++) { + TempData[(x + XOff) * PixBpp + c] = Temp[(x + SkipX) * PixBpp + c]; + } + } + + if (TempData != iCurImage->Data) { + ifree(iCurImage->Data); + iCurImage->Data = TempData; + } + + return IL_TRUE; +} + + +ILboolean ilSetPixels2D(ILint XOff, ILint YOff, ILuint Width, ILuint Height, void *Data) +{ + ILuint c, SkipX = 0, SkipY = 0, NewBps, PixBpp; + ILint x, y, NewWidth, NewHeight; + ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + TempData = iGetFlipped(iCurImage); + if (TempData == NULL) + return IL_FALSE; + } + } + + PixBpp = iCurImage->Bpp * iCurImage->Bpc; + + if (XOff < 0) { + SkipX = abs(XOff); + XOff = 0; + } + if (YOff < 0) { + SkipY = abs(YOff); + YOff = 0; + } + + if (iCurImage->Width < XOff + Width) + NewWidth = iCurImage->Width - XOff; + else + NewWidth = Width; + NewBps = Width * PixBpp; + + if (iCurImage->Height < YOff + Height) + NewHeight = iCurImage->Height - YOff; + else + NewHeight = Height; + + NewWidth -= SkipX; + NewHeight -= SkipY; + + for (y = 0; y < NewHeight; y++) { + for (x = 0; x < NewWidth; x++) { + for (c = 0; c < PixBpp; c++) { + TempData[(y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] = + Temp[(y + SkipY) * NewBps + (x + SkipX) * PixBpp + c]; + } + } + } + + if (TempData != iCurImage->Data) { + ifree(iCurImage->Data); + iCurImage->Data = TempData; + } + + return IL_TRUE; +} + + +ILboolean ilSetPixels3D(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, void *Data) +{ + ILuint SkipX = 0, SkipY = 0, SkipZ = 0, c, NewBps, NewSizePlane, PixBpp; + ILint x, y, z, NewW, NewH, NewD; + ILubyte *Temp = (ILubyte*)Data, *TempData = iCurImage->Data; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + if ((ILenum)ilGetInteger(IL_ORIGIN_MODE) != iCurImage->Origin) { + TempData = iGetFlipped(iCurImage); + if (TempData == NULL) + return IL_FALSE; + } + } + + PixBpp = iCurImage->Bpp * iCurImage->Bpc; + + if (XOff < 0) { + SkipX = abs(XOff); + XOff = 0; + } + if (YOff < 0) { + SkipY = abs(YOff); + YOff = 0; + } + if (ZOff < 0) { + SkipZ = abs(ZOff); + ZOff = 0; + } + + if (iCurImage->Width < XOff + Width) + NewW = iCurImage->Width - XOff; + else + NewW = Width; + NewBps = Width * PixBpp; + + if (iCurImage->Height < YOff + Height) + NewH = iCurImage->Height - YOff; + else + NewH = Height; + + if (iCurImage->Depth < ZOff + Depth) + NewD = iCurImage->Depth - ZOff; + else + NewD = Depth; + NewSizePlane = NewBps * Height; + + NewW -= SkipX; + NewH -= SkipY; + NewD -= SkipZ; + + for (z = 0; z < NewD; z++) { + for (y = 0; y < NewH; y++) { + for (x = 0; x < NewW; x++) { + for (c = 0; c < PixBpp; c++) { + TempData[(z + ZOff) * iCurImage->SizeOfPlane + (y + YOff) * iCurImage->Bps + (x + XOff) * PixBpp + c] = + Temp[(z + SkipZ) * NewSizePlane + (y + SkipY) * NewBps + (x + SkipX) * PixBpp + c]; + } + } + } + } + + if (TempData != iCurImage->Data) { + ifree(iCurImage->Data); + iCurImage->Data = TempData; + } + + return IL_TRUE; +} + + +void ILAPIENTRY ilSetPixels(ILint XOff, ILint YOff, ILint ZOff, ILuint Width, ILuint Height, ILuint Depth, ILenum Format, ILenum Type, void *Data) +{ + void *Converted; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return; + } + if (Data == NULL) { + ilSetError(IL_INVALID_PARAM); + return; + } + + if (Format == iCurImage->Format && Type == iCurImage->Type) { + Converted = (void*)Data; + } + else { + Converted = ilConvertBuffer(Width * Height * Depth * ilGetBppFormat(Format) * ilGetBpcType(Type), Format, iCurImage->Format, Type, iCurImage->Type, NULL, Data); + if (!Converted) + return; + } + + if (YOff + Height <= 1) { + ilSetPixels1D(XOff, Width, Converted); + } + else if (ZOff + Depth <= 1) { + ilSetPixels2D(XOff, YOff, Width, Height, Converted); + } + else { + ilSetPixels3D(XOff, YOff, ZOff, Width, Height, Depth, Converted); + } + + if (Format == iCurImage->Format && Type == iCurImage->Type) { + return; + } + + if (Converted != Data) + ifree(Converted); + + return; +} + + + +// Ripped from Platinum (Denton's sources) +// This could very well easily be changed to a 128x128 image instead...needed? + +//! Creates an ugly 64x64 black and yellow checkerboard image. +ILboolean ILAPIENTRY ilDefaultImage() +{ + ILubyte *TempData; + ILubyte Yellow[3] = { 18, 246, 243 }; + ILubyte Black[3] = { 0, 0, 0 }; + ILubyte *ColorPtr = Yellow; // The start color + ILboolean Color = IL_TRUE; + + // Loop Variables + ILint v, w, x, y; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!ilTexImage(64, 64, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + TempData = iCurImage->Data; + + for (v = 0; v < 8; v++) { + // We do this because after a "block" line ends, the next row of blocks + // above starts with the ending colour, but the very inner loop switches them. + if (Color) { + Color = IL_FALSE; + ColorPtr = Black; + } + else { + Color = IL_TRUE; + ColorPtr = Yellow; + } + + for (w = 0; w < 8; w++) { + for (x = 0; x < 8; x++) { + for (y = 0; y < 8; y++, TempData += iCurImage->Bpp) { + TempData[0] = ColorPtr[0]; + TempData[1] = ColorPtr[1]; + TempData[2] = ColorPtr[2]; + } + + // Switch to alternate between black and yellow + if (Color) { + Color = IL_FALSE; + ColorPtr = Black; + } + else { + Color = IL_TRUE; + ColorPtr = Yellow; + } + } + } + } + + return IL_TRUE; +} + + +ILubyte* ILAPIENTRY ilGetAlpha(ILenum Type) +{ + ILimage *TempImage; + ILubyte *Alpha; + ILushort *AlphaShort; + ILuint *AlphaInt; + ILdouble *AlphaDbl; + ILuint i, j, Bpc, Size, AlphaOff; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Bpc = ilGetBpcType(Type); + if (Bpc == 0) { + ilSetError(IL_INVALID_PARAM); + return NULL; + } + + if (iCurImage->Type == Type) { + TempImage = iCurImage; + } else { + TempImage = iConvertImage(iCurImage, iCurImage->Format, Type); + if (TempImage == NULL) + return NULL; + } + + Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * TempImage->Bpp; + Alpha = (ILubyte*)ialloc(Size / TempImage->Bpp * Bpc); + if (Alpha == NULL) { + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return NULL; + } + + switch (TempImage->Format) + { + case IL_RGB: + case IL_BGR: + case IL_LUMINANCE: + case IL_COLOUR_INDEX: // @TODO: Make IL_COLOUR_INDEX separate. + memset(Alpha, 0xFF, Size / TempImage->Bpp * Bpc); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return Alpha; + } + + // If our format is alpha, just return a copy. + if (TempImage->Format == IL_ALPHA) { + memcpy(Alpha, TempImage->Data, TempImage->SizeOfData); + return Alpha; + } + + if (TempImage->Format == IL_LUMINANCE_ALPHA) + AlphaOff = 2; + else + AlphaOff = 4; + + switch (TempImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + Alpha[j] = TempImage->Data[i]; + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + AlphaShort = (ILushort*)Alpha; + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + AlphaShort[j] = ((ILushort*)TempImage->Data)[i]; + break; + + case IL_INT: + case IL_UNSIGNED_INT: + case IL_FLOAT: // Can throw float in here, because it's the same size. + AlphaInt = (ILuint*)Alpha; + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + AlphaInt[j] = ((ILuint*)TempImage->Data)[i]; + break; + + case IL_DOUBLE: + AlphaDbl = (ILdouble*)Alpha; + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + AlphaDbl[j] = ((ILdouble*)TempImage->Data)[i]; + break; + } + + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return Alpha; +} + +// sets the Alpha value to a specific value for each pixel in the image +ILboolean ILAPIENTRY ilSetAlpha(ILdouble AlphaValue) +{ + ILboolean ret = IL_TRUE; + ILuint i,Size; + ILimage *Image = iCurImage; + ILuint AlphaOff; + + if (Image == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + AlphaValue = IL_CLAMP(AlphaValue); + + switch (Image->Format) + { + case IL_RGB: + ret = ilConvertImage(IL_RGBA, Image->Type); + case IL_RGBA: + AlphaOff = 4; + break; + case IL_BGR: + ret = ilConvertImage(IL_BGRA, Image->Type); + case IL_BGRA: + AlphaOff = 4; + break; + case IL_LUMINANCE: + ret = ilConvertImage(IL_LUMINANCE_ALPHA, Image->Type); + case IL_LUMINANCE_ALPHA: + AlphaOff = 2; + break; + case IL_ALPHA: + AlphaOff = 1; + case IL_COLOUR_INDEX: //@TODO use palette with alpha + ret = ilConvertImage(IL_RGBA, Image->Type); + AlphaOff = 4; + break; + } + if (ret == IL_FALSE) { + // Error has been set by ilConvertImage. + return IL_FALSE; + } + Size = Image->Width * Image->Height * Image->Depth * Image->Bpp; + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: { + const ILbyte alpha = (ILubyte)(AlphaValue * IL_MAX_UNSIGNED_BYTE + .5); + for (i = AlphaOff-1; i < Size; i += AlphaOff) + Image->Data[i] = alpha; + break; + } + case IL_SHORT: + case IL_UNSIGNED_SHORT: { + const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_SHORT + .5); + for (i = AlphaOff-1; i < Size; i += AlphaOff) + ((ILushort*)Image->Data)[i] = alpha; + break; + } + case IL_INT: + case IL_UNSIGNED_INT: { + const ILushort alpha = (ILushort)(AlphaValue * IL_MAX_UNSIGNED_INT + .5); + for (i = AlphaOff-1; i < Size; i += AlphaOff) + ((ILuint*)Image->Data)[i] = alpha; + break; + } + case IL_FLOAT: { + const ILfloat alpha = (ILfloat)AlphaValue; + for (i = AlphaOff-1; i < Size; i += AlphaOff) + ((ILfloat*)Image->Data)[i] = alpha; + break; + } + case IL_DOUBLE: { + const ILdouble alpha = AlphaValue; + for (i = AlphaOff-1; i < Size; i += AlphaOff) + ((ILdouble*)Image->Data)[i] = alpha; + break; + } + } + + return IL_TRUE; +} + +void ILAPIENTRY ilModAlpha(ILdouble AlphaValue) +{ + ILuint AlphaOff = 0; + ILboolean ret = IL_FALSE; + ILuint i,j,Size; + + union { + ILubyte alpha_byte; + ILushort alpha_short; + ILuint alpha_int; + ILfloat alpha_float; + ILdouble alpha_double; + } Alpha; + + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return; + } + + switch (iCurImage->Format) + { + case IL_RGB: + ret = ilConvertImage(IL_RGBA,iCurImage->Type); + AlphaOff = 4; + break; + case IL_BGR: + ret = ilConvertImage(IL_BGRA,iCurImage->Type); + AlphaOff = 4; + break; + case IL_LUMINANCE: + ret = ilConvertImage(IL_LUMINANCE_ALPHA,iCurImage->Type); + AlphaOff = 2; + break; + case IL_COLOUR_INDEX: + ret = ilConvertImage(IL_RGBA,iCurImage->Type); + AlphaOff = 4; + break; + } + Size = iCurImage->Width * iCurImage->Height * iCurImage->Depth * iCurImage->Bpp; + + if (!ret) + return; + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + Alpha.alpha_byte = (ILubyte)(AlphaValue * 0x000000FF + .5); + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + iCurImage->Data[i] = Alpha.alpha_byte; + break; + case IL_SHORT: + case IL_UNSIGNED_SHORT: + Alpha.alpha_short = (ILushort)(AlphaValue * 0x0000FFFF + .5); + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + ((ILushort*)iCurImage->Data)[i] = Alpha.alpha_short; + break; + case IL_INT: + case IL_UNSIGNED_INT: + Alpha.alpha_int = (ILuint)(AlphaValue * 0xFFFFFFFF + .5); + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + ((ILuint*)iCurImage->Data)[i] = Alpha.alpha_int; + break; + case IL_FLOAT: + Alpha.alpha_float = (ILfloat)AlphaValue; + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + ((ILfloat*)iCurImage->Data)[i] = Alpha.alpha_float; + break; + case IL_DOUBLE: + Alpha.alpha_double = AlphaValue; + for (i = AlphaOff-1, j = 0; i < Size; i += AlphaOff, j++) + ((ILdouble*)iCurImage->Data)[i] = Alpha.alpha_double; + break; + } + + return; +} + + +//! Clamps data values of unsigned bytes from 16 to 235 for display on an +// NTSC television. Reasoning for this is given at +// http://msdn.microsoft.com/en-us/library/bb174608.aspx. +ILboolean ILAPIENTRY ilClampNTSC(void) +{ + ILuint x, y, z, c; + ILuint Offset = 0; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (iCurImage->Type != IL_UNSIGNED_BYTE) // Should we set an error here? + return IL_FALSE; + + for (z = 0; z < iCurImage->Depth; z++) { + for (y = 0; y < iCurImage->Height; y++) { + for (x = 0; x < iCurImage->Width; x++) { + for (c = 0; c < iCurImage->Bpp; c++) { + iCurImage->Data[Offset + c] = IL_LIMIT(iCurImage->Data[Offset + c], 16, 235); + } + Offset += iCurImage->Bpp; + } + } + } + + return IL_TRUE; +} diff --git a/DevIL/src-IL/src/il_mdl.c b/DevIL/src-IL/src/il_mdl.c deleted file mode 100644 index d6b212a6..00000000 --- a/DevIL/src-IL/src/il_mdl.c +++ /dev/null @@ -1,218 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_mdl.c -// -// Description: Reads a Half-Life model file (.mdl). -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_MDL -#include "il_mdl.h" - - -ILboolean iLoadMdlInternal(void); -ILboolean iIsValidMdl(void); - -//! Checks if the file specified in FileName is a valid MDL file. -ILboolean ilIsValidMdl(ILconst_string FileName) -{ - ILHANDLE MdlFile; - ILboolean bMdl = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("mdl"))) { - ilSetError(IL_INVALID_EXTENSION); - return bMdl; - } - - MdlFile = iopenr(FileName); - if (MdlFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bMdl; - } - - bMdl = ilIsValidMdlF(MdlFile); - icloser(MdlFile); - - return bMdl; -} - - -//! Checks if the ILHANDLE contains a valid MDL file at the current position. -ILboolean ilIsValidMdlF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidMdl(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid MDL lump. -ILboolean ilIsValidMdlL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidMdl(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidMdl(void) -{ - ILuint Id, Version; - - Id = GetLittleUInt(); - Version = GetLittleUInt(); - iseek(-8, IL_SEEK_CUR); // Restore to previous position. - - // 0x54534449 == "IDST" - if (Id != 0x54534449 || Version != 10) - return IL_FALSE; - return IL_TRUE; -} - - -//! Reads a .mdl file -ILboolean ilLoadMdl(ILconst_string FileName) -{ - ILHANDLE MdlFile; - ILboolean bMdl = IL_FALSE; - - MdlFile = iopenr(FileName); - if (MdlFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bMdl; - } - - bMdl = ilLoadMdlF(MdlFile); - icloser(MdlFile); - - return bMdl; -} - - -//! Reads an already-opened .mdl file -ILboolean ilLoadMdlF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadMdlInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .mdl -ILboolean ilLoadMdlL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadMdlInternal(); -} - - -ILboolean iLoadMdlInternal() -{ - ILuint Id, Version, NumTex, TexOff, TexDataOff, Position, ImageNum; - ILubyte *TempPal; - TEX_HEAD TexHead; - ILimage *BaseImage=NULL; - ILboolean BaseCreated = IL_FALSE; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Id = GetLittleUInt(); - Version = GetLittleUInt(); - - // 0x54534449 == "IDST" - if (Id != 0x54534449 || Version != 10) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Skips the actual model header. - iseek(172, IL_SEEK_CUR); - - NumTex = GetLittleUInt(); - TexOff = GetLittleUInt(); - TexDataOff = GetLittleUInt(); - - if (NumTex == 0 || TexOff == 0 || TexDataOff == 0) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - iseek(TexOff, IL_SEEK_SET); - - for (ImageNum = 0; ImageNum < NumTex; ImageNum++) { - if (iread(TexHead.Name, 1, 64) != 64) - return IL_FALSE; - TexHead.Flags = GetLittleUInt(); - TexHead.Width = GetLittleUInt(); - TexHead.Height = GetLittleUInt(); - TexHead.Offset = GetLittleUInt(); - Position = itell(); - - if (TexHead.Offset == 0) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - if (!BaseCreated) { - ilTexImage(TexHead.Width, TexHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - BaseCreated = IL_TRUE; - BaseImage = iCurImage; - //iCurImage->NumNext = NumTex - 1; // Don't count the first image. - } - else { - //iCurImage->Next = ilNewImage(TexHead.Width, TexHead.Height, 1, 1, 1); - iCurImage = iCurImage->Next; - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Type = IL_UNSIGNED_BYTE; - } - - TempPal = (ILubyte*)ialloc(768); - if (TempPal == NULL) { - iCurImage = BaseImage; - return IL_FALSE; - } - iCurImage->Pal.Palette = TempPal; - iCurImage->Pal.PalSize = 768; - iCurImage->Pal.PalType = IL_PAL_RGB24; - - iseek(TexHead.Offset, IL_SEEK_SET); - if (iread(iCurImage->Data, TexHead.Width * TexHead.Height, 1) != 1) - return IL_FALSE; - if (iread(iCurImage->Pal.Palette, 1, 768) != 768) - return IL_FALSE; - - if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { - ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); - } - - iseek(Position, IL_SEEK_SET); - } - - iCurImage = BaseImage; - - return ilFixImage(); -} - -#endif//IL_NO_MDL diff --git a/DevIL/src-IL/src/il_mdl.cpp b/DevIL/src-IL/src/il_mdl.cpp new file mode 100644 index 00000000..d6b212a6 --- /dev/null +++ b/DevIL/src-IL/src/il_mdl.cpp @@ -0,0 +1,218 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_mdl.c +// +// Description: Reads a Half-Life model file (.mdl). +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_MDL +#include "il_mdl.h" + + +ILboolean iLoadMdlInternal(void); +ILboolean iIsValidMdl(void); + +//! Checks if the file specified in FileName is a valid MDL file. +ILboolean ilIsValidMdl(ILconst_string FileName) +{ + ILHANDLE MdlFile; + ILboolean bMdl = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("mdl"))) { + ilSetError(IL_INVALID_EXTENSION); + return bMdl; + } + + MdlFile = iopenr(FileName); + if (MdlFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bMdl; + } + + bMdl = ilIsValidMdlF(MdlFile); + icloser(MdlFile); + + return bMdl; +} + + +//! Checks if the ILHANDLE contains a valid MDL file at the current position. +ILboolean ilIsValidMdlF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidMdl(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid MDL lump. +ILboolean ilIsValidMdlL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidMdl(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidMdl(void) +{ + ILuint Id, Version; + + Id = GetLittleUInt(); + Version = GetLittleUInt(); + iseek(-8, IL_SEEK_CUR); // Restore to previous position. + + // 0x54534449 == "IDST" + if (Id != 0x54534449 || Version != 10) + return IL_FALSE; + return IL_TRUE; +} + + +//! Reads a .mdl file +ILboolean ilLoadMdl(ILconst_string FileName) +{ + ILHANDLE MdlFile; + ILboolean bMdl = IL_FALSE; + + MdlFile = iopenr(FileName); + if (MdlFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bMdl; + } + + bMdl = ilLoadMdlF(MdlFile); + icloser(MdlFile); + + return bMdl; +} + + +//! Reads an already-opened .mdl file +ILboolean ilLoadMdlF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadMdlInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .mdl +ILboolean ilLoadMdlL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadMdlInternal(); +} + + +ILboolean iLoadMdlInternal() +{ + ILuint Id, Version, NumTex, TexOff, TexDataOff, Position, ImageNum; + ILubyte *TempPal; + TEX_HEAD TexHead; + ILimage *BaseImage=NULL; + ILboolean BaseCreated = IL_FALSE; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Id = GetLittleUInt(); + Version = GetLittleUInt(); + + // 0x54534449 == "IDST" + if (Id != 0x54534449 || Version != 10) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Skips the actual model header. + iseek(172, IL_SEEK_CUR); + + NumTex = GetLittleUInt(); + TexOff = GetLittleUInt(); + TexDataOff = GetLittleUInt(); + + if (NumTex == 0 || TexOff == 0 || TexDataOff == 0) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + iseek(TexOff, IL_SEEK_SET); + + for (ImageNum = 0; ImageNum < NumTex; ImageNum++) { + if (iread(TexHead.Name, 1, 64) != 64) + return IL_FALSE; + TexHead.Flags = GetLittleUInt(); + TexHead.Width = GetLittleUInt(); + TexHead.Height = GetLittleUInt(); + TexHead.Offset = GetLittleUInt(); + Position = itell(); + + if (TexHead.Offset == 0) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + if (!BaseCreated) { + ilTexImage(TexHead.Width, TexHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + BaseCreated = IL_TRUE; + BaseImage = iCurImage; + //iCurImage->NumNext = NumTex - 1; // Don't count the first image. + } + else { + //iCurImage->Next = ilNewImage(TexHead.Width, TexHead.Height, 1, 1, 1); + iCurImage = iCurImage->Next; + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Type = IL_UNSIGNED_BYTE; + } + + TempPal = (ILubyte*)ialloc(768); + if (TempPal == NULL) { + iCurImage = BaseImage; + return IL_FALSE; + } + iCurImage->Pal.Palette = TempPal; + iCurImage->Pal.PalSize = 768; + iCurImage->Pal.PalType = IL_PAL_RGB24; + + iseek(TexHead.Offset, IL_SEEK_SET); + if (iread(iCurImage->Data, TexHead.Width * TexHead.Height, 1) != 1) + return IL_FALSE; + if (iread(iCurImage->Pal.Palette, 1, 768) != 768) + return IL_FALSE; + + if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { + ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); + } + + iseek(Position, IL_SEEK_SET); + } + + iCurImage = BaseImage; + + return ilFixImage(); +} + +#endif//IL_NO_MDL diff --git a/DevIL/src-IL/src/il_mng.c b/DevIL/src-IL/src/il_mng.c deleted file mode 100644 index 4b57a256..00000000 --- a/DevIL/src-IL/src/il_mng.c +++ /dev/null @@ -1,378 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_mng.c -// -// Description: Multiple Network Graphics (.mng) functions -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_MNG -#define MNG_SUPPORT_READ -#define MNG_SUPPORT_WRITE -#define MNG_SUPPORT_DISPLAY - -#ifdef _WIN32 -//#define MNG_USE_SO -#endif - -#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "libmng.lib") - #pragma comment(lib, "lcms2.lib") - #pragma comment(lib, "libjpeg.lib") - #pragma comment(lib, "zlibstatic.lib") - #else - #pragma comment(lib, "libmng.lib") - #pragma comment(lib, "lcms2.lib") - #pragma comment(lib, "libjpeg.lib") - #pragma comment(lib, "zlibstatic.lib") - #endif - #endif -#endif - - -#if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable : 4142) // Redefinition in jmorecfg.h -#endif - -#include - -#if defined(_MSC_VER) - #pragma warning(pop) -#endif - - -//--------------------------------------------------------------------------------------------- -// memory allocation; data must be zeroed -//--------------------------------------------------------------------------------------------- -mng_ptr MNG_DECL mymngalloc(mng_size_t size) -{ - return (mng_ptr)icalloc(1, size); -} - - -//--------------------------------------------------------------------------------------------- -// memory deallocation -//--------------------------------------------------------------------------------------------- -void MNG_DECL mymngfree(mng_ptr p, mng_size_t size) -{ - ifree(p); -} - - -//--------------------------------------------------------------------------------------------- -// Stream open: -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngopenstream(mng_handle mng) -{ - return MNG_TRUE; -} - - -//--------------------------------------------------------------------------------------------- -// Stream open for Writing: -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngopenstreamwrite(mng_handle mng) -{ - return MNG_TRUE; -} - - -//--------------------------------------------------------------------------------------------- -// Stream close: -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngclosestream(mng_handle mng) -{ - return MNG_TRUE; // We close the file ourself, mng_cleanup doesnt seem to do it... -} - - -//--------------------------------------------------------------------------------------------- -// feed data to the decoder -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngreadstream(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *bytesread) -{ - // read the requested amount of data from the file - *bytesread = iread(buffer, 1, (ILuint)size); - - return MNG_TRUE; -} - - -//--------------------------------------------------------------------------------------------- -// callback for writing data -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngwritedata(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *byteswritten) -{ - *byteswritten = iwrite(buffer, 1, (ILuint)size); - - if (*byteswritten < size) { - ilSetError(IL_FILE_WRITE_ERROR); - return MNG_FALSE; - } - - return MNG_TRUE; -} - - -//--------------------------------------------------------------------------------------------- -// the header's been read. set up the display stuff -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height) -{ - ILuint AlphaDepth; - - AlphaDepth = mng_get_alphadepth(mng); - - if (AlphaDepth == 0) { - ilTexImage(width, height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL); - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - mng_set_canvasstyle(mng, MNG_CANVAS_BGR8); - } - else { // Use alpha channel - ilTexImage(width, height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8); - } - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - return MNG_TRUE; -} - - -//--------------------------------------------------------------------------------------------- -// return a row pointer for the decoder to fill -//--------------------------------------------------------------------------------------------- -mng_ptr MNG_DECL mymnggetcanvasline(mng_handle mng, mng_uint32 line) -{ - return (mng_ptr)(iCurImage->Data + iCurImage->Bps * line); -} - - -//--------------------------------------------------------------------------------------------- -// timer -//--------------------------------------------------------------------------------------------- -mng_uint32 MNG_DECL mymnggetticks(mng_handle mng) -{ - return 0; -} - - -//--------------------------------------------------------------------------------------------- -// Refresh: -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) -{ - return MNG_TRUE; -} - - -//--------------------------------------------------------------------------------------------- -// interframe delay callback -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngsettimer(mng_handle mng, mng_uint32 msecs) -{ - return MNG_TRUE; -} - - - -// Make this do something different soon! - -//--------------------------------------------------------------------------------------------- -// Error Callback; -//--------------------------------------------------------------------------------------------- -mng_bool MNG_DECL mymngerror( - mng_handle mng, mng_int32 code, mng_int8 severity, - mng_chunkid chunktype, mng_uint32 chunkseq, - mng_int32 extra1, mng_int32 extra2, mng_pchar text - ) -{ - // error occured; - return MNG_FALSE; -} - - -ILboolean iLoadMngInternal(void); - -// Reads a file -ILboolean ilLoadMng(ILconst_string FileName) -{ - ILHANDLE MngFile; - ILboolean bMng = IL_FALSE; - - MngFile = iopenr(FileName); - if (MngFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bMng; - } - - bMng = ilLoadMngF(MngFile); - icloser(MngFile); - - return bMng; -} - - -// Reads an already-opened file -ILboolean ilLoadMngF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadMngInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -// Reads from a memory "lump" -ILboolean ilLoadMngL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadMngInternal(); -} - - -ILboolean iLoadMngInternal() -{ - mng_handle mng; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL); - if (mng == MNG_NULL) { - ilSetError(IL_LIB_MNG_ERROR); - return IL_FALSE; - } - - // If .mng background is available, use it. - mng_set_usebkgd(mng, MNG_TRUE); - - // Set the callbacks. - mng_setcb_errorproc(mng, mymngerror); - mng_setcb_openstream(mng, mymngopenstream); - mng_setcb_closestream(mng, mymngclosestream); - mng_setcb_readdata(mng, (mng_readdata)mymngreadstream); - mng_setcb_gettickcount(mng, mymnggetticks); - mng_setcb_settimer(mng, mymngsettimer); - mng_setcb_processheader(mng, mymngprocessheader); - mng_setcb_getcanvasline(mng, mymnggetcanvasline); - mng_setcb_refresh(mng, mymngrefresh); - - mng_read(mng); - mng_display(mng); - - return ilFixImage(); -} - - -ILboolean iSaveMngInternal(void); - -//! Writes a Mng file -ILboolean ilSaveMng(const ILstring FileName) -{ - ILHANDLE MngFile; - ILuint MngSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - MngFile = iopenw(FileName); - if (MngFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - MngSize = ilSaveMngF(MngFile); - iclosew(MngFile); - - if (MngSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Mng to an already-opened file -ILuint ilSaveMngF(ILHANDLE File) -{ - ILuint Pos = itellw(); - iSetOutputFile(File); - if (iSaveMngInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Mng to a memory "lump" -ILuint ilSaveMngL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveMngInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the Mng. -ILboolean iSaveMngInternal() -{ - //mng_handle mng; - - // Not working yet, so just error out. - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - - //if (iCurImage == NULL) { - // ilSetError(IL_ILLEGAL_OPERATION); - // return IL_FALSE; - //} - - //mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL); - //if (mng == MNG_NULL) { - // ilSetError(IL_LIB_MNG_ERROR); - // return IL_FALSE; - //} - - //mng_setcb_openstream(mng, mymngopenstreamwrite); - //mng_setcb_closestream(mng, mymngclosestream); - //mng_setcb_writedata(mng, mymngwritedata); - - //// Write File: - // mng_create(mng); - - //// Check return value. - //mng_putchunk_mhdr(mng, iCurImage->Width, iCurImage->Height, 1000, 3, 1, 3, 0x0047); - //mng_putchunk_basi(mng, iCurImage->Width, iCurImage->Height, 8, MNG_COLORTYPE_RGB, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 1); - //mng_putchunk_iend(mng); - //mng_putimgdata_ihdr(mng, iCurImage->Width, iCurImage->Height, MNG_COLORTYPE_RGB, 8, 0, 0, 0, 0, mymnggetcanvasline); - - //// Now write file: - //mng_write(mng); - - //mng_cleanup(&mng); - - //return IL_TRUE; -} - -#endif//IL_NO_MNG diff --git a/DevIL/src-IL/src/il_mng.cpp b/DevIL/src-IL/src/il_mng.cpp new file mode 100644 index 00000000..4b57a256 --- /dev/null +++ b/DevIL/src-IL/src/il_mng.cpp @@ -0,0 +1,378 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_mng.c +// +// Description: Multiple Network Graphics (.mng) functions +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_MNG +#define MNG_SUPPORT_READ +#define MNG_SUPPORT_WRITE +#define MNG_SUPPORT_DISPLAY + +#ifdef _WIN32 +//#define MNG_USE_SO +#endif + +#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "libmng.lib") + #pragma comment(lib, "lcms2.lib") + #pragma comment(lib, "libjpeg.lib") + #pragma comment(lib, "zlibstatic.lib") + #else + #pragma comment(lib, "libmng.lib") + #pragma comment(lib, "lcms2.lib") + #pragma comment(lib, "libjpeg.lib") + #pragma comment(lib, "zlibstatic.lib") + #endif + #endif +#endif + + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4142) // Redefinition in jmorecfg.h +#endif + +#include + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + + +//--------------------------------------------------------------------------------------------- +// memory allocation; data must be zeroed +//--------------------------------------------------------------------------------------------- +mng_ptr MNG_DECL mymngalloc(mng_size_t size) +{ + return (mng_ptr)icalloc(1, size); +} + + +//--------------------------------------------------------------------------------------------- +// memory deallocation +//--------------------------------------------------------------------------------------------- +void MNG_DECL mymngfree(mng_ptr p, mng_size_t size) +{ + ifree(p); +} + + +//--------------------------------------------------------------------------------------------- +// Stream open: +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngopenstream(mng_handle mng) +{ + return MNG_TRUE; +} + + +//--------------------------------------------------------------------------------------------- +// Stream open for Writing: +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngopenstreamwrite(mng_handle mng) +{ + return MNG_TRUE; +} + + +//--------------------------------------------------------------------------------------------- +// Stream close: +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngclosestream(mng_handle mng) +{ + return MNG_TRUE; // We close the file ourself, mng_cleanup doesnt seem to do it... +} + + +//--------------------------------------------------------------------------------------------- +// feed data to the decoder +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngreadstream(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *bytesread) +{ + // read the requested amount of data from the file + *bytesread = iread(buffer, 1, (ILuint)size); + + return MNG_TRUE; +} + + +//--------------------------------------------------------------------------------------------- +// callback for writing data +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngwritedata(mng_handle mng, mng_ptr buffer, mng_size_t size, mng_uint32 *byteswritten) +{ + *byteswritten = iwrite(buffer, 1, (ILuint)size); + + if (*byteswritten < size) { + ilSetError(IL_FILE_WRITE_ERROR); + return MNG_FALSE; + } + + return MNG_TRUE; +} + + +//--------------------------------------------------------------------------------------------- +// the header's been read. set up the display stuff +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height) +{ + ILuint AlphaDepth; + + AlphaDepth = mng_get_alphadepth(mng); + + if (AlphaDepth == 0) { + ilTexImage(width, height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL); + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + mng_set_canvasstyle(mng, MNG_CANVAS_BGR8); + } + else { // Use alpha channel + ilTexImage(width, height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8); + } + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + return MNG_TRUE; +} + + +//--------------------------------------------------------------------------------------------- +// return a row pointer for the decoder to fill +//--------------------------------------------------------------------------------------------- +mng_ptr MNG_DECL mymnggetcanvasline(mng_handle mng, mng_uint32 line) +{ + return (mng_ptr)(iCurImage->Data + iCurImage->Bps * line); +} + + +//--------------------------------------------------------------------------------------------- +// timer +//--------------------------------------------------------------------------------------------- +mng_uint32 MNG_DECL mymnggetticks(mng_handle mng) +{ + return 0; +} + + +//--------------------------------------------------------------------------------------------- +// Refresh: +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) +{ + return MNG_TRUE; +} + + +//--------------------------------------------------------------------------------------------- +// interframe delay callback +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngsettimer(mng_handle mng, mng_uint32 msecs) +{ + return MNG_TRUE; +} + + + +// Make this do something different soon! + +//--------------------------------------------------------------------------------------------- +// Error Callback; +//--------------------------------------------------------------------------------------------- +mng_bool MNG_DECL mymngerror( + mng_handle mng, mng_int32 code, mng_int8 severity, + mng_chunkid chunktype, mng_uint32 chunkseq, + mng_int32 extra1, mng_int32 extra2, mng_pchar text + ) +{ + // error occured; + return MNG_FALSE; +} + + +ILboolean iLoadMngInternal(void); + +// Reads a file +ILboolean ilLoadMng(ILconst_string FileName) +{ + ILHANDLE MngFile; + ILboolean bMng = IL_FALSE; + + MngFile = iopenr(FileName); + if (MngFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bMng; + } + + bMng = ilLoadMngF(MngFile); + icloser(MngFile); + + return bMng; +} + + +// Reads an already-opened file +ILboolean ilLoadMngF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadMngInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +// Reads from a memory "lump" +ILboolean ilLoadMngL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadMngInternal(); +} + + +ILboolean iLoadMngInternal() +{ + mng_handle mng; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL); + if (mng == MNG_NULL) { + ilSetError(IL_LIB_MNG_ERROR); + return IL_FALSE; + } + + // If .mng background is available, use it. + mng_set_usebkgd(mng, MNG_TRUE); + + // Set the callbacks. + mng_setcb_errorproc(mng, mymngerror); + mng_setcb_openstream(mng, mymngopenstream); + mng_setcb_closestream(mng, mymngclosestream); + mng_setcb_readdata(mng, (mng_readdata)mymngreadstream); + mng_setcb_gettickcount(mng, mymnggetticks); + mng_setcb_settimer(mng, mymngsettimer); + mng_setcb_processheader(mng, mymngprocessheader); + mng_setcb_getcanvasline(mng, mymnggetcanvasline); + mng_setcb_refresh(mng, mymngrefresh); + + mng_read(mng); + mng_display(mng); + + return ilFixImage(); +} + + +ILboolean iSaveMngInternal(void); + +//! Writes a Mng file +ILboolean ilSaveMng(const ILstring FileName) +{ + ILHANDLE MngFile; + ILuint MngSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + MngFile = iopenw(FileName); + if (MngFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + MngSize = ilSaveMngF(MngFile); + iclosew(MngFile); + + if (MngSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Mng to an already-opened file +ILuint ilSaveMngF(ILHANDLE File) +{ + ILuint Pos = itellw(); + iSetOutputFile(File); + if (iSaveMngInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Mng to a memory "lump" +ILuint ilSaveMngL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveMngInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the Mng. +ILboolean iSaveMngInternal() +{ + //mng_handle mng; + + // Not working yet, so just error out. + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + + //if (iCurImage == NULL) { + // ilSetError(IL_ILLEGAL_OPERATION); + // return IL_FALSE; + //} + + //mng = mng_initialize(MNG_NULL, mymngalloc, mymngfree, MNG_NULL); + //if (mng == MNG_NULL) { + // ilSetError(IL_LIB_MNG_ERROR); + // return IL_FALSE; + //} + + //mng_setcb_openstream(mng, mymngopenstreamwrite); + //mng_setcb_closestream(mng, mymngclosestream); + //mng_setcb_writedata(mng, mymngwritedata); + + //// Write File: + // mng_create(mng); + + //// Check return value. + //mng_putchunk_mhdr(mng, iCurImage->Width, iCurImage->Height, 1000, 3, 1, 3, 0x0047); + //mng_putchunk_basi(mng, iCurImage->Width, iCurImage->Height, 8, MNG_COLORTYPE_RGB, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 1); + //mng_putchunk_iend(mng); + //mng_putimgdata_ihdr(mng, iCurImage->Width, iCurImage->Height, MNG_COLORTYPE_RGB, 8, 0, 0, 0, 0, mymnggetcanvasline); + + //// Now write file: + //mng_write(mng); + + //mng_cleanup(&mng); + + //return IL_TRUE; +} + +#endif//IL_NO_MNG diff --git a/DevIL/src-IL/src/il_mp3.c b/DevIL/src-IL/src/il_mp3.c deleted file mode 100755 index d75711b9..00000000 --- a/DevIL/src-IL/src/il_mp3.c +++ /dev/null @@ -1,280 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/05/2009 -// -// Filename: src-IL/src/il_mp3.c -// -// MimeType: Reads from an MPEG-1 Audio Layer 3 (.mp3) file. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_MP3 - -typedef struct MP3HEAD -{ - char Signature[3]; - ILubyte VersionMajor; - ILubyte VersionMinor; - ILubyte Flags; - ILuint Length; -} MP3HEAD; - -#define MP3_NONE 0 -#define MP3_JPG 1 -#define MP3_PNG 2 - -ILboolean iLoadMp3Internal(void); -ILboolean iIsValidMp3(void); -ILboolean iCheckMp3(MP3HEAD *Header); -ILboolean iLoadJpegInternal(void); -ILboolean iLoadPngInternal(void); - - -//! Checks if the file specified in FileName is a valid MP3 file. -ILboolean ilIsValidMp3(ILconst_string FileName) -{ - ILHANDLE Mp3File; - ILboolean bMp3 = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("mp3"))) { - ilSetError(IL_INVALID_EXTENSION); - return bMp3; - } - - Mp3File = iopenr(FileName); - if (Mp3File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bMp3; - } - - bMp3 = ilIsValidMp3F(Mp3File); - icloser(Mp3File); - - return bMp3; -} - - -//! Checks if the ILHANDLE contains a valid MP3 file at the current position. -ILboolean ilIsValidMp3F(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidMp3(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid MP3 lump. -ILboolean ilIsValidMp3L(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidMp3(); -} - - -ILuint GetSynchInt() -{ - ILuint SynchInt; - - SynchInt = GetBigUInt(); - - SynchInt = ((SynchInt & 0x7F000000) >> 3) | ((SynchInt & 0x7F0000) >> 2) - | ((SynchInt & 0x7F00) >> 1) | (SynchInt & 0x7F); - - return SynchInt; -} - - -// Internal function used to get the MP3 header from the current file. -ILboolean iGetMp3Head(MP3HEAD *Header) -{ - if (iread(Header->Signature, 3, 1) != 1) - return IL_FALSE; - Header->VersionMajor = igetc(); - Header->VersionMinor = igetc(); - Header->Flags = igetc(); - Header->Length = GetSynchInt(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidMp3(void) -{ - MP3HEAD Header; - ILuint Pos = itell(); - - if (!iGetMp3Head(&Header)) - return IL_FALSE; - // The length of the header varies, so we just go back to the original position. - iseek(Pos, IL_SEEK_CUR); - - return iCheckMp3(&Header); -} - - -// Internal function used to check if the HEADER is a valid MP3 header. -ILboolean iCheckMp3(MP3HEAD *Header) -{ - if (strncmp(Header->Signature, "ID3", 3)) - return IL_FALSE; - if (Header->VersionMajor != 3 && Header->VersionMinor != 4) - return IL_FALSE; - - return IL_TRUE; -} - - -ILuint iFindMp3Pic(MP3HEAD *Header) -{ - char ID[4]; - ILuint FrameSize; - ILubyte TextEncoding; - ILubyte MimeType[65], Description[65]; - ILubyte PicType; - ILuint i; - ILuint Type = MP3_NONE; - - do { - if (iread(ID, 4, 1) != 1) - return MP3_NONE; - if (Header->VersionMajor == 3) - FrameSize = GetBigUInt(); - else - FrameSize = GetSynchInt(); - - GetBigUShort(); // Skip the flags. - - //@TODO: Support multiple APIC entries in an mp3 file. - if (!strncmp(ID, "APIC", 4)) { - //@TODO: Use TextEncoding properly - UTF16 strings starting with FFFE or FEFF. - TextEncoding = igetc(); - // Get the MimeType (read until we hit 0). - for (i = 0; i < 65; i++) { - MimeType[i] = igetc(); - if (MimeType[i] == 0) - break; - } - // The MimeType must be terminated by 0 in the file by the specs. - if (MimeType[i] != 0) - return MP3_NONE; - if (!strcmp(MimeType, "image/jpeg")) - Type = MP3_JPG; - else if (!strcmp(MimeType, "image/png")) - Type = MP3_PNG; - else - Type = MP3_NONE; - - PicType = igetc(); // Whether this is a cover, band logo, etc. - - // Skip the description. - for (i = 0; i < 65; i++) { - Description[i] = igetc(); - if (Description[i] == 0) - break; - } - if (Description[i] != 0) - return MP3_NONE; - return Type; - } - else { - iseek(FrameSize, IL_SEEK_CUR); - } - - //if (!strncmp(MimeType, " - } while (!ieof() && itell() < Header->Length); - - return Type; -} - - -//! Reads a MP3 file -ILboolean ilLoadMp3(ILconst_string FileName) -{ - ILHANDLE Mp3File; - ILboolean bMp3 = IL_FALSE; - - Mp3File = iopenr(FileName); - if (Mp3File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bMp3; - } - - bMp3 = ilLoadMp3F(Mp3File); - icloser(Mp3File); - - return bMp3; -} - - -//! Reads an already-opened MP3 file -ILboolean ilLoadMp3F(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadMp3Internal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a MP3 -ILboolean ilLoadMp3L(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadMp3Internal(); -} - - -// Internal function used to load the MP3. -ILboolean iLoadMp3Internal(void) -{ - MP3HEAD Header; - ILuint Type; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetMp3Head(&Header)) - return IL_FALSE; - if (!iCheckMp3(&Header)) - return IL_FALSE; - Type = iFindMp3Pic(&Header); - - switch (Type) - { -#ifndef IL_NO_JPG - case MP3_JPG: - return iLoadJpegInternal(); -#endif//IL_NO_JPG - -#ifndef IL_NO_PNG - case MP3_PNG: - return iLoadPngInternal(); -#endif//IL_NO_PNG - - // Either a picture was not found, or the MIME type was not recognized. - default: - ilSetError(IL_INVALID_FILE_HEADER); - } - - return IL_FALSE; -} - -#endif//IL_NO_MP3 - diff --git a/DevIL/src-IL/src/il_mp3.cpp b/DevIL/src-IL/src/il_mp3.cpp new file mode 100755 index 00000000..d75711b9 --- /dev/null +++ b/DevIL/src-IL/src/il_mp3.cpp @@ -0,0 +1,280 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/05/2009 +// +// Filename: src-IL/src/il_mp3.c +// +// MimeType: Reads from an MPEG-1 Audio Layer 3 (.mp3) file. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_MP3 + +typedef struct MP3HEAD +{ + char Signature[3]; + ILubyte VersionMajor; + ILubyte VersionMinor; + ILubyte Flags; + ILuint Length; +} MP3HEAD; + +#define MP3_NONE 0 +#define MP3_JPG 1 +#define MP3_PNG 2 + +ILboolean iLoadMp3Internal(void); +ILboolean iIsValidMp3(void); +ILboolean iCheckMp3(MP3HEAD *Header); +ILboolean iLoadJpegInternal(void); +ILboolean iLoadPngInternal(void); + + +//! Checks if the file specified in FileName is a valid MP3 file. +ILboolean ilIsValidMp3(ILconst_string FileName) +{ + ILHANDLE Mp3File; + ILboolean bMp3 = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("mp3"))) { + ilSetError(IL_INVALID_EXTENSION); + return bMp3; + } + + Mp3File = iopenr(FileName); + if (Mp3File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bMp3; + } + + bMp3 = ilIsValidMp3F(Mp3File); + icloser(Mp3File); + + return bMp3; +} + + +//! Checks if the ILHANDLE contains a valid MP3 file at the current position. +ILboolean ilIsValidMp3F(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidMp3(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid MP3 lump. +ILboolean ilIsValidMp3L(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidMp3(); +} + + +ILuint GetSynchInt() +{ + ILuint SynchInt; + + SynchInt = GetBigUInt(); + + SynchInt = ((SynchInt & 0x7F000000) >> 3) | ((SynchInt & 0x7F0000) >> 2) + | ((SynchInt & 0x7F00) >> 1) | (SynchInt & 0x7F); + + return SynchInt; +} + + +// Internal function used to get the MP3 header from the current file. +ILboolean iGetMp3Head(MP3HEAD *Header) +{ + if (iread(Header->Signature, 3, 1) != 1) + return IL_FALSE; + Header->VersionMajor = igetc(); + Header->VersionMinor = igetc(); + Header->Flags = igetc(); + Header->Length = GetSynchInt(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidMp3(void) +{ + MP3HEAD Header; + ILuint Pos = itell(); + + if (!iGetMp3Head(&Header)) + return IL_FALSE; + // The length of the header varies, so we just go back to the original position. + iseek(Pos, IL_SEEK_CUR); + + return iCheckMp3(&Header); +} + + +// Internal function used to check if the HEADER is a valid MP3 header. +ILboolean iCheckMp3(MP3HEAD *Header) +{ + if (strncmp(Header->Signature, "ID3", 3)) + return IL_FALSE; + if (Header->VersionMajor != 3 && Header->VersionMinor != 4) + return IL_FALSE; + + return IL_TRUE; +} + + +ILuint iFindMp3Pic(MP3HEAD *Header) +{ + char ID[4]; + ILuint FrameSize; + ILubyte TextEncoding; + ILubyte MimeType[65], Description[65]; + ILubyte PicType; + ILuint i; + ILuint Type = MP3_NONE; + + do { + if (iread(ID, 4, 1) != 1) + return MP3_NONE; + if (Header->VersionMajor == 3) + FrameSize = GetBigUInt(); + else + FrameSize = GetSynchInt(); + + GetBigUShort(); // Skip the flags. + + //@TODO: Support multiple APIC entries in an mp3 file. + if (!strncmp(ID, "APIC", 4)) { + //@TODO: Use TextEncoding properly - UTF16 strings starting with FFFE or FEFF. + TextEncoding = igetc(); + // Get the MimeType (read until we hit 0). + for (i = 0; i < 65; i++) { + MimeType[i] = igetc(); + if (MimeType[i] == 0) + break; + } + // The MimeType must be terminated by 0 in the file by the specs. + if (MimeType[i] != 0) + return MP3_NONE; + if (!strcmp(MimeType, "image/jpeg")) + Type = MP3_JPG; + else if (!strcmp(MimeType, "image/png")) + Type = MP3_PNG; + else + Type = MP3_NONE; + + PicType = igetc(); // Whether this is a cover, band logo, etc. + + // Skip the description. + for (i = 0; i < 65; i++) { + Description[i] = igetc(); + if (Description[i] == 0) + break; + } + if (Description[i] != 0) + return MP3_NONE; + return Type; + } + else { + iseek(FrameSize, IL_SEEK_CUR); + } + + //if (!strncmp(MimeType, " + } while (!ieof() && itell() < Header->Length); + + return Type; +} + + +//! Reads a MP3 file +ILboolean ilLoadMp3(ILconst_string FileName) +{ + ILHANDLE Mp3File; + ILboolean bMp3 = IL_FALSE; + + Mp3File = iopenr(FileName); + if (Mp3File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bMp3; + } + + bMp3 = ilLoadMp3F(Mp3File); + icloser(Mp3File); + + return bMp3; +} + + +//! Reads an already-opened MP3 file +ILboolean ilLoadMp3F(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadMp3Internal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a MP3 +ILboolean ilLoadMp3L(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadMp3Internal(); +} + + +// Internal function used to load the MP3. +ILboolean iLoadMp3Internal(void) +{ + MP3HEAD Header; + ILuint Type; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetMp3Head(&Header)) + return IL_FALSE; + if (!iCheckMp3(&Header)) + return IL_FALSE; + Type = iFindMp3Pic(&Header); + + switch (Type) + { +#ifndef IL_NO_JPG + case MP3_JPG: + return iLoadJpegInternal(); +#endif//IL_NO_JPG + +#ifndef IL_NO_PNG + case MP3_PNG: + return iLoadPngInternal(); +#endif//IL_NO_PNG + + // Either a picture was not found, or the MIME type was not recognized. + default: + ilSetError(IL_INVALID_FILE_HEADER); + } + + return IL_FALSE; +} + +#endif//IL_NO_MP3 + diff --git a/DevIL/src-IL/src/il_neuquant.c b/DevIL/src-IL/src/il_neuquant.c deleted file mode 100644 index c00f4a00..00000000 --- a/DevIL/src-IL/src/il_neuquant.c +++ /dev/null @@ -1,462 +0,0 @@ -/* NeuQuant Neural-Net Quantization Algorithm - * ------------------------------------------ - * - * Copyright (c) 1994 Anthony Dekker - * - * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. - * See "Kohonen neural networks for optimal colour quantization" - * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367. - * for a discussion of the algorithm. - * See also http://www.acm.org/~dekker/NEUQUANT.HTML - * - * Any party obtaining a copy of these files from the author, directly or - * indirectly, is granted, free of charge, a full and unrestricted irrevocable, - * world-wide, paid up, royalty-free, nonexclusive right and license to deal - * in this software and documentation files (the "Software"), including without - * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons who receive - * copies from any such party to do so, with the only requirement being - * that this copyright notice remain intact. - */ - -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// by Denton Woods -// Last modified: 01/04/2009 -// -// Filename: src-IL/src/il_neuquant.c -// -// Description: Heavily modified by Denton Woods. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" - - -// Function definitions -void initnet(ILubyte *thepic, ILint len, ILint sample); -void unbiasnet(); -void inxbuild(); -ILubyte inxsearch(ILint b, ILint g, ILint r); -void learn(); - -// four primes near 500 - assume no image has a length so large -// that it is divisible by all four primes -#define prime1 499 -#define prime2 491 -#define prime3 487 -#define prime4 503 - -#define minpicturebytes (3*prime4) // minimum size for input image - - -// Network Definitions -// ------------------- - -#define netsize 256 // number of colours used -#define maxnetpos (netsizethink-1) -#define netbiasshift 4 // bias for colour values -#define ncycles 100 // no. of learning cycles - -// defs for freq and bias -#define intbiasshift 16 // bias for fractions -#define intbias (((ILint) 1)<>betashift)// beta = 1/1024 -#define betagamma (intbias<<(gammashift-betashift)) - -// defs for decreasing radius factor -#define initrad (netsize>>3) // for 256 cols, radius starts -#define radiusbiasshift 6 // at 32.0 biased by 6 bits -#define radiusbias (((ILint) 1)<>= netbiasshift; - network[i][3] = i; // record colour no - } - return; -} - - -// Insertion sort of network and building of netindex[0..255] (to do after unbias) -// ------------------------------------------------------------------------------- - -void inxbuild() -{ - ILint i,j,smallpos,smallval; - ILint *p,*q; - ILint previouscol,startpos; - - previouscol = 0; - startpos = 0; - for (i=0; i>1; - for (j=previouscol+1; j>1; - for (j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; // really 256 - return; -} - - -// Search for BGR values 0..255 (after net is unbiased) and return colour index -// ---------------------------------------------------------------------------- - -ILubyte inxsearch(ILint b, ILint g, ILint r) -{ - ILint i,j,dist,a,bestd; - ILint *p; - ILint best; - - bestd = 1000; // biggest possible dist is 256*3 - best = -1; - i = netindex[g]; // index on g - j = i-1; // start at netindex[g] and work outwards - - while ((i=0)) { - if (i= bestd) i = netsizethink; // stop iter - else { - i++; - if (dist<0) dist = -dist; - a = p[0] - b; if (a<0) a = -a; - dist += a; - if (dist=0) { - p = network[j]; - dist = g - p[1]; // inx key - reverse dif - if (dist >= bestd) j = -1; // stop iter - else { - j--; - if (dist<0) dist = -dist; - a = p[0] - b; if (a<0) a = -a; - dist += a; - if (dist>(intbiasshift-netbiasshift)); - if (biasdist> betashift); - *f++ -= betafreq; - *p++ += (betafreq<netsizethink) hi=netsizethink; - - j = i+1; - k = i-1; - q = radpower; - while ((jlo)) { - a = (*(++q)); - if (jlo) { - p = network[k]; - *p -= (a*(*p - b)) / alpharadbias; - p++; - *p -= (a*(*p - g)) / alpharadbias; - p++; - *p -= (a*(*p - r)) / alpharadbias; - k--; - } - } - return; -} - - -// Main Learning Loop -// ------------------ - -void learn() -{ - ILint i,j,b,g,r; - ILint radius,rad,alpha,step,delta,samplepixels; - ILubyte *p; - ILubyte *lim; - - alphadec = 30 + ((samplefac-1)/3); - p = thepicture; - lim = thepicture + lengthcount; - samplepixels = lengthcount/(3*samplefac); - delta = samplepixels/ncycles; - alpha = initalpha; - radius = initradius; - - rad = radius >> radiusbiasshift; - if (rad <= 1) rad = 0; - for (i=0; i= lim) p -= lengthcount; - - i++; - if (i%delta == 0) { - alpha -= alpha / alphadec; - radius -= radius / radiusdec; - rad = radius >> radiusbiasshift; - if (rad <= 1) rad = 0; - for (j=0; jData, TempImage->SizeOfData, sample); - learn(); - unbiasnet(); - - NewImage = (ILimage*)icalloc(sizeof(ILimage), 1); - if (NewImage == NULL) { - ilCloseImage(TempImage); - return NULL; - } - NewImage->Data = (ILubyte*)ialloc(TempImage->SizeOfData / 3); - if (NewImage->Data == NULL) { - ilCloseImage(TempImage); - ifree(NewImage); - return NULL; - } - ilCopyImageAttr(NewImage, Image); - NewImage->Bpp = 1; - NewImage->Bps = Image->Width; - NewImage->SizeOfPlane = NewImage->Bps * Image->Height; - NewImage->SizeOfData = NewImage->SizeOfPlane; - NewImage->Format = IL_COLOUR_INDEX; - NewImage->Type = IL_UNSIGNED_BYTE; - - NewImage->Pal.PalSize = netsizethink * 3; - NewImage->Pal.PalType = IL_PAL_BGR24; - NewImage->Pal.Palette = (ILubyte*)ialloc(256*3); - if (NewImage->Pal.Palette == NULL) { - ilCloseImage(TempImage); - ilCloseImage(NewImage); - return NULL; - } - - for (i = 0, j = 0; i < (unsigned)netsizethink; i++, j += 3) { - NewImage->Pal.Palette[j ] = network[i][0]; - NewImage->Pal.Palette[j+1] = network[i][1]; - NewImage->Pal.Palette[j+2] = network[i][2]; - } - - inxbuild(); - for (i = 0, j = 0; j < TempImage->SizeOfData; i++, j += 3) { - NewImage->Data[i] = inxsearch( - TempImage->Data[j], TempImage->Data[j+1], TempImage->Data[j+2]); - } - - ilCloseImage(TempImage); - - return NewImage; -} diff --git a/DevIL/src-IL/src/il_neuquant.cpp b/DevIL/src-IL/src/il_neuquant.cpp new file mode 100644 index 00000000..c00f4a00 --- /dev/null +++ b/DevIL/src-IL/src/il_neuquant.cpp @@ -0,0 +1,462 @@ +/* NeuQuant Neural-Net Quantization Algorithm + * ------------------------------------------ + * + * Copyright (c) 1994 Anthony Dekker + * + * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. + * See "Kohonen neural networks for optimal colour quantization" + * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367. + * for a discussion of the algorithm. + * See also http://www.acm.org/~dekker/NEUQUANT.HTML + * + * Any party obtaining a copy of these files from the author, directly or + * indirectly, is granted, free of charge, a full and unrestricted irrevocable, + * world-wide, paid up, royalty-free, nonexclusive right and license to deal + * in this software and documentation files (the "Software"), including without + * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons who receive + * copies from any such party to do so, with the only requirement being + * that this copyright notice remain intact. + */ + +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// by Denton Woods +// Last modified: 01/04/2009 +// +// Filename: src-IL/src/il_neuquant.c +// +// Description: Heavily modified by Denton Woods. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" + + +// Function definitions +void initnet(ILubyte *thepic, ILint len, ILint sample); +void unbiasnet(); +void inxbuild(); +ILubyte inxsearch(ILint b, ILint g, ILint r); +void learn(); + +// four primes near 500 - assume no image has a length so large +// that it is divisible by all four primes +#define prime1 499 +#define prime2 491 +#define prime3 487 +#define prime4 503 + +#define minpicturebytes (3*prime4) // minimum size for input image + + +// Network Definitions +// ------------------- + +#define netsize 256 // number of colours used +#define maxnetpos (netsizethink-1) +#define netbiasshift 4 // bias for colour values +#define ncycles 100 // no. of learning cycles + +// defs for freq and bias +#define intbiasshift 16 // bias for fractions +#define intbias (((ILint) 1)<>betashift)// beta = 1/1024 +#define betagamma (intbias<<(gammashift-betashift)) + +// defs for decreasing radius factor +#define initrad (netsize>>3) // for 256 cols, radius starts +#define radiusbiasshift 6 // at 32.0 biased by 6 bits +#define radiusbias (((ILint) 1)<>= netbiasshift; + network[i][3] = i; // record colour no + } + return; +} + + +// Insertion sort of network and building of netindex[0..255] (to do after unbias) +// ------------------------------------------------------------------------------- + +void inxbuild() +{ + ILint i,j,smallpos,smallval; + ILint *p,*q; + ILint previouscol,startpos; + + previouscol = 0; + startpos = 0; + for (i=0; i>1; + for (j=previouscol+1; j>1; + for (j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; // really 256 + return; +} + + +// Search for BGR values 0..255 (after net is unbiased) and return colour index +// ---------------------------------------------------------------------------- + +ILubyte inxsearch(ILint b, ILint g, ILint r) +{ + ILint i,j,dist,a,bestd; + ILint *p; + ILint best; + + bestd = 1000; // biggest possible dist is 256*3 + best = -1; + i = netindex[g]; // index on g + j = i-1; // start at netindex[g] and work outwards + + while ((i=0)) { + if (i= bestd) i = netsizethink; // stop iter + else { + i++; + if (dist<0) dist = -dist; + a = p[0] - b; if (a<0) a = -a; + dist += a; + if (dist=0) { + p = network[j]; + dist = g - p[1]; // inx key - reverse dif + if (dist >= bestd) j = -1; // stop iter + else { + j--; + if (dist<0) dist = -dist; + a = p[0] - b; if (a<0) a = -a; + dist += a; + if (dist>(intbiasshift-netbiasshift)); + if (biasdist> betashift); + *f++ -= betafreq; + *p++ += (betafreq<netsizethink) hi=netsizethink; + + j = i+1; + k = i-1; + q = radpower; + while ((jlo)) { + a = (*(++q)); + if (jlo) { + p = network[k]; + *p -= (a*(*p - b)) / alpharadbias; + p++; + *p -= (a*(*p - g)) / alpharadbias; + p++; + *p -= (a*(*p - r)) / alpharadbias; + k--; + } + } + return; +} + + +// Main Learning Loop +// ------------------ + +void learn() +{ + ILint i,j,b,g,r; + ILint radius,rad,alpha,step,delta,samplepixels; + ILubyte *p; + ILubyte *lim; + + alphadec = 30 + ((samplefac-1)/3); + p = thepicture; + lim = thepicture + lengthcount; + samplepixels = lengthcount/(3*samplefac); + delta = samplepixels/ncycles; + alpha = initalpha; + radius = initradius; + + rad = radius >> radiusbiasshift; + if (rad <= 1) rad = 0; + for (i=0; i= lim) p -= lengthcount; + + i++; + if (i%delta == 0) { + alpha -= alpha / alphadec; + radius -= radius / radiusdec; + rad = radius >> radiusbiasshift; + if (rad <= 1) rad = 0; + for (j=0; jData, TempImage->SizeOfData, sample); + learn(); + unbiasnet(); + + NewImage = (ILimage*)icalloc(sizeof(ILimage), 1); + if (NewImage == NULL) { + ilCloseImage(TempImage); + return NULL; + } + NewImage->Data = (ILubyte*)ialloc(TempImage->SizeOfData / 3); + if (NewImage->Data == NULL) { + ilCloseImage(TempImage); + ifree(NewImage); + return NULL; + } + ilCopyImageAttr(NewImage, Image); + NewImage->Bpp = 1; + NewImage->Bps = Image->Width; + NewImage->SizeOfPlane = NewImage->Bps * Image->Height; + NewImage->SizeOfData = NewImage->SizeOfPlane; + NewImage->Format = IL_COLOUR_INDEX; + NewImage->Type = IL_UNSIGNED_BYTE; + + NewImage->Pal.PalSize = netsizethink * 3; + NewImage->Pal.PalType = IL_PAL_BGR24; + NewImage->Pal.Palette = (ILubyte*)ialloc(256*3); + if (NewImage->Pal.Palette == NULL) { + ilCloseImage(TempImage); + ilCloseImage(NewImage); + return NULL; + } + + for (i = 0, j = 0; i < (unsigned)netsizethink; i++, j += 3) { + NewImage->Pal.Palette[j ] = network[i][0]; + NewImage->Pal.Palette[j+1] = network[i][1]; + NewImage->Pal.Palette[j+2] = network[i][2]; + } + + inxbuild(); + for (i = 0, j = 0; j < TempImage->SizeOfData; i++, j += 3) { + NewImage->Data[i] = inxsearch( + TempImage->Data[j], TempImage->Data[j+1], TempImage->Data[j+2]); + } + + ilCloseImage(TempImage); + + return NewImage; +} diff --git a/DevIL/src-IL/src/il_pal.c b/DevIL/src-IL/src/il_pal.c deleted file mode 100644 index c66d5a70..00000000 --- a/DevIL/src-IL/src/il_pal.c +++ /dev/null @@ -1,1111 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/14/2009 -// -// Filename: src-IL/src/il_pal.c -// -// Description: Loads palettes from different file formats -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include "il_pal.h" -#include -#include -#include - - -//! Loads a palette from FileName into the current image's palette. -ILboolean ILAPIENTRY ilLoadPal(ILconst_string FileName) -{ - FILE *f; - ILboolean IsPsp; - char Head[8]; - - if (FileName == NULL) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (iCheckExtension(FileName, IL_TEXT("col"))) { - return ilLoadColPal(FileName); - } - if (iCheckExtension(FileName, IL_TEXT("act"))) { - return ilLoadActPal(FileName); - } - if (iCheckExtension(FileName, IL_TEXT("plt"))) { - return ilLoadPltPal(FileName); - } - -#ifndef _UNICODE - f = fopen(FileName, "rt"); -#else - f = _wfopen(FileName, L"rt"); -#endif//_UNICODE - if (f == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - fread(Head, 1, 8, f); - if (!strncmp(Head, "JASC-PAL", 8)) - IsPsp = IL_TRUE; - else - IsPsp = IL_FALSE; - - fclose(f); - - if (IsPsp) - return ilLoadJascPal(FileName); - return ilLoadHaloPal(FileName); -} - - -//! Loads a Paint Shop Pro formatted palette (.pal) file. -ILboolean ilLoadJascPal(ILconst_string FileName) -{ - FILE *PalFile; - ILuint NumColours, i, c; - ILubyte Buff[BUFFLEN]; - ILboolean Error = IL_FALSE; - ILpal *Pal = &iCurImage->Pal; - - if (!iCheckExtension(FileName, IL_TEXT("pal"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - -#ifndef _UNICODE - PalFile = fopen(FileName, "rt"); -#else - PalFile = _wfopen(FileName, L"rt"); -#endif//_UNICODE - if (PalFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - } - - iFgetw(Buff, BUFFLEN, PalFile); - if (stricmp((const char*)Buff, "JASC-PAL")) { - Error = IL_TRUE; - } - iFgetw(Buff, BUFFLEN, PalFile); - if (stricmp((const char*)Buff, "0100")) { - Error = IL_TRUE; - } - - iFgetw(Buff, BUFFLEN, PalFile); - NumColours = atoi((const char*)Buff); - if (NumColours == 0 || Error) { - ilSetError(IL_INVALID_FILE_HEADER); - fclose(PalFile); - return IL_FALSE; - } - - Pal->PalSize = NumColours * PALBPP; - Pal->PalType = IL_PAL_RGB24; - Pal->Palette = (ILubyte*)ialloc(NumColours * PALBPP); - if (Pal->Palette == NULL) { - fclose(PalFile); - return IL_FALSE; - } - - for (i = 0; i < NumColours; i++) { - for (c = 0; c < PALBPP; c++) { - iFgetw(Buff, BUFFLEN, PalFile); - Pal->Palette[i * PALBPP + c] = atoi((const char*)Buff); - } - } - - fclose(PalFile); - - return IL_TRUE; -} - - -// File Get Word -// MaxLen must be greater than 1, because the trailing NULL is always stored. -char *iFgetw(ILubyte *Buff, ILint MaxLen, FILE *File) -{ - ILint Temp; - ILint i; - - if (Buff == NULL || File == NULL || MaxLen < 2) { - ilSetError(IL_INVALID_PARAM); - return NULL; - } - - for (i = 0; i < MaxLen - 1; i++) { - Temp = fgetc(File); - if (Temp == '\n' || Temp == '\0' || Temp == IL_EOF || feof(File)) { - break; - } - - if (Temp == ' ') { - while (Temp == ' ') { // Just to get rid of any extra spaces - Temp = fgetc(File); - } - fseek(File, -1, IL_SEEK_CUR); // Go back one - break; - } - - if (!isprint(Temp)) { // Skips any non-printing characters - while (!isprint(Temp)) { - Temp = fgetc(File); - } - fseek(File, -1, IL_SEEK_CUR); - break; - } - - Buff[i] = Temp; - } - - Buff[i] = '\0'; - return (char *)Buff; -} - - -ILboolean ILAPIENTRY ilSavePal(ILconst_string FileName) -{ - ILstring Ext = iGetExtension(FileName); - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - -#ifndef _UNICODE - if (FileName == NULL || strlen(FileName) < 1 || Ext == NULL) { -#else - if (FileName == NULL || wcslen(FileName) < 1 || Ext == NULL) { -#endif//_UNICODE - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType == IL_PAL_NONE) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iStrCmp(Ext, IL_TEXT("pal"))) { - return ilSaveJascPal(FileName); - } - - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; -} - - -//! Saves a Paint Shop Pro formatted palette (.pal) file. -ILboolean ilSaveJascPal(ILconst_string FileName) -{ - FILE *PalFile; - ILuint i, PalBpp, NumCols = ilGetInteger(IL_PALETTE_NUM_COLS); - ILubyte *CurPal; - - if (iCurImage == NULL || NumCols == 0 || NumCols > 256) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - -#ifndef _UNICODE - if (FileName == NULL || strlen(FileName) < 5) { -#else - if (FileName == NULL || wcslen(FileName) < 5) { -#endif//_UNICODE - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - if (!iCheckExtension(FileName, IL_TEXT("pal"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - // Create a copy of the current palette and convert it to RGB24 format. - CurPal = iCurImage->Pal.Palette; - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (!iCurImage->Pal.Palette) { - iCurImage->Pal.Palette = CurPal; - return IL_FALSE; - } - - memcpy(iCurImage->Pal.Palette, CurPal, iCurImage->Pal.PalSize); - if (!ilConvertPal(IL_PAL_RGB24)) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = CurPal; - return IL_FALSE; - } - -#ifndef _UNICODE - PalFile = fopen(FileName, "wt"); -#else - PalFile = _wfopen(FileName, L"wt"); -#endif//_UNICODE - if (!PalFile) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - // Header needed on all .pal files - fputs("JASC-PAL\n0100\n256\n", PalFile); - - PalBpp = ilGetBppPal(iCurImage->Pal.PalType); - for (i = 0; i < iCurImage->Pal.PalSize; i += PalBpp) { - fprintf(PalFile, "%d %d %d\n", - iCurImage->Pal.Palette[i], iCurImage->Pal.Palette[i+1], iCurImage->Pal.Palette[i+2]); - } - - NumCols = 256 - NumCols; - for (i = 0; i < NumCols; i++) { - fprintf(PalFile, "0 0 0\n"); - } - - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = CurPal; - - fclose(PalFile); - - return IL_TRUE; -} - - -//! Loads a Halo formatted palette (.pal) file. -ILboolean ilLoadHaloPal(ILconst_string FileName) -{ - ILHANDLE HaloFile; - HALOHEAD HaloHead; - ILushort *TempPal; - ILuint i, Size; - - if (!iCheckExtension(FileName, IL_TEXT("pal"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - HaloFile = iopenr(FileName); - if (HaloFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - if (iread(&HaloHead, sizeof(HALOHEAD), 1) != 1) - return IL_FALSE; - - if (HaloHead.Id != 'A' + ('H' << 8) || HaloHead.Version != 0xe3) { - icloser(HaloFile); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - Size = (HaloHead.MaxIndex + 1) * 3; - TempPal = (ILushort*)ialloc(Size * sizeof(ILushort)); - if (TempPal == NULL) { - icloser(HaloFile); - return IL_FALSE; - } - - if (iread(TempPal, sizeof(ILushort), Size) != Size) { - icloser(HaloFile); - ifree(TempPal); - return IL_FALSE; - } - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - } - iCurImage->Pal.PalType = IL_PAL_RGB24; - iCurImage->Pal.PalSize = Size; - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) { - icloser(HaloFile); - return IL_FALSE; - } - - for (i = 0; i < iCurImage->Pal.PalSize; i++, TempPal++) { - iCurImage->Pal.Palette[i] = (ILubyte)*TempPal; - } - TempPal -= iCurImage->Pal.PalSize; - ifree(TempPal); - - icloser(HaloFile); - - return IL_TRUE; -} - - -// Hasn't been tested -// @TODO: Test the thing! - -//! Loads a .col palette file -ILboolean ilLoadColPal(ILconst_string FileName) -{ - ILuint RealFileSize, FileSize; - ILushort Version; - ILHANDLE ColFile; - - if (!iCheckExtension(FileName, IL_TEXT("col"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - ColFile = iopenr(FileName); - if (ColFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - } - - iseek(0, IL_SEEK_END); - RealFileSize = ftell((FILE*)ColFile); - iseek(0, IL_SEEK_SET); - - if (RealFileSize > 768) { // has a header - fread(&FileSize, 4, 1, (FILE*)ColFile); - if ((FileSize - 8) % 3 != 0) { // check to make sure an even multiple of 3! - icloser(ColFile); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - if (iread(&Version, 2, 1) != 1) { - icloser(ColFile); - return IL_FALSE; - } - if (Version != 0xB123) { - icloser(ColFile); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - if (iread(&Version, 2, 1) != 1) { - icloser(ColFile); - return IL_FALSE; - } - if (Version != 0) { - icloser(ColFile); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - } - - iCurImage->Pal.Palette = (ILubyte*)ialloc(768); - if (iCurImage->Pal.Palette == NULL) { - icloser(ColFile); - return IL_FALSE; - } - - if (iread(iCurImage->Pal.Palette, 1, 768) != 768) { - icloser(ColFile); - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - return IL_FALSE; - } - - iCurImage->Pal.PalSize = 768; - iCurImage->Pal.PalType = IL_PAL_RGB24; - - icloser(ColFile); - - return IL_TRUE; -} - - -//! Loads an .act palette file. -ILboolean ilLoadActPal(ILconst_string FileName) -{ - ILHANDLE ActFile; - - if (!iCheckExtension(FileName, IL_TEXT("act"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - ActFile = iopenr(FileName); - if (ActFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - } - - iCurImage->Pal.PalType = IL_PAL_RGB24; - iCurImage->Pal.PalSize = 768; - iCurImage->Pal.Palette = (ILubyte*)ialloc(768); - if (!iCurImage->Pal.Palette) { - icloser(ActFile); - return IL_FALSE; - } - - if (iread(iCurImage->Pal.Palette, 1, 768) != 768) { - icloser(ActFile); - return IL_FALSE; - } - - icloser(ActFile); - - return IL_TRUE; -} - - -//! Loads an .plt palette file. -ILboolean ilLoadPltPal(ILconst_string FileName) -{ - ILHANDLE PltFile; - - if (!iCheckExtension(FileName, IL_TEXT("plt"))) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - } - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - PltFile = iopenr(FileName); - if (PltFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - } - - iCurImage->Pal.PalSize = GetLittleUInt(); - if (iCurImage->Pal.PalSize == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - iCurImage->Pal.PalType = IL_PAL_RGB24; - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (!iCurImage->Pal.Palette) { - icloser(PltFile); - return IL_FALSE; - } - - if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) { - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = NULL; - icloser(PltFile); - return IL_FALSE; - } - - icloser(PltFile); - - return IL_TRUE; -} - - -// Assumes that Dest has nothing in it. -ILboolean iCopyPalette(ILpal *Dest, ILpal *Src) -{ - if (Src->Palette == NULL || Src->PalSize == 0) - return IL_FALSE; - - Dest->Palette = (ILubyte*)ialloc(Src->PalSize); - if (Dest->Palette == NULL) - return IL_FALSE; - - memcpy(Dest->Palette, Src->Palette, Src->PalSize); - - Dest->PalSize = Src->PalSize; - Dest->PalType = Src->PalType; - - return IL_TRUE; -} - - -ILAPI ILpal* ILAPIENTRY iCopyPal() -{ - ILpal *Pal; - - if (iCurImage == NULL || iCurImage->Pal.Palette == NULL || - iCurImage->Pal.PalSize == 0 || iCurImage->Pal.PalType == IL_PAL_NONE) { - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - - Pal = (ILpal*)ialloc(sizeof(ILpal)); - if (Pal == NULL) { - return NULL; - } - if (!iCopyPalette(Pal, &iCurImage->Pal)) { - ifree(Pal); - return NULL; - } - - return Pal; -} - - -// Converts the palette to the DestFormat format. -ILAPI ILpal* ILAPIENTRY iConvertPal(ILpal *Pal, ILenum DestFormat) -{ - ILpal *NewPal = NULL; - ILuint i, j, NewPalSize; - - // Checks to see if the current image is valid and has a palette - if (Pal == NULL || Pal->PalSize == 0 || Pal->Palette == NULL || Pal->PalType == IL_PAL_NONE) { - ilSetError(IL_ILLEGAL_OPERATION); - return NULL; - } - - /*if (Pal->PalType == DestFormat) { - return NULL; - }*/ - - NewPal = (ILpal*)ialloc(sizeof(ILpal)); - if (NewPal == NULL) { - return NULL; - } - NewPal->PalSize = Pal->PalSize; - NewPal->PalType = Pal->PalType; - - switch (DestFormat) - { - case IL_PAL_RGB24: - case IL_PAL_BGR24: - switch (Pal->PalType) - { - case IL_PAL_RGB24: - NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_BGR24) { - j = ilGetBppPal(Pal->PalType); - for (i = 0; i < Pal->PalSize; i += j) { - NewPal->Palette[i] = Pal->Palette[i+2]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i]; - } - } - else { - memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); - } - NewPal->PalType = DestFormat; - break; - - case IL_PAL_BGR24: - NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_RGB24) { - j = ilGetBppPal(Pal->PalType); - for (i = 0; i < Pal->PalSize; i += j) { - NewPal->Palette[i] = Pal->Palette[i+2]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i]; - } - } - else { - memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); - } - NewPal->PalType = DestFormat; - break; - - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - NewPalSize = (ILuint)((ILfloat)Pal->PalSize * 3.0f / 4.0f); - NewPal->Palette = (ILubyte*)ialloc(NewPalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_RGB24) { - for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { - NewPal->Palette[j] = Pal->Palette[i+2]; - NewPal->Palette[j+1] = Pal->Palette[i+1]; - NewPal->Palette[j+2] = Pal->Palette[i]; - } - } - else { - for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { - NewPal->Palette[j] = Pal->Palette[i]; - NewPal->Palette[j+1] = Pal->Palette[i+1]; - NewPal->Palette[j+2] = Pal->Palette[i+2]; - } - } - NewPal->PalSize = NewPalSize; - NewPal->PalType = DestFormat; - break; - - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - NewPalSize = (ILuint)((ILfloat)Pal->PalSize * 3.0f / 4.0f); - NewPal->Palette = (ILubyte*)ialloc(NewPalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_RGB24) { - for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { - NewPal->Palette[j] = Pal->Palette[i]; - NewPal->Palette[j+1] = Pal->Palette[i+1]; - NewPal->Palette[j+2] = Pal->Palette[i+2]; - } - } - else { - for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { - NewPal->Palette[j] = Pal->Palette[i+2]; - NewPal->Palette[j+1] = Pal->Palette[i+1]; - NewPal->Palette[j+2] = Pal->Palette[i]; - } - } - NewPal->PalSize = NewPalSize; - NewPal->PalType = DestFormat; - break; - - default: - ilSetError(IL_INVALID_PARAM); - return NULL; - } - break; - - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - switch (Pal->PalType) - { - case IL_PAL_RGB24: - case IL_PAL_BGR24: - NewPalSize = Pal->PalSize * 4 / 3; - NewPal->Palette = (ILubyte*)ialloc(NewPalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if ((Pal->PalType == IL_PAL_BGR24 && (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32)) || - (Pal->PalType == IL_PAL_RGB24 && (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32))) { - for (i = 0, j = 0; i < Pal->PalSize; i += 3, j += 4) { - NewPal->Palette[j] = Pal->Palette[i+2]; - NewPal->Palette[j+1] = Pal->Palette[i+1]; - NewPal->Palette[j+2] = Pal->Palette[i]; - NewPal->Palette[j+3] = 255; - } - } - else { - for (i = 0, j = 0; i < Pal->PalSize; i += 3, j += 4) { - NewPal->Palette[j] = Pal->Palette[i]; - NewPal->Palette[j+1] = Pal->Palette[i+1]; - NewPal->Palette[j+2] = Pal->Palette[i+2]; - NewPal->Palette[j+3] = 255; - } - } - NewPal->PalSize = NewPalSize; - NewPal->PalType = DestFormat; - break; - - case IL_PAL_RGB32: - NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - - if (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32) { - for (i = 0; i < Pal->PalSize; i += 4) { - NewPal->Palette[i] = Pal->Palette[i+2]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i]; - NewPal->Palette[i+3] = 255; - } - } - else { - for (i = 0; i < Pal->PalSize; i += 4) { - NewPal->Palette[i] = Pal->Palette[i]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i+2]; - NewPal->Palette[i+3] = 255; - } - } - NewPal->PalType = DestFormat; - break; - - case IL_PAL_RGBA32: - NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32) { - for (i = 0; i < Pal->PalSize; i += 4) { - NewPal->Palette[i] = Pal->Palette[i+2]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i]; - NewPal->Palette[i+3] = Pal->Palette[i+3]; - } - } - else { - memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); - } - NewPal->PalType = DestFormat; - break; - - case IL_PAL_BGR32: - NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32) { - for (i = 0; i < Pal->PalSize; i += 4) { - NewPal->Palette[i] = Pal->Palette[i+2]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i]; - NewPal->Palette[i+3] = 255; - } - } - else { - for (i = 0; i < Pal->PalSize; i += 4) { - NewPal->Palette[i] = Pal->Palette[i]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i+2]; - NewPal->Palette[i+3] = 255; - } - } - NewPal->PalType = DestFormat; - break; - - case IL_PAL_BGRA32: - NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); - if (NewPal->Palette == NULL) - goto alloc_error; - if (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32) { - for (i = 0; i < Pal->PalSize; i += 4) { - NewPal->Palette[i] = Pal->Palette[i+2]; - NewPal->Palette[i+1] = Pal->Palette[i+1]; - NewPal->Palette[i+2] = Pal->Palette[i]; - NewPal->Palette[i+3] = Pal->Palette[i+3]; - } - } - else { - memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); - } - NewPal->PalType = DestFormat; - break; - - default: - ilSetError(IL_INVALID_PARAM); - return NULL; - } - break; - - - default: - ilSetError(IL_INVALID_PARAM); - return NULL; - } - - NewPal->PalType = DestFormat; - - return NewPal; - -alloc_error: - ifree(NewPal); - return NULL; -} - - -//! Converts the current image to the DestFormat format. -ILboolean ILAPIENTRY ilConvertPal(ILenum DestFormat) -{ - ILpal *Pal; - - if (iCurImage == NULL || iCurImage->Pal.Palette == NULL || - iCurImage->Pal.PalSize == 0 || iCurImage->Pal.PalType == IL_PAL_NONE) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Pal = iConvertPal(&iCurImage->Pal, DestFormat); - if (Pal == NULL) - return IL_FALSE; - - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.PalSize = Pal->PalSize; - iCurImage->Pal.PalType = Pal->PalType; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(Pal->PalSize); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - memcpy(iCurImage->Pal.Palette, Pal->Palette, Pal->PalSize); - - ifree(Pal->Palette); - ifree(Pal); - - return IL_TRUE; -} - - -// Sets the current palette. -ILAPI void ILAPIENTRY ilSetPal(ILpal *Pal) -{ - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - } - - if (Pal->Palette && Pal->PalSize && Pal->PalType != IL_PAL_NONE) { - iCurImage->Pal.Palette = (ILubyte*)ialloc(Pal->PalSize); - if (iCurImage->Pal.Palette == NULL) - return; - memcpy(iCurImage->Pal.Palette, Pal->Palette, Pal->PalSize); - iCurImage->Pal.PalSize = Pal->PalSize; - iCurImage->Pal.PalType = Pal->PalType; - } - else { - iCurImage->Pal.Palette = NULL; - iCurImage->Pal.PalSize = 0; - iCurImage->Pal.PalType = IL_PAL_NONE; - } - - return; -} - - -ILuint CurSort = 0; -typedef struct COL_CUBE -{ - ILubyte Min[3]; - ILubyte Val[3]; - ILubyte Max[3]; -} COL_CUBE; - -int sort_func(void *e1, void *e2) -{ - return ((COL_CUBE*)e1)->Val[CurSort] - ((COL_CUBE*)e2)->Val[CurSort]; -} - - -ILboolean ILAPIENTRY ilApplyPal(ILconst_string FileName) -{ - ILimage Image, *CurImage = iCurImage; - ILubyte *NewData; - ILuint *PalInfo, NumColours, NumPix, MaxDist, DistEntry=0, i, j; - ILint Dist1, Dist2, Dist3; - ILboolean Same; - ILenum Origin; -// COL_CUBE *Cubes; - - if( iCurImage == NULL || (iCurImage->Format != IL_BYTE || iCurImage->Format != IL_UNSIGNED_BYTE) ) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - NewData = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth); - if (NewData == NULL) { - return IL_FALSE; - } - - iCurImage = &Image; - imemclear(&Image, sizeof(ILimage)); - // IL_PAL_RGB24, because we don't want to make parts transparent that shouldn't be. - if (!ilLoadPal(FileName) || !ilConvertPal(IL_PAL_RGB24)) { - ifree(NewData); - iCurImage = CurImage; - return IL_FALSE; - } - - NumColours = Image.Pal.PalSize / 3; // RGB24 is 3 bytes per entry. - PalInfo = (ILuint*)ialloc(NumColours * sizeof(ILuint)); - if (PalInfo == NULL) { - ifree(NewData); - iCurImage = CurImage; - return IL_FALSE; - } - - NumPix = CurImage->SizeOfData / ilGetBppFormat(CurImage->Format); - switch (CurImage->Format) - { - case IL_COLOUR_INDEX: - iCurImage = CurImage; - if (!ilConvertPal(IL_PAL_RGB24)) { - ifree(NewData); - ifree(PalInfo); - return IL_FALSE; - } - - NumPix = iCurImage->Pal.PalSize / ilGetBppPal(iCurImage->Pal.PalType); - for (i = 0; i < NumPix; i++) { - for (j = 0; j < Image.Pal.PalSize; j += 3) { - // No need to perform a sqrt. - Dist1 = (ILint)iCurImage->Pal.Palette[i] - (ILint)Image.Pal.Palette[j]; - Dist2 = (ILint)iCurImage->Pal.Palette[i+1] - (ILint)Image.Pal.Palette[j+1]; - Dist3 = (ILint)iCurImage->Pal.Palette[i+2] - (ILint)Image.Pal.Palette[j+2]; - PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3; - } - MaxDist = UINT_MAX; - DistEntry = 0; - for (j = 0; j < NumColours; j++) { - if (PalInfo[j] < MaxDist) { - DistEntry = j; - MaxDist = PalInfo[j]; - } - } - iCurImage->Pal.Palette[i] = DistEntry; - } - - for (i = 0; i < iCurImage->SizeOfData; i++) { - NewData[i] = iCurImage->Pal.Palette[iCurImage->Data[i]]; - } - break; - case IL_RGB: - case IL_RGBA: - /*Cube = (COL_CUBE*)ialloc(NumColours * sizeof(COL_CUBE)); - // @TODO: Check if ialloc failed here! - for (i = 0; i < NumColours; i++) - memcpy(&Cubes[i].Val, Image.Pal.Palette[i * 3], 3); - for (j = 0; j < 3; j++) { - qsort(Cubes, NumColours, sizeof(COL_CUBE), sort_func); - Cubes[0].Min = 0; - Cubes[NumColours-1] = UCHAR_MAX; - NumColours--; - for (i = 1; i < NumColours; i++) { - Cubes[i].Min[CurSort] = Cubes[i-1].Val[CurSort] + 1; - Cubes[i-1].Max[CurSort] = Cubes[i].Val[CurSort] - 1; - } - CurSort++; - NumColours++; - }*/ - for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) { - Same = IL_TRUE; - if (i != 0) { - for (j = 0; j < CurImage->Bpp; j++) { - if (CurImage->Data[i-CurImage->Bpp+j] != CurImage->Data[i+j]) { - Same = IL_FALSE; - break; - } - } - } - if (Same) { - NewData[i / CurImage->Bpp] = DistEntry; - continue; - } - for (j = 0; j < Image.Pal.PalSize; j += 3) { - // No need to perform a sqrt. - Dist1 = (ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j]; - Dist2 = (ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j+1]; - Dist3 = (ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j+2]; - PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3; - } - MaxDist = UINT_MAX; - DistEntry = 0; - for (j = 0; j < NumColours; j++) { - if (PalInfo[j] < MaxDist) { - DistEntry = j; - MaxDist = PalInfo[j]; - } - } - NewData[i / CurImage->Bpp] = DistEntry; - } - - break; - - case IL_BGR: - case IL_BGRA: - for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) { - for (j = 0; j < NumColours; j++) { - // No need to perform a sqrt. - PalInfo[j] = ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) * - ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) + - ((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) * - ((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) + - ((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]) * - ((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]); - } - MaxDist = UINT_MAX; - DistEntry = 0; - for (j = 0; j < NumColours; j++) { - if (PalInfo[j] < MaxDist) { - DistEntry = j; - MaxDist = PalInfo[j]; - } - } - NewData[i / CurImage->Bpp] = DistEntry; - } - - break; - - case IL_LUMINANCE: - case IL_LUMINANCE_ALPHA: - for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp ) { - for (j = 0; j < NumColours; j++) { - // No need to perform a sqrt. - PalInfo[j] = ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) * - ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) + - ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) * - ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) + - ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]) * - ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]); - } - MaxDist = UINT_MAX; - DistEntry = 0; - for (j = 0; j < NumColours; j++) { - if (PalInfo[j] < MaxDist) { - DistEntry = j; - MaxDist = PalInfo[j]; - } - } - NewData[i] = DistEntry; - } - - break; - - default: // Should be no other! - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - iCurImage = CurImage; - Origin = iCurImage->Origin; - if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, 1, - IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NewData)) { - ifree(Image.Pal.Palette); - ifree(PalInfo); - ifree(NewData); - return IL_FALSE; - } - iCurImage->Origin = Origin; - - iCurImage->Pal.Palette = Image.Pal.Palette; - iCurImage->Pal.PalSize = Image.Pal.PalSize; - iCurImage->Pal.PalType = Image.Pal.PalType; - ifree(PalInfo); - ifree(NewData); - - return IL_TRUE; -} diff --git a/DevIL/src-IL/src/il_pal.cpp b/DevIL/src-IL/src/il_pal.cpp new file mode 100644 index 00000000..c66d5a70 --- /dev/null +++ b/DevIL/src-IL/src/il_pal.cpp @@ -0,0 +1,1111 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/14/2009 +// +// Filename: src-IL/src/il_pal.c +// +// Description: Loads palettes from different file formats +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include "il_pal.h" +#include +#include +#include + + +//! Loads a palette from FileName into the current image's palette. +ILboolean ILAPIENTRY ilLoadPal(ILconst_string FileName) +{ + FILE *f; + ILboolean IsPsp; + char Head[8]; + + if (FileName == NULL) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (iCheckExtension(FileName, IL_TEXT("col"))) { + return ilLoadColPal(FileName); + } + if (iCheckExtension(FileName, IL_TEXT("act"))) { + return ilLoadActPal(FileName); + } + if (iCheckExtension(FileName, IL_TEXT("plt"))) { + return ilLoadPltPal(FileName); + } + +#ifndef _UNICODE + f = fopen(FileName, "rt"); +#else + f = _wfopen(FileName, L"rt"); +#endif//_UNICODE + if (f == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + fread(Head, 1, 8, f); + if (!strncmp(Head, "JASC-PAL", 8)) + IsPsp = IL_TRUE; + else + IsPsp = IL_FALSE; + + fclose(f); + + if (IsPsp) + return ilLoadJascPal(FileName); + return ilLoadHaloPal(FileName); +} + + +//! Loads a Paint Shop Pro formatted palette (.pal) file. +ILboolean ilLoadJascPal(ILconst_string FileName) +{ + FILE *PalFile; + ILuint NumColours, i, c; + ILubyte Buff[BUFFLEN]; + ILboolean Error = IL_FALSE; + ILpal *Pal = &iCurImage->Pal; + + if (!iCheckExtension(FileName, IL_TEXT("pal"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + +#ifndef _UNICODE + PalFile = fopen(FileName, "rt"); +#else + PalFile = _wfopen(FileName, L"rt"); +#endif//_UNICODE + if (PalFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + } + + iFgetw(Buff, BUFFLEN, PalFile); + if (stricmp((const char*)Buff, "JASC-PAL")) { + Error = IL_TRUE; + } + iFgetw(Buff, BUFFLEN, PalFile); + if (stricmp((const char*)Buff, "0100")) { + Error = IL_TRUE; + } + + iFgetw(Buff, BUFFLEN, PalFile); + NumColours = atoi((const char*)Buff); + if (NumColours == 0 || Error) { + ilSetError(IL_INVALID_FILE_HEADER); + fclose(PalFile); + return IL_FALSE; + } + + Pal->PalSize = NumColours * PALBPP; + Pal->PalType = IL_PAL_RGB24; + Pal->Palette = (ILubyte*)ialloc(NumColours * PALBPP); + if (Pal->Palette == NULL) { + fclose(PalFile); + return IL_FALSE; + } + + for (i = 0; i < NumColours; i++) { + for (c = 0; c < PALBPP; c++) { + iFgetw(Buff, BUFFLEN, PalFile); + Pal->Palette[i * PALBPP + c] = atoi((const char*)Buff); + } + } + + fclose(PalFile); + + return IL_TRUE; +} + + +// File Get Word +// MaxLen must be greater than 1, because the trailing NULL is always stored. +char *iFgetw(ILubyte *Buff, ILint MaxLen, FILE *File) +{ + ILint Temp; + ILint i; + + if (Buff == NULL || File == NULL || MaxLen < 2) { + ilSetError(IL_INVALID_PARAM); + return NULL; + } + + for (i = 0; i < MaxLen - 1; i++) { + Temp = fgetc(File); + if (Temp == '\n' || Temp == '\0' || Temp == IL_EOF || feof(File)) { + break; + } + + if (Temp == ' ') { + while (Temp == ' ') { // Just to get rid of any extra spaces + Temp = fgetc(File); + } + fseek(File, -1, IL_SEEK_CUR); // Go back one + break; + } + + if (!isprint(Temp)) { // Skips any non-printing characters + while (!isprint(Temp)) { + Temp = fgetc(File); + } + fseek(File, -1, IL_SEEK_CUR); + break; + } + + Buff[i] = Temp; + } + + Buff[i] = '\0'; + return (char *)Buff; +} + + +ILboolean ILAPIENTRY ilSavePal(ILconst_string FileName) +{ + ILstring Ext = iGetExtension(FileName); + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + +#ifndef _UNICODE + if (FileName == NULL || strlen(FileName) < 1 || Ext == NULL) { +#else + if (FileName == NULL || wcslen(FileName) < 1 || Ext == NULL) { +#endif//_UNICODE + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType == IL_PAL_NONE) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iStrCmp(Ext, IL_TEXT("pal"))) { + return ilSaveJascPal(FileName); + } + + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; +} + + +//! Saves a Paint Shop Pro formatted palette (.pal) file. +ILboolean ilSaveJascPal(ILconst_string FileName) +{ + FILE *PalFile; + ILuint i, PalBpp, NumCols = ilGetInteger(IL_PALETTE_NUM_COLS); + ILubyte *CurPal; + + if (iCurImage == NULL || NumCols == 0 || NumCols > 256) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + +#ifndef _UNICODE + if (FileName == NULL || strlen(FileName) < 5) { +#else + if (FileName == NULL || wcslen(FileName) < 5) { +#endif//_UNICODE + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + if (!iCheckExtension(FileName, IL_TEXT("pal"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + // Create a copy of the current palette and convert it to RGB24 format. + CurPal = iCurImage->Pal.Palette; + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (!iCurImage->Pal.Palette) { + iCurImage->Pal.Palette = CurPal; + return IL_FALSE; + } + + memcpy(iCurImage->Pal.Palette, CurPal, iCurImage->Pal.PalSize); + if (!ilConvertPal(IL_PAL_RGB24)) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = CurPal; + return IL_FALSE; + } + +#ifndef _UNICODE + PalFile = fopen(FileName, "wt"); +#else + PalFile = _wfopen(FileName, L"wt"); +#endif//_UNICODE + if (!PalFile) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + // Header needed on all .pal files + fputs("JASC-PAL\n0100\n256\n", PalFile); + + PalBpp = ilGetBppPal(iCurImage->Pal.PalType); + for (i = 0; i < iCurImage->Pal.PalSize; i += PalBpp) { + fprintf(PalFile, "%d %d %d\n", + iCurImage->Pal.Palette[i], iCurImage->Pal.Palette[i+1], iCurImage->Pal.Palette[i+2]); + } + + NumCols = 256 - NumCols; + for (i = 0; i < NumCols; i++) { + fprintf(PalFile, "0 0 0\n"); + } + + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = CurPal; + + fclose(PalFile); + + return IL_TRUE; +} + + +//! Loads a Halo formatted palette (.pal) file. +ILboolean ilLoadHaloPal(ILconst_string FileName) +{ + ILHANDLE HaloFile; + HALOHEAD HaloHead; + ILushort *TempPal; + ILuint i, Size; + + if (!iCheckExtension(FileName, IL_TEXT("pal"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + HaloFile = iopenr(FileName); + if (HaloFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + if (iread(&HaloHead, sizeof(HALOHEAD), 1) != 1) + return IL_FALSE; + + if (HaloHead.Id != 'A' + ('H' << 8) || HaloHead.Version != 0xe3) { + icloser(HaloFile); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + Size = (HaloHead.MaxIndex + 1) * 3; + TempPal = (ILushort*)ialloc(Size * sizeof(ILushort)); + if (TempPal == NULL) { + icloser(HaloFile); + return IL_FALSE; + } + + if (iread(TempPal, sizeof(ILushort), Size) != Size) { + icloser(HaloFile); + ifree(TempPal); + return IL_FALSE; + } + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + } + iCurImage->Pal.PalType = IL_PAL_RGB24; + iCurImage->Pal.PalSize = Size; + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) { + icloser(HaloFile); + return IL_FALSE; + } + + for (i = 0; i < iCurImage->Pal.PalSize; i++, TempPal++) { + iCurImage->Pal.Palette[i] = (ILubyte)*TempPal; + } + TempPal -= iCurImage->Pal.PalSize; + ifree(TempPal); + + icloser(HaloFile); + + return IL_TRUE; +} + + +// Hasn't been tested +// @TODO: Test the thing! + +//! Loads a .col palette file +ILboolean ilLoadColPal(ILconst_string FileName) +{ + ILuint RealFileSize, FileSize; + ILushort Version; + ILHANDLE ColFile; + + if (!iCheckExtension(FileName, IL_TEXT("col"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + ColFile = iopenr(FileName); + if (ColFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + } + + iseek(0, IL_SEEK_END); + RealFileSize = ftell((FILE*)ColFile); + iseek(0, IL_SEEK_SET); + + if (RealFileSize > 768) { // has a header + fread(&FileSize, 4, 1, (FILE*)ColFile); + if ((FileSize - 8) % 3 != 0) { // check to make sure an even multiple of 3! + icloser(ColFile); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + if (iread(&Version, 2, 1) != 1) { + icloser(ColFile); + return IL_FALSE; + } + if (Version != 0xB123) { + icloser(ColFile); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + if (iread(&Version, 2, 1) != 1) { + icloser(ColFile); + return IL_FALSE; + } + if (Version != 0) { + icloser(ColFile); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + } + + iCurImage->Pal.Palette = (ILubyte*)ialloc(768); + if (iCurImage->Pal.Palette == NULL) { + icloser(ColFile); + return IL_FALSE; + } + + if (iread(iCurImage->Pal.Palette, 1, 768) != 768) { + icloser(ColFile); + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + return IL_FALSE; + } + + iCurImage->Pal.PalSize = 768; + iCurImage->Pal.PalType = IL_PAL_RGB24; + + icloser(ColFile); + + return IL_TRUE; +} + + +//! Loads an .act palette file. +ILboolean ilLoadActPal(ILconst_string FileName) +{ + ILHANDLE ActFile; + + if (!iCheckExtension(FileName, IL_TEXT("act"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + ActFile = iopenr(FileName); + if (ActFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + } + + iCurImage->Pal.PalType = IL_PAL_RGB24; + iCurImage->Pal.PalSize = 768; + iCurImage->Pal.Palette = (ILubyte*)ialloc(768); + if (!iCurImage->Pal.Palette) { + icloser(ActFile); + return IL_FALSE; + } + + if (iread(iCurImage->Pal.Palette, 1, 768) != 768) { + icloser(ActFile); + return IL_FALSE; + } + + icloser(ActFile); + + return IL_TRUE; +} + + +//! Loads an .plt palette file. +ILboolean ilLoadPltPal(ILconst_string FileName) +{ + ILHANDLE PltFile; + + if (!iCheckExtension(FileName, IL_TEXT("plt"))) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + } + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + PltFile = iopenr(FileName); + if (PltFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + } + + iCurImage->Pal.PalSize = GetLittleUInt(); + if (iCurImage->Pal.PalSize == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + iCurImage->Pal.PalType = IL_PAL_RGB24; + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (!iCurImage->Pal.Palette) { + icloser(PltFile); + return IL_FALSE; + } + + if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) { + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = NULL; + icloser(PltFile); + return IL_FALSE; + } + + icloser(PltFile); + + return IL_TRUE; +} + + +// Assumes that Dest has nothing in it. +ILboolean iCopyPalette(ILpal *Dest, ILpal *Src) +{ + if (Src->Palette == NULL || Src->PalSize == 0) + return IL_FALSE; + + Dest->Palette = (ILubyte*)ialloc(Src->PalSize); + if (Dest->Palette == NULL) + return IL_FALSE; + + memcpy(Dest->Palette, Src->Palette, Src->PalSize); + + Dest->PalSize = Src->PalSize; + Dest->PalType = Src->PalType; + + return IL_TRUE; +} + + +ILAPI ILpal* ILAPIENTRY iCopyPal() +{ + ILpal *Pal; + + if (iCurImage == NULL || iCurImage->Pal.Palette == NULL || + iCurImage->Pal.PalSize == 0 || iCurImage->Pal.PalType == IL_PAL_NONE) { + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + + Pal = (ILpal*)ialloc(sizeof(ILpal)); + if (Pal == NULL) { + return NULL; + } + if (!iCopyPalette(Pal, &iCurImage->Pal)) { + ifree(Pal); + return NULL; + } + + return Pal; +} + + +// Converts the palette to the DestFormat format. +ILAPI ILpal* ILAPIENTRY iConvertPal(ILpal *Pal, ILenum DestFormat) +{ + ILpal *NewPal = NULL; + ILuint i, j, NewPalSize; + + // Checks to see if the current image is valid and has a palette + if (Pal == NULL || Pal->PalSize == 0 || Pal->Palette == NULL || Pal->PalType == IL_PAL_NONE) { + ilSetError(IL_ILLEGAL_OPERATION); + return NULL; + } + + /*if (Pal->PalType == DestFormat) { + return NULL; + }*/ + + NewPal = (ILpal*)ialloc(sizeof(ILpal)); + if (NewPal == NULL) { + return NULL; + } + NewPal->PalSize = Pal->PalSize; + NewPal->PalType = Pal->PalType; + + switch (DestFormat) + { + case IL_PAL_RGB24: + case IL_PAL_BGR24: + switch (Pal->PalType) + { + case IL_PAL_RGB24: + NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_BGR24) { + j = ilGetBppPal(Pal->PalType); + for (i = 0; i < Pal->PalSize; i += j) { + NewPal->Palette[i] = Pal->Palette[i+2]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i]; + } + } + else { + memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); + } + NewPal->PalType = DestFormat; + break; + + case IL_PAL_BGR24: + NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_RGB24) { + j = ilGetBppPal(Pal->PalType); + for (i = 0; i < Pal->PalSize; i += j) { + NewPal->Palette[i] = Pal->Palette[i+2]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i]; + } + } + else { + memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); + } + NewPal->PalType = DestFormat; + break; + + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + NewPalSize = (ILuint)((ILfloat)Pal->PalSize * 3.0f / 4.0f); + NewPal->Palette = (ILubyte*)ialloc(NewPalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_RGB24) { + for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { + NewPal->Palette[j] = Pal->Palette[i+2]; + NewPal->Palette[j+1] = Pal->Palette[i+1]; + NewPal->Palette[j+2] = Pal->Palette[i]; + } + } + else { + for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { + NewPal->Palette[j] = Pal->Palette[i]; + NewPal->Palette[j+1] = Pal->Palette[i+1]; + NewPal->Palette[j+2] = Pal->Palette[i+2]; + } + } + NewPal->PalSize = NewPalSize; + NewPal->PalType = DestFormat; + break; + + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + NewPalSize = (ILuint)((ILfloat)Pal->PalSize * 3.0f / 4.0f); + NewPal->Palette = (ILubyte*)ialloc(NewPalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_RGB24) { + for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { + NewPal->Palette[j] = Pal->Palette[i]; + NewPal->Palette[j+1] = Pal->Palette[i+1]; + NewPal->Palette[j+2] = Pal->Palette[i+2]; + } + } + else { + for (i = 0, j = 0; i < Pal->PalSize; i += 4, j += 3) { + NewPal->Palette[j] = Pal->Palette[i+2]; + NewPal->Palette[j+1] = Pal->Palette[i+1]; + NewPal->Palette[j+2] = Pal->Palette[i]; + } + } + NewPal->PalSize = NewPalSize; + NewPal->PalType = DestFormat; + break; + + default: + ilSetError(IL_INVALID_PARAM); + return NULL; + } + break; + + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + switch (Pal->PalType) + { + case IL_PAL_RGB24: + case IL_PAL_BGR24: + NewPalSize = Pal->PalSize * 4 / 3; + NewPal->Palette = (ILubyte*)ialloc(NewPalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if ((Pal->PalType == IL_PAL_BGR24 && (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32)) || + (Pal->PalType == IL_PAL_RGB24 && (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32))) { + for (i = 0, j = 0; i < Pal->PalSize; i += 3, j += 4) { + NewPal->Palette[j] = Pal->Palette[i+2]; + NewPal->Palette[j+1] = Pal->Palette[i+1]; + NewPal->Palette[j+2] = Pal->Palette[i]; + NewPal->Palette[j+3] = 255; + } + } + else { + for (i = 0, j = 0; i < Pal->PalSize; i += 3, j += 4) { + NewPal->Palette[j] = Pal->Palette[i]; + NewPal->Palette[j+1] = Pal->Palette[i+1]; + NewPal->Palette[j+2] = Pal->Palette[i+2]; + NewPal->Palette[j+3] = 255; + } + } + NewPal->PalSize = NewPalSize; + NewPal->PalType = DestFormat; + break; + + case IL_PAL_RGB32: + NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + + if (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32) { + for (i = 0; i < Pal->PalSize; i += 4) { + NewPal->Palette[i] = Pal->Palette[i+2]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i]; + NewPal->Palette[i+3] = 255; + } + } + else { + for (i = 0; i < Pal->PalSize; i += 4) { + NewPal->Palette[i] = Pal->Palette[i]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i+2]; + NewPal->Palette[i+3] = 255; + } + } + NewPal->PalType = DestFormat; + break; + + case IL_PAL_RGBA32: + NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_BGR32 || DestFormat == IL_PAL_BGRA32) { + for (i = 0; i < Pal->PalSize; i += 4) { + NewPal->Palette[i] = Pal->Palette[i+2]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i]; + NewPal->Palette[i+3] = Pal->Palette[i+3]; + } + } + else { + memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); + } + NewPal->PalType = DestFormat; + break; + + case IL_PAL_BGR32: + NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32) { + for (i = 0; i < Pal->PalSize; i += 4) { + NewPal->Palette[i] = Pal->Palette[i+2]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i]; + NewPal->Palette[i+3] = 255; + } + } + else { + for (i = 0; i < Pal->PalSize; i += 4) { + NewPal->Palette[i] = Pal->Palette[i]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i+2]; + NewPal->Palette[i+3] = 255; + } + } + NewPal->PalType = DestFormat; + break; + + case IL_PAL_BGRA32: + NewPal->Palette = (ILubyte*)ialloc(Pal->PalSize); + if (NewPal->Palette == NULL) + goto alloc_error; + if (DestFormat == IL_PAL_RGB32 || DestFormat == IL_PAL_RGBA32) { + for (i = 0; i < Pal->PalSize; i += 4) { + NewPal->Palette[i] = Pal->Palette[i+2]; + NewPal->Palette[i+1] = Pal->Palette[i+1]; + NewPal->Palette[i+2] = Pal->Palette[i]; + NewPal->Palette[i+3] = Pal->Palette[i+3]; + } + } + else { + memcpy(NewPal->Palette, Pal->Palette, Pal->PalSize); + } + NewPal->PalType = DestFormat; + break; + + default: + ilSetError(IL_INVALID_PARAM); + return NULL; + } + break; + + + default: + ilSetError(IL_INVALID_PARAM); + return NULL; + } + + NewPal->PalType = DestFormat; + + return NewPal; + +alloc_error: + ifree(NewPal); + return NULL; +} + + +//! Converts the current image to the DestFormat format. +ILboolean ILAPIENTRY ilConvertPal(ILenum DestFormat) +{ + ILpal *Pal; + + if (iCurImage == NULL || iCurImage->Pal.Palette == NULL || + iCurImage->Pal.PalSize == 0 || iCurImage->Pal.PalType == IL_PAL_NONE) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Pal = iConvertPal(&iCurImage->Pal, DestFormat); + if (Pal == NULL) + return IL_FALSE; + + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.PalSize = Pal->PalSize; + iCurImage->Pal.PalType = Pal->PalType; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(Pal->PalSize); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + memcpy(iCurImage->Pal.Palette, Pal->Palette, Pal->PalSize); + + ifree(Pal->Palette); + ifree(Pal); + + return IL_TRUE; +} + + +// Sets the current palette. +ILAPI void ILAPIENTRY ilSetPal(ILpal *Pal) +{ + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + } + + if (Pal->Palette && Pal->PalSize && Pal->PalType != IL_PAL_NONE) { + iCurImage->Pal.Palette = (ILubyte*)ialloc(Pal->PalSize); + if (iCurImage->Pal.Palette == NULL) + return; + memcpy(iCurImage->Pal.Palette, Pal->Palette, Pal->PalSize); + iCurImage->Pal.PalSize = Pal->PalSize; + iCurImage->Pal.PalType = Pal->PalType; + } + else { + iCurImage->Pal.Palette = NULL; + iCurImage->Pal.PalSize = 0; + iCurImage->Pal.PalType = IL_PAL_NONE; + } + + return; +} + + +ILuint CurSort = 0; +typedef struct COL_CUBE +{ + ILubyte Min[3]; + ILubyte Val[3]; + ILubyte Max[3]; +} COL_CUBE; + +int sort_func(void *e1, void *e2) +{ + return ((COL_CUBE*)e1)->Val[CurSort] - ((COL_CUBE*)e2)->Val[CurSort]; +} + + +ILboolean ILAPIENTRY ilApplyPal(ILconst_string FileName) +{ + ILimage Image, *CurImage = iCurImage; + ILubyte *NewData; + ILuint *PalInfo, NumColours, NumPix, MaxDist, DistEntry=0, i, j; + ILint Dist1, Dist2, Dist3; + ILboolean Same; + ILenum Origin; +// COL_CUBE *Cubes; + + if( iCurImage == NULL || (iCurImage->Format != IL_BYTE || iCurImage->Format != IL_UNSIGNED_BYTE) ) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + NewData = (ILubyte*)ialloc(iCurImage->Width * iCurImage->Height * iCurImage->Depth); + if (NewData == NULL) { + return IL_FALSE; + } + + iCurImage = &Image; + imemclear(&Image, sizeof(ILimage)); + // IL_PAL_RGB24, because we don't want to make parts transparent that shouldn't be. + if (!ilLoadPal(FileName) || !ilConvertPal(IL_PAL_RGB24)) { + ifree(NewData); + iCurImage = CurImage; + return IL_FALSE; + } + + NumColours = Image.Pal.PalSize / 3; // RGB24 is 3 bytes per entry. + PalInfo = (ILuint*)ialloc(NumColours * sizeof(ILuint)); + if (PalInfo == NULL) { + ifree(NewData); + iCurImage = CurImage; + return IL_FALSE; + } + + NumPix = CurImage->SizeOfData / ilGetBppFormat(CurImage->Format); + switch (CurImage->Format) + { + case IL_COLOUR_INDEX: + iCurImage = CurImage; + if (!ilConvertPal(IL_PAL_RGB24)) { + ifree(NewData); + ifree(PalInfo); + return IL_FALSE; + } + + NumPix = iCurImage->Pal.PalSize / ilGetBppPal(iCurImage->Pal.PalType); + for (i = 0; i < NumPix; i++) { + for (j = 0; j < Image.Pal.PalSize; j += 3) { + // No need to perform a sqrt. + Dist1 = (ILint)iCurImage->Pal.Palette[i] - (ILint)Image.Pal.Palette[j]; + Dist2 = (ILint)iCurImage->Pal.Palette[i+1] - (ILint)Image.Pal.Palette[j+1]; + Dist3 = (ILint)iCurImage->Pal.Palette[i+2] - (ILint)Image.Pal.Palette[j+2]; + PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3; + } + MaxDist = UINT_MAX; + DistEntry = 0; + for (j = 0; j < NumColours; j++) { + if (PalInfo[j] < MaxDist) { + DistEntry = j; + MaxDist = PalInfo[j]; + } + } + iCurImage->Pal.Palette[i] = DistEntry; + } + + for (i = 0; i < iCurImage->SizeOfData; i++) { + NewData[i] = iCurImage->Pal.Palette[iCurImage->Data[i]]; + } + break; + case IL_RGB: + case IL_RGBA: + /*Cube = (COL_CUBE*)ialloc(NumColours * sizeof(COL_CUBE)); + // @TODO: Check if ialloc failed here! + for (i = 0; i < NumColours; i++) + memcpy(&Cubes[i].Val, Image.Pal.Palette[i * 3], 3); + for (j = 0; j < 3; j++) { + qsort(Cubes, NumColours, sizeof(COL_CUBE), sort_func); + Cubes[0].Min = 0; + Cubes[NumColours-1] = UCHAR_MAX; + NumColours--; + for (i = 1; i < NumColours; i++) { + Cubes[i].Min[CurSort] = Cubes[i-1].Val[CurSort] + 1; + Cubes[i-1].Max[CurSort] = Cubes[i].Val[CurSort] - 1; + } + CurSort++; + NumColours++; + }*/ + for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) { + Same = IL_TRUE; + if (i != 0) { + for (j = 0; j < CurImage->Bpp; j++) { + if (CurImage->Data[i-CurImage->Bpp+j] != CurImage->Data[i+j]) { + Same = IL_FALSE; + break; + } + } + } + if (Same) { + NewData[i / CurImage->Bpp] = DistEntry; + continue; + } + for (j = 0; j < Image.Pal.PalSize; j += 3) { + // No need to perform a sqrt. + Dist1 = (ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j]; + Dist2 = (ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j+1]; + Dist3 = (ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j+2]; + PalInfo[j / 3] = Dist1 * Dist1 + Dist2 * Dist2 + Dist3 * Dist3; + } + MaxDist = UINT_MAX; + DistEntry = 0; + for (j = 0; j < NumColours; j++) { + if (PalInfo[j] < MaxDist) { + DistEntry = j; + MaxDist = PalInfo[j]; + } + } + NewData[i / CurImage->Bpp] = DistEntry; + } + + break; + + case IL_BGR: + case IL_BGRA: + for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp) { + for (j = 0; j < NumColours; j++) { + // No need to perform a sqrt. + PalInfo[j] = ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) * + ((ILint)CurImage->Data[i+2] - (ILint)Image.Pal.Palette[j * 3]) + + ((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) * + ((ILint)CurImage->Data[i+1] - (ILint)Image.Pal.Palette[j * 3 + 1]) + + ((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]) * + ((ILint)CurImage->Data[i] - (ILint)Image.Pal.Palette[j * 3 + 2]); + } + MaxDist = UINT_MAX; + DistEntry = 0; + for (j = 0; j < NumColours; j++) { + if (PalInfo[j] < MaxDist) { + DistEntry = j; + MaxDist = PalInfo[j]; + } + } + NewData[i / CurImage->Bpp] = DistEntry; + } + + break; + + case IL_LUMINANCE: + case IL_LUMINANCE_ALPHA: + for (i = 0; i < CurImage->SizeOfData; i += CurImage->Bpp ) { + for (j = 0; j < NumColours; j++) { + // No need to perform a sqrt. + PalInfo[j] = ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) * + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3]) + + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) * + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 1]) + + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]) * + ((ILuint)CurImage->Data[i] - (ILuint)Image.Pal.Palette[j * 3 + 2]); + } + MaxDist = UINT_MAX; + DistEntry = 0; + for (j = 0; j < NumColours; j++) { + if (PalInfo[j] < MaxDist) { + DistEntry = j; + MaxDist = PalInfo[j]; + } + } + NewData[i] = DistEntry; + } + + break; + + default: // Should be no other! + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + iCurImage = CurImage; + Origin = iCurImage->Origin; + if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, 1, + IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NewData)) { + ifree(Image.Pal.Palette); + ifree(PalInfo); + ifree(NewData); + return IL_FALSE; + } + iCurImage->Origin = Origin; + + iCurImage->Pal.Palette = Image.Pal.Palette; + iCurImage->Pal.PalSize = Image.Pal.PalSize; + iCurImage->Pal.PalType = Image.Pal.PalType; + ifree(PalInfo); + ifree(NewData); + + return IL_TRUE; +} diff --git a/DevIL/src-IL/src/il_pcd.c b/DevIL/src-IL/src/il_pcd.c deleted file mode 100644 index 8c588398..00000000 --- a/DevIL/src-IL/src/il_pcd.c +++ /dev/null @@ -1,206 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_pcd.c -// -// Description: Reads from a Kodak PhotoCD (.pcd) file. -// Note: The code here is sloppy - I had to convert it from Pascal, -// which I've never even attempted to read before...enjoy! =) -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_PCD - - -ILboolean iLoadPcdInternal(void); - -//! Reads a .pcd file -ILboolean ilLoadPcd(ILconst_string FileName) -{ - ILHANDLE PcdFile; - ILboolean bPcd = IL_FALSE; - - PcdFile = iopenr(FileName); - if (PcdFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPcd; - } - - bPcd = ilLoadPcdF(PcdFile); - icloser(PcdFile); - - return bPcd; -} - - -//! Reads an already-opened .pcd file -ILboolean ilLoadPcdF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPcdInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .pcd file -ILboolean ilLoadPcdL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPcdInternal(); -} - - -void YCbCr2RGB(ILubyte Y, ILubyte Cb, ILubyte Cr, ILubyte *r, ILubyte *g, ILubyte *b) -{ - static const ILdouble c11 = 0.0054980*256; - static const ILdouble c12 = 0.0000000*256; - static const ILdouble c13 = 0.0051681*256; - static const ILdouble c21 = 0.0054980*256; - static const ILdouble c22 =-0.0015446*256; - static const ILdouble c23 =-0.0026325*256; - static const ILdouble c31 = 0.0054980*256; - static const ILdouble c32 = 0.0079533*256; - static const ILdouble c33 = 0.0000000*256; - ILint r1, g1, b1; - - r1 = (ILint)(c11*Y + c12*(Cb-156) + c13*(Cr-137)); - g1 = (ILint)(c21*Y + c22*(Cb-156) + c23*(Cr-137)); - b1 = (ILint)(c31*Y + c32*(Cb-156) + c33*(Cr-137)); - - if (r1 < 0) - *r = 0; - else if (r1 > 255) - *r = 255; - else - *r = r1; - - if (g1 < 0) - *g = 0; - else if (g1 > 255) - *g = 255; - else - *g = g1; - - if (b1 < 0) - *b = 0; - else if (b1 > 255) - *b = 255; - else - *b = b1; - - return; -} - - -ILboolean iLoadPcdInternal() -{ - ILubyte VertOrientation; - ILuint Width, Height, i, Total, x, CurPos = 0; - ILubyte *Y1=NULL, *Y2=NULL, *CbCr=NULL, r = 0, g = 0, b = 0; - ILuint PicNum; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iseek(72, IL_SEEK_CUR); - if (iread(&VertOrientation, 1, 1) != 1) - return IL_FALSE; - - iseek(-72, IL_SEEK_CUR); // Can't rewind - - PicNum = iGetInt(IL_PCD_PICNUM); - - switch (PicNum) - { - case 0: - iseek(0x02000, IL_SEEK_CUR); - Width = 192; - Height = 128; - break; - case 1: - iseek(0x0b800, IL_SEEK_CUR); - Width = 384; - Height = 256; - break; - case 2: - iseek(0x30000, IL_SEEK_CUR); - Width = 768; - Height = 512; - break; - default: - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - if (itell() == IL_EOF) // Supposed to have data here. - return IL_FALSE; - - Y1 = (ILubyte*)ialloc(Width); - Y2 = (ILubyte*)ialloc(Width); - CbCr = (ILubyte*)ialloc(Width); - if (Y1 == NULL || Y2 == NULL || CbCr == NULL) { - ifree(Y1); - ifree(Y2); - ifree(CbCr); - return IL_FALSE; - } - - if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - Total = Height >> 1; - for (i = 0; i < Total; i++) { - iread(Y1, 1, Width); - iread(Y2, 1, Width); - if (iread(CbCr, 1, Width) != Width) { // Only really need to check the last one. - ifree(Y1); - ifree(Y2); - ifree(CbCr); - return IL_FALSE; - } - - for (x = 0; x < Width; x++) { - YCbCr2RGB(Y1[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b); - iCurImage->Data[CurPos++] = r; - iCurImage->Data[CurPos++] = g; - iCurImage->Data[CurPos++] = b; - } - - for (x = 0; x < Width; x++) { - YCbCr2RGB(Y2[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b); - iCurImage->Data[CurPos++] = r; - iCurImage->Data[CurPos++] = g; - iCurImage->Data[CurPos++] = b; - } - } - - ifree(Y1); - ifree(Y2); - ifree(CbCr); - - // Not sure how it is...the documentation is hard to understand - if ((VertOrientation & 0x3F) != 8) - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - else - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - return ilFixImage(); -} - - -#endif//IL_NO_PCD diff --git a/DevIL/src-IL/src/il_pcd.cpp b/DevIL/src-IL/src/il_pcd.cpp new file mode 100644 index 00000000..8c588398 --- /dev/null +++ b/DevIL/src-IL/src/il_pcd.cpp @@ -0,0 +1,206 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_pcd.c +// +// Description: Reads from a Kodak PhotoCD (.pcd) file. +// Note: The code here is sloppy - I had to convert it from Pascal, +// which I've never even attempted to read before...enjoy! =) +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_PCD + + +ILboolean iLoadPcdInternal(void); + +//! Reads a .pcd file +ILboolean ilLoadPcd(ILconst_string FileName) +{ + ILHANDLE PcdFile; + ILboolean bPcd = IL_FALSE; + + PcdFile = iopenr(FileName); + if (PcdFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPcd; + } + + bPcd = ilLoadPcdF(PcdFile); + icloser(PcdFile); + + return bPcd; +} + + +//! Reads an already-opened .pcd file +ILboolean ilLoadPcdF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPcdInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .pcd file +ILboolean ilLoadPcdL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPcdInternal(); +} + + +void YCbCr2RGB(ILubyte Y, ILubyte Cb, ILubyte Cr, ILubyte *r, ILubyte *g, ILubyte *b) +{ + static const ILdouble c11 = 0.0054980*256; + static const ILdouble c12 = 0.0000000*256; + static const ILdouble c13 = 0.0051681*256; + static const ILdouble c21 = 0.0054980*256; + static const ILdouble c22 =-0.0015446*256; + static const ILdouble c23 =-0.0026325*256; + static const ILdouble c31 = 0.0054980*256; + static const ILdouble c32 = 0.0079533*256; + static const ILdouble c33 = 0.0000000*256; + ILint r1, g1, b1; + + r1 = (ILint)(c11*Y + c12*(Cb-156) + c13*(Cr-137)); + g1 = (ILint)(c21*Y + c22*(Cb-156) + c23*(Cr-137)); + b1 = (ILint)(c31*Y + c32*(Cb-156) + c33*(Cr-137)); + + if (r1 < 0) + *r = 0; + else if (r1 > 255) + *r = 255; + else + *r = r1; + + if (g1 < 0) + *g = 0; + else if (g1 > 255) + *g = 255; + else + *g = g1; + + if (b1 < 0) + *b = 0; + else if (b1 > 255) + *b = 255; + else + *b = b1; + + return; +} + + +ILboolean iLoadPcdInternal() +{ + ILubyte VertOrientation; + ILuint Width, Height, i, Total, x, CurPos = 0; + ILubyte *Y1=NULL, *Y2=NULL, *CbCr=NULL, r = 0, g = 0, b = 0; + ILuint PicNum; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iseek(72, IL_SEEK_CUR); + if (iread(&VertOrientation, 1, 1) != 1) + return IL_FALSE; + + iseek(-72, IL_SEEK_CUR); // Can't rewind + + PicNum = iGetInt(IL_PCD_PICNUM); + + switch (PicNum) + { + case 0: + iseek(0x02000, IL_SEEK_CUR); + Width = 192; + Height = 128; + break; + case 1: + iseek(0x0b800, IL_SEEK_CUR); + Width = 384; + Height = 256; + break; + case 2: + iseek(0x30000, IL_SEEK_CUR); + Width = 768; + Height = 512; + break; + default: + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + if (itell() == IL_EOF) // Supposed to have data here. + return IL_FALSE; + + Y1 = (ILubyte*)ialloc(Width); + Y2 = (ILubyte*)ialloc(Width); + CbCr = (ILubyte*)ialloc(Width); + if (Y1 == NULL || Y2 == NULL || CbCr == NULL) { + ifree(Y1); + ifree(Y2); + ifree(CbCr); + return IL_FALSE; + } + + if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + Total = Height >> 1; + for (i = 0; i < Total; i++) { + iread(Y1, 1, Width); + iread(Y2, 1, Width); + if (iread(CbCr, 1, Width) != Width) { // Only really need to check the last one. + ifree(Y1); + ifree(Y2); + ifree(CbCr); + return IL_FALSE; + } + + for (x = 0; x < Width; x++) { + YCbCr2RGB(Y1[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b); + iCurImage->Data[CurPos++] = r; + iCurImage->Data[CurPos++] = g; + iCurImage->Data[CurPos++] = b; + } + + for (x = 0; x < Width; x++) { + YCbCr2RGB(Y2[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b); + iCurImage->Data[CurPos++] = r; + iCurImage->Data[CurPos++] = g; + iCurImage->Data[CurPos++] = b; + } + } + + ifree(Y1); + ifree(Y2); + ifree(CbCr); + + // Not sure how it is...the documentation is hard to understand + if ((VertOrientation & 0x3F) != 8) + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + else + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + return ilFixImage(); +} + + +#endif//IL_NO_PCD diff --git a/DevIL/src-IL/src/il_pcx.c b/DevIL/src-IL/src/il_pcx.c deleted file mode 100644 index bce1387c..00000000 --- a/DevIL/src-IL/src/il_pcx.c +++ /dev/null @@ -1,739 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_pcx.c -// -// Description: Reads and writes from/to a .pcx file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_PCX -#include "il_pcx.h" - - -//! Checks if the file specified in FileName is a valid .pcx file. -ILboolean ilIsValidPcx(ILconst_string FileName) -{ - ILHANDLE PcxFile; - ILboolean bPcx = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("pcx"))) { - ilSetError(IL_INVALID_EXTENSION); - return bPcx; - } - - PcxFile = iopenr(FileName); - if (PcxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPcx; - } - - bPcx = ilIsValidPcxF(PcxFile); - icloser(PcxFile); - - return bPcx; -} - - -//! Checks if the ILHANDLE contains a valid .pcx file at the current position. -ILboolean ilIsValidPcxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidPcx(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .pcx lump. -ILboolean ilIsValidPcxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidPcx(); -} - - -// Internal function obtain the .pcx header from the current file. -ILboolean iGetPcxHead(PCXHEAD *Head) -{ - Head->Manufacturer = igetc(); - Head->Version = igetc(); - Head->Encoding = igetc(); - Head->Bpp = igetc(); - Head->Xmin = GetLittleUShort(); - Head->Ymin = GetLittleUShort(); - Head->Xmax = GetLittleUShort(); - Head->Ymax = GetLittleUShort(); - Head->HDpi = GetLittleUShort(); - Head->VDpi = GetLittleUShort(); - iread(Head->ColMap, 1, 48); - Head->Reserved = igetc(); - Head->NumPlanes = igetc(); - Head->Bps = GetLittleUShort(); - Head->PaletteInfo = GetLittleUShort(); - Head->HScreenSize = GetLittleUShort(); - Head->VScreenSize = GetLittleUShort(); - iread(Head->Filler, 1, 54); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidPcx() -{ - PCXHEAD Head; - - if (!iGetPcxHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(PCXHEAD), IL_SEEK_CUR); - - return iCheckPcx(&Head); -} - - -// Internal function used to check if the HEADER is a valid .pcx header. -// Should we also do a check on Header->Bpp? -ILboolean iCheckPcx(PCXHEAD *Header) -{ - ILuint Test; - - // Got rid of the Reserved check, because I've seen some .pcx files with invalid values in it. - if (Header->Manufacturer != 10 || Header->Encoding != 1/* || Header->Reserved != 0*/) - return IL_FALSE; - - // Try to support all pcx versions, as they only differ in allowed formats... - // Let's hope it works. - if(Header->Version != 5 && Header->Version != 0 && Header->Version != 2 && - Header->VDpi != 3 && Header->VDpi != 4) - return IL_FALSE; - - // See if the padding size is correct - Test = Header->Xmax - Header->Xmin + 1; - if (Header->Bpp >= 8) { - if (Test & 1) { - if (Header->Bps != Test + 1) - return IL_FALSE; - } - else { - if (Header->Bps != Test) // No padding - return IL_FALSE; - } - } - - /* for (i = 0; i < 54; i++) { useless check - if (Header->Filler[i] != 0) - return IL_FALSE; - } */ - - return IL_TRUE; -} - - -//! Reads a .pcx file -ILboolean ilLoadPcx(ILconst_string FileName) -{ - ILHANDLE PcxFile; - ILboolean bPcx = IL_FALSE; - - PcxFile = iopenr(FileName); - if (PcxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPcx; - } - - bPcx = ilLoadPcxF(PcxFile); - icloser(PcxFile); - - return bPcx; -} - - -//! Reads an already-opened .pcx file -ILboolean ilLoadPcxF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPcxInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .pcx -ILboolean ilLoadPcxL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPcxInternal(); -} - - -// Internal function used to load the .pcx. -ILboolean iLoadPcxInternal() -{ - PCXHEAD Header; - ILboolean bPcx = IL_FALSE; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return bPcx; - } - - if (!iGetPcxHead(&Header)) - return IL_FALSE; - if (!iCheckPcx(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - bPcx = iUncompressPcx(&Header); - - if (!bPcx) - return IL_FALSE; - return ilFixImage(); -} - - -// Internal function to uncompress the .pcx (all .pcx files are rle compressed) -ILboolean iUncompressPcx(PCXHEAD *Header) -{ - //changed decompression loop 2003-09-01 - //From the pcx spec: "There should always - //be a decoding break at the end of each scan line. - //But there will not be a decoding break at the end of - //each plane within each scan line." - //This is now handled correctly (hopefully ;) ) - - ILubyte ByteHead, Colour, *ScanLine /* For all planes */; - ILuint ScanLineSize; - ILuint c, i, x, y; - - if (Header->Bpp < 8) { - /*ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE;*/ - return iUncompressSmall(Header); - } - - if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - switch (iCurImage->Bpp) - { - case 1: - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalType = IL_PAL_RGB24; - iCurImage->Pal.PalSize = 256 * 3; // Need to find out for sure... - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - break; - //case 2: // No 16-bit images in the pcx format! - case 3: - iCurImage->Format = IL_RGB; - iCurImage->Pal.Palette = NULL; - iCurImage->Pal.PalSize = 0; - iCurImage->Pal.PalType = IL_PAL_NONE; - break; - case 4: - iCurImage->Format = IL_RGBA; - iCurImage->Pal.Palette = NULL; - iCurImage->Pal.PalSize = 0; - iCurImage->Pal.PalType = IL_PAL_NONE; - break; - - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - ScanLineSize = iCurImage->Bpp*Header->Bps; - ScanLine = (ILubyte*)ialloc(ScanLineSize); - if (ScanLine == NULL) { - return IL_FALSE; - } - - - //changed 2003-09-01 - //having the decoding code twice is error-prone, - //so I made iUnCache() smart enough to grasp - //if iPreCache() wasn't called and call it - //anyways. - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->SizeOfData / 4); - - for (y = 0; y < iCurImage->Height; y++) { - x = 0; - //read scanline - while (x < ScanLineSize) { - if (iread(&ByteHead, 1, 1) != 1) { - iUnCache(); - goto file_read_error; - } - if ((ByteHead & 0xC0) == 0xC0) { - ByteHead &= 0x3F; - if (iread(&Colour, 1, 1) != 1) { - iUnCache(); - goto file_read_error; - } - if (x + ByteHead > ScanLineSize) { - iUnCache(); - goto file_read_error; - } - for (i = 0; i < ByteHead; i++) { - ScanLine[x++] = Colour; - } - } - else { - ScanLine[x++] = ByteHead; - } - } - - //convert plane-separated scanline into index, rgb or rgba pixels. - //there might be a padding byte at the end of each scanline... - for (x = 0; x < iCurImage->Width; x++) { - for(c = 0; c < iCurImage->Bpp; c++) { - iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] = - ScanLine[x + c * Header->Bps]; - } - } - } - - iUnCache(); - - // Read in the palette - if (Header->Version == 5 && iCurImage->Bpp == 1) { - x = itell(); - if (iread(&ByteHead, 1, 1) == 0) { // If true, assume that we have a luminance image. - ilGetError(); // Get rid of the IL_FILE_READ_ERROR. - iCurImage->Format = IL_LUMINANCE; - if (iCurImage->Pal.Palette) - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.PalSize = 0; - iCurImage->Pal.PalType = IL_PAL_NONE; - } - else { - if (ByteHead != 12) // Some Quake2 .pcx files don't have this byte for some reason. - iseek(-1, IL_SEEK_CUR); - if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) - goto file_read_error; - } - } - - ifree(ScanLine); - - return IL_TRUE; - -file_read_error: - ifree(ScanLine); - - //added 2003-09-01 - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; -} - - -ILboolean iUncompressSmall(PCXHEAD *Header) -{ - ILuint i = 0, j, k, c, d, x, y, Bps; - ILubyte HeadByte, Colour, Data = 0, *ScanLine; - - if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - switch (Header->NumPlanes) - { - case 1: - iCurImage->Format = IL_LUMINANCE; - break; - case 4: - iCurImage->Format = IL_COLOUR_INDEX; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - if (Header->NumPlanes == 1 && Header->Bpp == 1) { - for (j = 0; j < iCurImage->Height; j++) { - i = 0; //number of written pixels - while (i < iCurImage->Width) { - if (iread(&HeadByte, 1, 1) != 1) - return IL_FALSE; - if (HeadByte >= 192) { - HeadByte -= 192; - if (iread(&Data, 1, 1) != 1) - return IL_FALSE; - - for (c = 0; c < HeadByte; c++) { - k = 128; - for (d = 0; d < 8 && i < iCurImage->Width; d++) { - iCurImage->Data[j * iCurImage->Width + i++] = ((Data & k) != 0 ? 255 : 0); - k >>= 1; - } - } - } - else { - k = 128; - for (c = 0; c < 8 && i < iCurImage->Width; c++) { - iCurImage->Data[j * iCurImage->Width + i++] = ((HeadByte & k) != 0 ? 255 : 0); - k >>= 1; - } - } - } - - //if(Data != 0) - //changed 2003-09-01: - //There has to be an even number of bytes per line in a pcx. - //One byte can hold up to 8 bits, so Width/8 bytes - //are needed to hold a 1 bit per pixel image line. - //If Width/8 is even no padding is needed, - //one pad byte has to be read otherwise. - //(let's hope the above is true ;-)) - if(!((iCurImage->Width >> 3) & 0x1)) - igetc(); // Skip pad byte - } - } - else if (Header->NumPlanes == 4 && Header->Bpp == 1){ // 4-bit images - //changed decoding 2003-09-10 (was buggy)...could need a speedup - - Bps = Header->Bps * Header->NumPlanes * 8; - iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes). - ScanLine = (ILubyte*)ialloc(Bps); - if (iCurImage->Pal.Palette == NULL || ScanLine == NULL) { - ifree(ScanLine); - ifree(iCurImage->Pal.Palette); - return IL_FALSE; - } - memcpy(iCurImage->Pal.Palette, Header->ColMap, 16 * 3); - iCurImage->Pal.PalSize = 16 * 3; - iCurImage->Pal.PalType = IL_PAL_RGB24; - - memset(iCurImage->Data, 0, iCurImage->SizeOfData); - - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->SizeOfData / 4); - for (y = 0; y < iCurImage->Height; y++) { - x = 0; - while (x < Bps) { - if (iread(&HeadByte, 1, 1) != 1) { - iUnCache(); - ifree(ScanLine); - return IL_FALSE; - } - if ((HeadByte & 0xC0) == 0xC0) { - HeadByte &= 0x3F; - if (iread(&Colour, 1, 1) != 1) { - iUnCache(); - ifree(ScanLine); - return IL_FALSE; - } - for (i = 0; i < HeadByte; i++) { - k = 128; - for (j = 0; j < 8 && x < Bps; j++) { - ScanLine[x++] = (Colour & k)?1:0; - k >>= 1; - } - } - } - else { - k = 128; - for (j = 0; j < 8 && x < Bps; j++) { - ScanLine[x++] = (HeadByte & k)?1:0; - k >>= 1; - } - } - } - - for (x = 0; x < iCurImage->Width; x++) { // 'Cleverly' ignores the pad bytes. ;) - for(c = 0; c < Header->NumPlanes; c++) - iCurImage->Data[y * iCurImage->Width + x] |= ScanLine[x + c*Header->Bps*8] << c; - } - } - iUnCache(); - ifree(ScanLine); - } - else { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - return IL_TRUE; -} - - -//! Writes a .pcx file -ILboolean ilSavePcx(const ILstring FileName) -{ - ILHANDLE PcxFile; - ILuint PcxSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - PcxFile = iopenw(FileName); - if (PcxFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - PcxSize = ilSavePcxF(PcxFile); - iclosew(PcxFile); - - if (PcxSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a .pcx to an already-opened file -ILuint ilSavePcxF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSavePcxInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a .pcx to a memory "lump" -ILuint ilSavePcxL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSavePcxInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the .pcx. -ILboolean iSavePcxInternal() -{ - ILuint i, c, PalSize; - ILpal *TempPal; - ILimage *TempImage = iCurImage; - ILubyte *TempData; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - switch (iCurImage->Format) - { - case IL_LUMINANCE: - TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - break; - - case IL_BGR: - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - break; - - case IL_BGRA: - TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - break; - - default: - if (iCurImage->Bpc > 1) { - TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - } - } - - if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - if (TempImage != iCurImage) { - ilCloseImage(TempImage); - } - return IL_FALSE; - } - } - else { - TempData = TempImage->Data; - } - - - iputc(0xA); // Manufacturer - always 10 - iputc(0x5); // Version Number - always 5 - iputc(0x1); // Encoding - always 1 - iputc(0x8); // Bits per channel - SaveLittleUShort(0); // X Minimum - SaveLittleUShort(0); // Y Minimum - SaveLittleUShort((ILushort)(iCurImage->Width - 1)); - SaveLittleUShort((ILushort)(iCurImage->Height - 1)); - SaveLittleUShort(0); - SaveLittleUShort(0); - - // Useless palette info? - for (i = 0; i < 48; i++) { - iputc(0); - } - iputc(0x0); // Reserved - always 0 - - iputc(iCurImage->Bpp); // Number of planes - only 1 is supported right now - - SaveLittleUShort((ILushort)(iCurImage->Width & 1 ? iCurImage->Width + 1 : iCurImage->Width)); // Bps - SaveLittleUShort(0x1); // Palette type - ignored? - - // Mainly filler info - for (i = 0; i < 58; i++) { - iputc(0x0); - } - - // Output data - for (i = 0; i < TempImage->Height; i++) { - for (c = 0; c < TempImage->Bpp; c++) { - encLine(TempData + TempImage->Bps * i + c, TempImage->Width, (ILubyte)(TempImage->Bpp - 1)); - } - } - - // Automatically assuming we have a palette...dangerous! - // Also assuming 3 bpp palette - iputc(0xC); // Pad byte must have this value - - // If the current image has a palette, take care of it - if (TempImage->Format == IL_COLOUR_INDEX) { - // If the palette in .pcx format, write it directly - if (TempImage->Pal.PalType == IL_PAL_RGB24) { - iwrite(TempImage->Pal.Palette, 1, TempImage->Pal.PalSize); - } - else { - TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24); - if (TempPal == NULL) { - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) - ifree(TempData); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - - iwrite(TempPal->Palette, 1, TempPal->PalSize); - ifree(TempPal->Palette); - ifree(TempPal); - } - } - - // If the palette is not all 256 colours, we have to pad it. - PalSize = 768 - iCurImage->Pal.PalSize; - for (i = 0; i < PalSize; i++) { - iputc(0x0); - } - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) - ifree(TempData); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return IL_TRUE; -} - - -// Routine used from ZSoft's pcx documentation -ILuint encput(ILubyte byt, ILubyte cnt) -{ - if (cnt) { - if ((cnt == 1) && (0xC0 != (0xC0 & byt))) { - if (IL_EOF == iputc(byt)) - return(0); /* disk write error (probably full) */ - return(1); - } - else { - if (IL_EOF == iputc((ILubyte)((ILuint)0xC0 | cnt))) - return (0); /* disk write error */ - if (IL_EOF == iputc(byt)) - return (0); /* disk write error */ - return (2); - } - } - - return (0); -} - -// This subroutine encodes one scanline and writes it to a file. -// It returns number of bytes written into outBuff, 0 if failed. -ILuint encLine(ILubyte *inBuff, ILint inLen, ILubyte Stride) -{ - ILubyte _this, last; - ILint srcIndex, i; - ILint total; - ILubyte runCount; // max single runlength is 63 - total = 0; - runCount = 1; - last = *(inBuff); - - // Find the pixel dimensions of the image by calculating - //[XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1]. - //Then calculate how many bytes are in a "run" - - for (srcIndex = 1; srcIndex < inLen; srcIndex++) { - inBuff += Stride; - _this = *(++inBuff); - if (_this == last) { // There is a "run" in the data, encode it - runCount++; - if (runCount == 63) { - if (! (i = encput(last, runCount))) - return (0); - total += i; - runCount = 0; - } - } - else { // No "run" - _this != last - if (runCount) { - if (! (i = encput(last, runCount))) - return(0); - total += i; - } - last = _this; - runCount = 1; - } - } // endloop - - if (runCount) { // finish up - if (! (i = encput(last, runCount))) - return (0); - if (inLen % 2) - iputc(0); - return (total + i); - } - else { - if (inLen % 2) - iputc(0); - } - - return (total); -} - -#endif//IL_NO_PCX diff --git a/DevIL/src-IL/src/il_pcx.cpp b/DevIL/src-IL/src/il_pcx.cpp new file mode 100644 index 00000000..bce1387c --- /dev/null +++ b/DevIL/src-IL/src/il_pcx.cpp @@ -0,0 +1,739 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_pcx.c +// +// Description: Reads and writes from/to a .pcx file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_PCX +#include "il_pcx.h" + + +//! Checks if the file specified in FileName is a valid .pcx file. +ILboolean ilIsValidPcx(ILconst_string FileName) +{ + ILHANDLE PcxFile; + ILboolean bPcx = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("pcx"))) { + ilSetError(IL_INVALID_EXTENSION); + return bPcx; + } + + PcxFile = iopenr(FileName); + if (PcxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPcx; + } + + bPcx = ilIsValidPcxF(PcxFile); + icloser(PcxFile); + + return bPcx; +} + + +//! Checks if the ILHANDLE contains a valid .pcx file at the current position. +ILboolean ilIsValidPcxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidPcx(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .pcx lump. +ILboolean ilIsValidPcxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidPcx(); +} + + +// Internal function obtain the .pcx header from the current file. +ILboolean iGetPcxHead(PCXHEAD *Head) +{ + Head->Manufacturer = igetc(); + Head->Version = igetc(); + Head->Encoding = igetc(); + Head->Bpp = igetc(); + Head->Xmin = GetLittleUShort(); + Head->Ymin = GetLittleUShort(); + Head->Xmax = GetLittleUShort(); + Head->Ymax = GetLittleUShort(); + Head->HDpi = GetLittleUShort(); + Head->VDpi = GetLittleUShort(); + iread(Head->ColMap, 1, 48); + Head->Reserved = igetc(); + Head->NumPlanes = igetc(); + Head->Bps = GetLittleUShort(); + Head->PaletteInfo = GetLittleUShort(); + Head->HScreenSize = GetLittleUShort(); + Head->VScreenSize = GetLittleUShort(); + iread(Head->Filler, 1, 54); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidPcx() +{ + PCXHEAD Head; + + if (!iGetPcxHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(PCXHEAD), IL_SEEK_CUR); + + return iCheckPcx(&Head); +} + + +// Internal function used to check if the HEADER is a valid .pcx header. +// Should we also do a check on Header->Bpp? +ILboolean iCheckPcx(PCXHEAD *Header) +{ + ILuint Test; + + // Got rid of the Reserved check, because I've seen some .pcx files with invalid values in it. + if (Header->Manufacturer != 10 || Header->Encoding != 1/* || Header->Reserved != 0*/) + return IL_FALSE; + + // Try to support all pcx versions, as they only differ in allowed formats... + // Let's hope it works. + if(Header->Version != 5 && Header->Version != 0 && Header->Version != 2 && + Header->VDpi != 3 && Header->VDpi != 4) + return IL_FALSE; + + // See if the padding size is correct + Test = Header->Xmax - Header->Xmin + 1; + if (Header->Bpp >= 8) { + if (Test & 1) { + if (Header->Bps != Test + 1) + return IL_FALSE; + } + else { + if (Header->Bps != Test) // No padding + return IL_FALSE; + } + } + + /* for (i = 0; i < 54; i++) { useless check + if (Header->Filler[i] != 0) + return IL_FALSE; + } */ + + return IL_TRUE; +} + + +//! Reads a .pcx file +ILboolean ilLoadPcx(ILconst_string FileName) +{ + ILHANDLE PcxFile; + ILboolean bPcx = IL_FALSE; + + PcxFile = iopenr(FileName); + if (PcxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPcx; + } + + bPcx = ilLoadPcxF(PcxFile); + icloser(PcxFile); + + return bPcx; +} + + +//! Reads an already-opened .pcx file +ILboolean ilLoadPcxF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPcxInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .pcx +ILboolean ilLoadPcxL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPcxInternal(); +} + + +// Internal function used to load the .pcx. +ILboolean iLoadPcxInternal() +{ + PCXHEAD Header; + ILboolean bPcx = IL_FALSE; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return bPcx; + } + + if (!iGetPcxHead(&Header)) + return IL_FALSE; + if (!iCheckPcx(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + bPcx = iUncompressPcx(&Header); + + if (!bPcx) + return IL_FALSE; + return ilFixImage(); +} + + +// Internal function to uncompress the .pcx (all .pcx files are rle compressed) +ILboolean iUncompressPcx(PCXHEAD *Header) +{ + //changed decompression loop 2003-09-01 + //From the pcx spec: "There should always + //be a decoding break at the end of each scan line. + //But there will not be a decoding break at the end of + //each plane within each scan line." + //This is now handled correctly (hopefully ;) ) + + ILubyte ByteHead, Colour, *ScanLine /* For all planes */; + ILuint ScanLineSize; + ILuint c, i, x, y; + + if (Header->Bpp < 8) { + /*ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE;*/ + return iUncompressSmall(Header); + } + + if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + switch (iCurImage->Bpp) + { + case 1: + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalType = IL_PAL_RGB24; + iCurImage->Pal.PalSize = 256 * 3; // Need to find out for sure... + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + break; + //case 2: // No 16-bit images in the pcx format! + case 3: + iCurImage->Format = IL_RGB; + iCurImage->Pal.Palette = NULL; + iCurImage->Pal.PalSize = 0; + iCurImage->Pal.PalType = IL_PAL_NONE; + break; + case 4: + iCurImage->Format = IL_RGBA; + iCurImage->Pal.Palette = NULL; + iCurImage->Pal.PalSize = 0; + iCurImage->Pal.PalType = IL_PAL_NONE; + break; + + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + ScanLineSize = iCurImage->Bpp*Header->Bps; + ScanLine = (ILubyte*)ialloc(ScanLineSize); + if (ScanLine == NULL) { + return IL_FALSE; + } + + + //changed 2003-09-01 + //having the decoding code twice is error-prone, + //so I made iUnCache() smart enough to grasp + //if iPreCache() wasn't called and call it + //anyways. + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->SizeOfData / 4); + + for (y = 0; y < iCurImage->Height; y++) { + x = 0; + //read scanline + while (x < ScanLineSize) { + if (iread(&ByteHead, 1, 1) != 1) { + iUnCache(); + goto file_read_error; + } + if ((ByteHead & 0xC0) == 0xC0) { + ByteHead &= 0x3F; + if (iread(&Colour, 1, 1) != 1) { + iUnCache(); + goto file_read_error; + } + if (x + ByteHead > ScanLineSize) { + iUnCache(); + goto file_read_error; + } + for (i = 0; i < ByteHead; i++) { + ScanLine[x++] = Colour; + } + } + else { + ScanLine[x++] = ByteHead; + } + } + + //convert plane-separated scanline into index, rgb or rgba pixels. + //there might be a padding byte at the end of each scanline... + for (x = 0; x < iCurImage->Width; x++) { + for(c = 0; c < iCurImage->Bpp; c++) { + iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] = + ScanLine[x + c * Header->Bps]; + } + } + } + + iUnCache(); + + // Read in the palette + if (Header->Version == 5 && iCurImage->Bpp == 1) { + x = itell(); + if (iread(&ByteHead, 1, 1) == 0) { // If true, assume that we have a luminance image. + ilGetError(); // Get rid of the IL_FILE_READ_ERROR. + iCurImage->Format = IL_LUMINANCE; + if (iCurImage->Pal.Palette) + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.PalSize = 0; + iCurImage->Pal.PalType = IL_PAL_NONE; + } + else { + if (ByteHead != 12) // Some Quake2 .pcx files don't have this byte for some reason. + iseek(-1, IL_SEEK_CUR); + if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) + goto file_read_error; + } + } + + ifree(ScanLine); + + return IL_TRUE; + +file_read_error: + ifree(ScanLine); + + //added 2003-09-01 + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; +} + + +ILboolean iUncompressSmall(PCXHEAD *Header) +{ + ILuint i = 0, j, k, c, d, x, y, Bps; + ILubyte HeadByte, Colour, Data = 0, *ScanLine; + + if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + switch (Header->NumPlanes) + { + case 1: + iCurImage->Format = IL_LUMINANCE; + break; + case 4: + iCurImage->Format = IL_COLOUR_INDEX; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + if (Header->NumPlanes == 1 && Header->Bpp == 1) { + for (j = 0; j < iCurImage->Height; j++) { + i = 0; //number of written pixels + while (i < iCurImage->Width) { + if (iread(&HeadByte, 1, 1) != 1) + return IL_FALSE; + if (HeadByte >= 192) { + HeadByte -= 192; + if (iread(&Data, 1, 1) != 1) + return IL_FALSE; + + for (c = 0; c < HeadByte; c++) { + k = 128; + for (d = 0; d < 8 && i < iCurImage->Width; d++) { + iCurImage->Data[j * iCurImage->Width + i++] = ((Data & k) != 0 ? 255 : 0); + k >>= 1; + } + } + } + else { + k = 128; + for (c = 0; c < 8 && i < iCurImage->Width; c++) { + iCurImage->Data[j * iCurImage->Width + i++] = ((HeadByte & k) != 0 ? 255 : 0); + k >>= 1; + } + } + } + + //if(Data != 0) + //changed 2003-09-01: + //There has to be an even number of bytes per line in a pcx. + //One byte can hold up to 8 bits, so Width/8 bytes + //are needed to hold a 1 bit per pixel image line. + //If Width/8 is even no padding is needed, + //one pad byte has to be read otherwise. + //(let's hope the above is true ;-)) + if(!((iCurImage->Width >> 3) & 0x1)) + igetc(); // Skip pad byte + } + } + else if (Header->NumPlanes == 4 && Header->Bpp == 1){ // 4-bit images + //changed decoding 2003-09-10 (was buggy)...could need a speedup + + Bps = Header->Bps * Header->NumPlanes * 8; + iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes). + ScanLine = (ILubyte*)ialloc(Bps); + if (iCurImage->Pal.Palette == NULL || ScanLine == NULL) { + ifree(ScanLine); + ifree(iCurImage->Pal.Palette); + return IL_FALSE; + } + memcpy(iCurImage->Pal.Palette, Header->ColMap, 16 * 3); + iCurImage->Pal.PalSize = 16 * 3; + iCurImage->Pal.PalType = IL_PAL_RGB24; + + memset(iCurImage->Data, 0, iCurImage->SizeOfData); + + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->SizeOfData / 4); + for (y = 0; y < iCurImage->Height; y++) { + x = 0; + while (x < Bps) { + if (iread(&HeadByte, 1, 1) != 1) { + iUnCache(); + ifree(ScanLine); + return IL_FALSE; + } + if ((HeadByte & 0xC0) == 0xC0) { + HeadByte &= 0x3F; + if (iread(&Colour, 1, 1) != 1) { + iUnCache(); + ifree(ScanLine); + return IL_FALSE; + } + for (i = 0; i < HeadByte; i++) { + k = 128; + for (j = 0; j < 8 && x < Bps; j++) { + ScanLine[x++] = (Colour & k)?1:0; + k >>= 1; + } + } + } + else { + k = 128; + for (j = 0; j < 8 && x < Bps; j++) { + ScanLine[x++] = (HeadByte & k)?1:0; + k >>= 1; + } + } + } + + for (x = 0; x < iCurImage->Width; x++) { // 'Cleverly' ignores the pad bytes. ;) + for(c = 0; c < Header->NumPlanes; c++) + iCurImage->Data[y * iCurImage->Width + x] |= ScanLine[x + c*Header->Bps*8] << c; + } + } + iUnCache(); + ifree(ScanLine); + } + else { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + return IL_TRUE; +} + + +//! Writes a .pcx file +ILboolean ilSavePcx(const ILstring FileName) +{ + ILHANDLE PcxFile; + ILuint PcxSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + PcxFile = iopenw(FileName); + if (PcxFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + PcxSize = ilSavePcxF(PcxFile); + iclosew(PcxFile); + + if (PcxSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a .pcx to an already-opened file +ILuint ilSavePcxF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSavePcxInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a .pcx to a memory "lump" +ILuint ilSavePcxL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSavePcxInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the .pcx. +ILboolean iSavePcxInternal() +{ + ILuint i, c, PalSize; + ILpal *TempPal; + ILimage *TempImage = iCurImage; + ILubyte *TempData; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + switch (iCurImage->Format) + { + case IL_LUMINANCE: + TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + break; + + case IL_BGR: + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + break; + + case IL_BGRA: + TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + break; + + default: + if (iCurImage->Bpc > 1) { + TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + } + } + + if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + if (TempImage != iCurImage) { + ilCloseImage(TempImage); + } + return IL_FALSE; + } + } + else { + TempData = TempImage->Data; + } + + + iputc(0xA); // Manufacturer - always 10 + iputc(0x5); // Version Number - always 5 + iputc(0x1); // Encoding - always 1 + iputc(0x8); // Bits per channel + SaveLittleUShort(0); // X Minimum + SaveLittleUShort(0); // Y Minimum + SaveLittleUShort((ILushort)(iCurImage->Width - 1)); + SaveLittleUShort((ILushort)(iCurImage->Height - 1)); + SaveLittleUShort(0); + SaveLittleUShort(0); + + // Useless palette info? + for (i = 0; i < 48; i++) { + iputc(0); + } + iputc(0x0); // Reserved - always 0 + + iputc(iCurImage->Bpp); // Number of planes - only 1 is supported right now + + SaveLittleUShort((ILushort)(iCurImage->Width & 1 ? iCurImage->Width + 1 : iCurImage->Width)); // Bps + SaveLittleUShort(0x1); // Palette type - ignored? + + // Mainly filler info + for (i = 0; i < 58; i++) { + iputc(0x0); + } + + // Output data + for (i = 0; i < TempImage->Height; i++) { + for (c = 0; c < TempImage->Bpp; c++) { + encLine(TempData + TempImage->Bps * i + c, TempImage->Width, (ILubyte)(TempImage->Bpp - 1)); + } + } + + // Automatically assuming we have a palette...dangerous! + // Also assuming 3 bpp palette + iputc(0xC); // Pad byte must have this value + + // If the current image has a palette, take care of it + if (TempImage->Format == IL_COLOUR_INDEX) { + // If the palette in .pcx format, write it directly + if (TempImage->Pal.PalType == IL_PAL_RGB24) { + iwrite(TempImage->Pal.Palette, 1, TempImage->Pal.PalSize); + } + else { + TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24); + if (TempPal == NULL) { + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) + ifree(TempData); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + + iwrite(TempPal->Palette, 1, TempPal->PalSize); + ifree(TempPal->Palette); + ifree(TempPal); + } + } + + // If the palette is not all 256 colours, we have to pad it. + PalSize = 768 - iCurImage->Pal.PalSize; + for (i = 0; i < PalSize; i++) { + iputc(0x0); + } + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) + ifree(TempData); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return IL_TRUE; +} + + +// Routine used from ZSoft's pcx documentation +ILuint encput(ILubyte byt, ILubyte cnt) +{ + if (cnt) { + if ((cnt == 1) && (0xC0 != (0xC0 & byt))) { + if (IL_EOF == iputc(byt)) + return(0); /* disk write error (probably full) */ + return(1); + } + else { + if (IL_EOF == iputc((ILubyte)((ILuint)0xC0 | cnt))) + return (0); /* disk write error */ + if (IL_EOF == iputc(byt)) + return (0); /* disk write error */ + return (2); + } + } + + return (0); +} + +// This subroutine encodes one scanline and writes it to a file. +// It returns number of bytes written into outBuff, 0 if failed. +ILuint encLine(ILubyte *inBuff, ILint inLen, ILubyte Stride) +{ + ILubyte _this, last; + ILint srcIndex, i; + ILint total; + ILubyte runCount; // max single runlength is 63 + total = 0; + runCount = 1; + last = *(inBuff); + + // Find the pixel dimensions of the image by calculating + //[XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1]. + //Then calculate how many bytes are in a "run" + + for (srcIndex = 1; srcIndex < inLen; srcIndex++) { + inBuff += Stride; + _this = *(++inBuff); + if (_this == last) { // There is a "run" in the data, encode it + runCount++; + if (runCount == 63) { + if (! (i = encput(last, runCount))) + return (0); + total += i; + runCount = 0; + } + } + else { // No "run" - _this != last + if (runCount) { + if (! (i = encput(last, runCount))) + return(0); + total += i; + } + last = _this; + runCount = 1; + } + } // endloop + + if (runCount) { // finish up + if (! (i = encput(last, runCount))) + return (0); + if (inLen % 2) + iputc(0); + return (total + i); + } + else { + if (inLen % 2) + iputc(0); + } + + return (total); +} + +#endif//IL_NO_PCX diff --git a/DevIL/src-IL/src/il_pic.c b/DevIL/src-IL/src/il_pic.c deleted file mode 100644 index 85af4d4e..00000000 --- a/DevIL/src-IL/src/il_pic.c +++ /dev/null @@ -1,425 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_pic.c -// -// Description: Softimage Pic (.pic) functions -// Lots of this code is taken from Paul Bourke's Softimage Pic code at -// http://local.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_PIC -#include "il_pic.h" -#include - - -//! Checks if the file specified in FileName is a valid .pic file. -ILboolean ilIsValidPic(ILconst_string FileName) -{ - ILHANDLE PicFile; - ILboolean bPic = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("pic"))) { - ilSetError(IL_INVALID_EXTENSION); - return bPic; - } - - PicFile = iopenr(FileName); - if (PicFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPic; - } - - bPic = ilIsValidPicF(PicFile); - icloser(PicFile); - - return bPic; -} - - -//! Checks if the ILHANDLE contains a valid .pic file at the current position. -ILboolean ilIsValidPicF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidPic(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .pic lump. -ILboolean ilIsValidPicL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidPic(); -} - - -// Internal function used to get the .pic header from the current file. -ILboolean iGetPicHead(PIC_HEAD *Header) -{ - Header->Magic = GetBigInt(); - Header->Version = GetBigFloat(); - iread(Header->Comment, 1, 80); - iread(Header->Id, 1, 4); - Header->Width = GetBigShort(); - Header->Height = GetBigShort(); - Header->Ratio = GetBigFloat(); - Header->Fields = GetBigShort(); - Header->Padding = GetBigShort(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidPic() -{ - PIC_HEAD Head; - - if (!iGetPicHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(PIC_HEAD), IL_SEEK_CUR); // Go ahead and restore to previous state - - return iCheckPic(&Head); -} - - -// Internal function used to check if the header is a valid .pic header. -ILboolean iCheckPic(PIC_HEAD *Header) -{ - if (Header->Magic != 0x5380F634) - return IL_FALSE; - if (strncmp((const char*)Header->Id, "PICT", 4)) - return IL_FALSE; - if (Header->Width == 0) - return IL_FALSE; - if (Header->Height == 0) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a .pic file -ILboolean ilLoadPic(ILconst_string FileName) -{ - ILHANDLE PicFile; - ILboolean bPic = IL_FALSE; - - PicFile = iopenr(FileName); - if (PicFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPic; - } - - bPic = ilLoadPicF(PicFile); - icloser(PicFile); - - return bPic; -} - - -//! Reads an already-opened .pic file -ILboolean ilLoadPicF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPicInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .pic -ILboolean ilLoadPicL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPicInternal(); -} - - -// Internal function used to load the .pic -ILboolean iLoadPicInternal() -{ - ILuint Alpha = IL_FALSE; - ILubyte Chained; - CHANNEL *Channel = NULL, *Channels = NULL, *Prev; - PIC_HEAD Header; - ILboolean Read; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetPicHead(&Header)) - return IL_FALSE; - if (!iCheckPic(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Read channels - do { - if (Channel == NULL) { - Channel = Channels = (CHANNEL*)ialloc(sizeof(CHANNEL)); - if (Channels == NULL) - return IL_FALSE; - } - else { - Channels->Next = (CHANNEL*)ialloc(sizeof(CHANNEL)); - if (Channels->Next == NULL) { - // Clean up the list before erroring out. - while (Channel) { - Prev = Channel; - Channel = (CHANNEL*)Channel->Next; - ifree(Prev); - } - return IL_FALSE; - } - Channels = (CHANNEL*)Channels->Next; - } - Channels->Next = NULL; - - Chained = igetc(); - Channels->Size = igetc(); - Channels->Type = igetc(); - Channels->Chan = igetc(); - if (ieof()) { - Read = IL_FALSE; - goto finish; - } - - // See if we have an alpha channel in there - if (Channels->Chan & PIC_ALPHA_CHANNEL) - Alpha = IL_TRUE; - - } while (Chained); - - if (Alpha) { // Has an alpha channel - if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { - Read = IL_FALSE; - goto finish; // Have to destroy Channels first. - } - } - else { // No alpha channel - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { - Read = IL_FALSE; - goto finish; // Have to destroy Channels first. - } - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - Read = readScanlines((ILuint*)iCurImage->Data, Header.Width, Header.Height, Channel, Alpha); - -finish: - // Destroy channels - while (Channel) { - Prev = Channel; - Channel = (CHANNEL*)Channel->Next; - ifree(Prev); - } - - if (Read == IL_FALSE) - return IL_FALSE; - - return ilFixImage(); -} - - -ILboolean readScanlines(ILuint *image, ILint width, ILint height, CHANNEL *channel, ILuint alpha) -{ - ILint i; - ILuint *scan; - - (void)alpha; - - for (i = height - 1; i >= 0; i--) { - scan = image + i * width; - - if (!readScanline((ILubyte *)scan, width, channel, alpha ? 4 : 3)) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - } - - return IL_TRUE; -} - - -ILuint readScanline(ILubyte *scan, ILint width, CHANNEL *channel, ILint bytes) -{ - ILint noCol; - ILint off[4]; - ILuint status=0; - - while (channel) { - noCol = 0; - if(channel->Chan & PIC_RED_CHANNEL) { - off[noCol] = 0; - noCol++; - } - if(channel->Chan & PIC_GREEN_CHANNEL) { - off[noCol] = 1; - noCol++; - } - if(channel->Chan & PIC_BLUE_CHANNEL) { - off[noCol] = 2; - noCol++; - } - if(channel->Chan & PIC_ALPHA_CHANNEL) { - off[noCol] = 3; - noCol++; - //@TODO: Find out if this is possible. - if (bytes == 3) // Alpha channel in a 24-bit image. Do not know what to do with this. - return 0; - } - - switch(channel->Type & 0x0F) - { - case PIC_UNCOMPRESSED: - status = channelReadRaw(scan, width, noCol, off, bytes); - break; - case PIC_PURE_RUN_LENGTH: - status = channelReadPure(scan, width, noCol, off, bytes); - break; - case PIC_MIXED_RUN_LENGTH: - status = channelReadMixed(scan, width, noCol, off, bytes); - break; - } - if (!status) - break; - - channel = (CHANNEL*)channel->Next; - } - return status; -} - - -ILboolean channelReadRaw(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) -{ - ILint i, j; - - for (i = 0; i < width; i++) { - if (ieof()) - return IL_FALSE; - for (j = 0; j < noCol; j++) - if (iread(&scan[off[j]], 1, 1) != 1) - return IL_FALSE; - scan += bytes; - } - return IL_TRUE; -} - - -ILboolean channelReadPure(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) -{ - ILubyte col[4]; - ILint count; - int i, j, k; - - for (i = width; i > 0; ) { - count = igetc(); - if (count == IL_EOF) - return IL_FALSE; - if (count > width) - count = width; - i -= count; - - if (ieof()) - return IL_FALSE; - - for (j = 0; j < noCol; j++) - if (iread(&col[j], 1, 1) != 1) - return IL_FALSE; - - for (k = 0; k < count; k++, scan += bytes) { - for(j = 0; j < noCol; j++) - scan[off[j] + k] = col[j]; - } - } - return IL_TRUE; -} - - -ILboolean channelReadMixed(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) -{ - ILint count; - int i, j, k; - ILubyte col[4]; - - for(i = 0; i < width; i += count) { - if (ieof()) - return IL_FALSE; - - count = igetc(); - if (count == IL_EOF) - return IL_FALSE; - - if (count >= 128) { // Repeated sequence - if (count == 128) { // Long run - count = GetBigUShort(); - if (ieof()) { - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; - } - } - else - count -= 127; - - // We've run past... - if ((i + count) > width) { - //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Repeat) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - for (j = 0; j < noCol; j++) - if (iread(&col[j], 1, 1) != 1) { - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; - } - - for (k = 0; k < count; k++, scan += bytes) { - for (j = 0; j < noCol; j++) - scan[off[j]] = col[j]; - } - } else { // Raw sequence - count++; - if ((i + count) > width) { - //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Raw) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - for (k = count; k > 0; k--, scan += bytes) { - for (j = 0; j < noCol; j++) - if (iread(&scan[off[j]], 1, 1) != 1) { - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; - } - } - } - } - - return IL_TRUE; -} - - -#endif//IL_NO_PIC - diff --git a/DevIL/src-IL/src/il_pic.cpp b/DevIL/src-IL/src/il_pic.cpp new file mode 100644 index 00000000..85af4d4e --- /dev/null +++ b/DevIL/src-IL/src/il_pic.cpp @@ -0,0 +1,425 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_pic.c +// +// Description: Softimage Pic (.pic) functions +// Lots of this code is taken from Paul Bourke's Softimage Pic code at +// http://local.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_PIC +#include "il_pic.h" +#include + + +//! Checks if the file specified in FileName is a valid .pic file. +ILboolean ilIsValidPic(ILconst_string FileName) +{ + ILHANDLE PicFile; + ILboolean bPic = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("pic"))) { + ilSetError(IL_INVALID_EXTENSION); + return bPic; + } + + PicFile = iopenr(FileName); + if (PicFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPic; + } + + bPic = ilIsValidPicF(PicFile); + icloser(PicFile); + + return bPic; +} + + +//! Checks if the ILHANDLE contains a valid .pic file at the current position. +ILboolean ilIsValidPicF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidPic(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .pic lump. +ILboolean ilIsValidPicL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidPic(); +} + + +// Internal function used to get the .pic header from the current file. +ILboolean iGetPicHead(PIC_HEAD *Header) +{ + Header->Magic = GetBigInt(); + Header->Version = GetBigFloat(); + iread(Header->Comment, 1, 80); + iread(Header->Id, 1, 4); + Header->Width = GetBigShort(); + Header->Height = GetBigShort(); + Header->Ratio = GetBigFloat(); + Header->Fields = GetBigShort(); + Header->Padding = GetBigShort(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidPic() +{ + PIC_HEAD Head; + + if (!iGetPicHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(PIC_HEAD), IL_SEEK_CUR); // Go ahead and restore to previous state + + return iCheckPic(&Head); +} + + +// Internal function used to check if the header is a valid .pic header. +ILboolean iCheckPic(PIC_HEAD *Header) +{ + if (Header->Magic != 0x5380F634) + return IL_FALSE; + if (strncmp((const char*)Header->Id, "PICT", 4)) + return IL_FALSE; + if (Header->Width == 0) + return IL_FALSE; + if (Header->Height == 0) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a .pic file +ILboolean ilLoadPic(ILconst_string FileName) +{ + ILHANDLE PicFile; + ILboolean bPic = IL_FALSE; + + PicFile = iopenr(FileName); + if (PicFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPic; + } + + bPic = ilLoadPicF(PicFile); + icloser(PicFile); + + return bPic; +} + + +//! Reads an already-opened .pic file +ILboolean ilLoadPicF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPicInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .pic +ILboolean ilLoadPicL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPicInternal(); +} + + +// Internal function used to load the .pic +ILboolean iLoadPicInternal() +{ + ILuint Alpha = IL_FALSE; + ILubyte Chained; + CHANNEL *Channel = NULL, *Channels = NULL, *Prev; + PIC_HEAD Header; + ILboolean Read; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetPicHead(&Header)) + return IL_FALSE; + if (!iCheckPic(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Read channels + do { + if (Channel == NULL) { + Channel = Channels = (CHANNEL*)ialloc(sizeof(CHANNEL)); + if (Channels == NULL) + return IL_FALSE; + } + else { + Channels->Next = (CHANNEL*)ialloc(sizeof(CHANNEL)); + if (Channels->Next == NULL) { + // Clean up the list before erroring out. + while (Channel) { + Prev = Channel; + Channel = (CHANNEL*)Channel->Next; + ifree(Prev); + } + return IL_FALSE; + } + Channels = (CHANNEL*)Channels->Next; + } + Channels->Next = NULL; + + Chained = igetc(); + Channels->Size = igetc(); + Channels->Type = igetc(); + Channels->Chan = igetc(); + if (ieof()) { + Read = IL_FALSE; + goto finish; + } + + // See if we have an alpha channel in there + if (Channels->Chan & PIC_ALPHA_CHANNEL) + Alpha = IL_TRUE; + + } while (Chained); + + if (Alpha) { // Has an alpha channel + if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { + Read = IL_FALSE; + goto finish; // Have to destroy Channels first. + } + } + else { // No alpha channel + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { + Read = IL_FALSE; + goto finish; // Have to destroy Channels first. + } + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + Read = readScanlines((ILuint*)iCurImage->Data, Header.Width, Header.Height, Channel, Alpha); + +finish: + // Destroy channels + while (Channel) { + Prev = Channel; + Channel = (CHANNEL*)Channel->Next; + ifree(Prev); + } + + if (Read == IL_FALSE) + return IL_FALSE; + + return ilFixImage(); +} + + +ILboolean readScanlines(ILuint *image, ILint width, ILint height, CHANNEL *channel, ILuint alpha) +{ + ILint i; + ILuint *scan; + + (void)alpha; + + for (i = height - 1; i >= 0; i--) { + scan = image + i * width; + + if (!readScanline((ILubyte *)scan, width, channel, alpha ? 4 : 3)) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + } + + return IL_TRUE; +} + + +ILuint readScanline(ILubyte *scan, ILint width, CHANNEL *channel, ILint bytes) +{ + ILint noCol; + ILint off[4]; + ILuint status=0; + + while (channel) { + noCol = 0; + if(channel->Chan & PIC_RED_CHANNEL) { + off[noCol] = 0; + noCol++; + } + if(channel->Chan & PIC_GREEN_CHANNEL) { + off[noCol] = 1; + noCol++; + } + if(channel->Chan & PIC_BLUE_CHANNEL) { + off[noCol] = 2; + noCol++; + } + if(channel->Chan & PIC_ALPHA_CHANNEL) { + off[noCol] = 3; + noCol++; + //@TODO: Find out if this is possible. + if (bytes == 3) // Alpha channel in a 24-bit image. Do not know what to do with this. + return 0; + } + + switch(channel->Type & 0x0F) + { + case PIC_UNCOMPRESSED: + status = channelReadRaw(scan, width, noCol, off, bytes); + break; + case PIC_PURE_RUN_LENGTH: + status = channelReadPure(scan, width, noCol, off, bytes); + break; + case PIC_MIXED_RUN_LENGTH: + status = channelReadMixed(scan, width, noCol, off, bytes); + break; + } + if (!status) + break; + + channel = (CHANNEL*)channel->Next; + } + return status; +} + + +ILboolean channelReadRaw(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) +{ + ILint i, j; + + for (i = 0; i < width; i++) { + if (ieof()) + return IL_FALSE; + for (j = 0; j < noCol; j++) + if (iread(&scan[off[j]], 1, 1) != 1) + return IL_FALSE; + scan += bytes; + } + return IL_TRUE; +} + + +ILboolean channelReadPure(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) +{ + ILubyte col[4]; + ILint count; + int i, j, k; + + for (i = width; i > 0; ) { + count = igetc(); + if (count == IL_EOF) + return IL_FALSE; + if (count > width) + count = width; + i -= count; + + if (ieof()) + return IL_FALSE; + + for (j = 0; j < noCol; j++) + if (iread(&col[j], 1, 1) != 1) + return IL_FALSE; + + for (k = 0; k < count; k++, scan += bytes) { + for(j = 0; j < noCol; j++) + scan[off[j] + k] = col[j]; + } + } + return IL_TRUE; +} + + +ILboolean channelReadMixed(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) +{ + ILint count; + int i, j, k; + ILubyte col[4]; + + for(i = 0; i < width; i += count) { + if (ieof()) + return IL_FALSE; + + count = igetc(); + if (count == IL_EOF) + return IL_FALSE; + + if (count >= 128) { // Repeated sequence + if (count == 128) { // Long run + count = GetBigUShort(); + if (ieof()) { + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; + } + } + else + count -= 127; + + // We've run past... + if ((i + count) > width) { + //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Repeat) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + for (j = 0; j < noCol; j++) + if (iread(&col[j], 1, 1) != 1) { + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; + } + + for (k = 0; k < count; k++, scan += bytes) { + for (j = 0; j < noCol; j++) + scan[off[j]] = col[j]; + } + } else { // Raw sequence + count++; + if ((i + count) > width) { + //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Raw) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + for (k = count; k > 0; k--, scan += bytes) { + for (j = 0; j < noCol; j++) + if (iread(&scan[off[j]], 1, 1) != 1) { + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; + } + } + } + } + + return IL_TRUE; +} + + +#endif//IL_NO_PIC + diff --git a/DevIL/src-IL/src/il_pix.c b/DevIL/src-IL/src/il_pix.c deleted file mode 100644 index 2f1b070d..00000000 --- a/DevIL/src-IL/src/il_pix.c +++ /dev/null @@ -1,158 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_pix.c -// -// Description: Reads from an Alias | Wavefront .pix file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_PIX -#include "il_endian.h" - - -#ifdef _MSC_VER -#pragma pack(push, pix_struct, 1) -#endif -typedef struct PIXHEAD -{ - ILushort Width; - ILushort Height; - ILushort OffX; - ILushort OffY; - ILushort Bpp; -} IL_PACKSTRUCT PIXHEAD; -#ifdef _MSC_VER -#pragma pack(pop, pix_struct) -#endif - -ILboolean iCheckPix(PIXHEAD *Header); -ILboolean iLoadPixInternal(void); - - -// Internal function used to get the Pix header from the current file. -ILboolean iGetPixHead(PIXHEAD *Header) -{ - Header->Width = GetBigUShort(); - Header->Height = GetBigUShort(); - Header->OffX = GetBigUShort(); - Header->OffY = GetBigUShort(); - Header->Bpp = GetBigUShort(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidPix() -{ - PIXHEAD Head; - - if (!iGetPixHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(PIXHEAD), IL_SEEK_CUR); - - return iCheckPix(&Head); -} - - -// Internal function used to check if the HEADER is a valid Pix header. -ILboolean iCheckPix(PIXHEAD *Header) -{ - if (Header->Width == 0 || Header->Height == 0) - return IL_FALSE; - if (Header->Bpp != 24) - return IL_FALSE; - //if (Header->OffY != Header->Height) - // return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a Pix file -ILboolean ilLoadPix(ILconst_string FileName) -{ - ILHANDLE PixFile; - ILboolean bPix = IL_FALSE; - - PixFile = iopenr(FileName); - if (PixFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPix; - } - - bPix = ilLoadPixF(PixFile); - icloser(PixFile); - - return bPix; -} - - -//! Reads an already-opened Pix file -ILboolean ilLoadPixF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPixInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Pix -ILboolean ilLoadPixL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPixInternal(); -} - - -// Internal function used to load the Pix. -ILboolean iLoadPixInternal() -{ - PIXHEAD Header; - ILuint i, j; - ILubyte ByteHead, Colour[3]; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetPixHead(&Header)) - return IL_FALSE; - if (!iCheckPix(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - - for (i = 0; i < iCurImage->SizeOfData; ) { - ByteHead = igetc(); - if (iread(Colour, 1, 3) != 3) - return IL_FALSE; - for (j = 0; j < ByteHead; j++) { - iCurImage->Data[i++] = Colour[0]; - iCurImage->Data[i++] = Colour[1]; - iCurImage->Data[i++] = Colour[2]; - } - } - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - return ilFixImage(); -} - -#endif//IL_NO_PIX diff --git a/DevIL/src-IL/src/il_pix.cpp b/DevIL/src-IL/src/il_pix.cpp new file mode 100644 index 00000000..2f1b070d --- /dev/null +++ b/DevIL/src-IL/src/il_pix.cpp @@ -0,0 +1,158 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_pix.c +// +// Description: Reads from an Alias | Wavefront .pix file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_PIX +#include "il_endian.h" + + +#ifdef _MSC_VER +#pragma pack(push, pix_struct, 1) +#endif +typedef struct PIXHEAD +{ + ILushort Width; + ILushort Height; + ILushort OffX; + ILushort OffY; + ILushort Bpp; +} IL_PACKSTRUCT PIXHEAD; +#ifdef _MSC_VER +#pragma pack(pop, pix_struct) +#endif + +ILboolean iCheckPix(PIXHEAD *Header); +ILboolean iLoadPixInternal(void); + + +// Internal function used to get the Pix header from the current file. +ILboolean iGetPixHead(PIXHEAD *Header) +{ + Header->Width = GetBigUShort(); + Header->Height = GetBigUShort(); + Header->OffX = GetBigUShort(); + Header->OffY = GetBigUShort(); + Header->Bpp = GetBigUShort(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidPix() +{ + PIXHEAD Head; + + if (!iGetPixHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(PIXHEAD), IL_SEEK_CUR); + + return iCheckPix(&Head); +} + + +// Internal function used to check if the HEADER is a valid Pix header. +ILboolean iCheckPix(PIXHEAD *Header) +{ + if (Header->Width == 0 || Header->Height == 0) + return IL_FALSE; + if (Header->Bpp != 24) + return IL_FALSE; + //if (Header->OffY != Header->Height) + // return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a Pix file +ILboolean ilLoadPix(ILconst_string FileName) +{ + ILHANDLE PixFile; + ILboolean bPix = IL_FALSE; + + PixFile = iopenr(FileName); + if (PixFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPix; + } + + bPix = ilLoadPixF(PixFile); + icloser(PixFile); + + return bPix; +} + + +//! Reads an already-opened Pix file +ILboolean ilLoadPixF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPixInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Pix +ILboolean ilLoadPixL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPixInternal(); +} + + +// Internal function used to load the Pix. +ILboolean iLoadPixInternal() +{ + PIXHEAD Header; + ILuint i, j; + ILubyte ByteHead, Colour[3]; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetPixHead(&Header)) + return IL_FALSE; + if (!iCheckPix(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + + for (i = 0; i < iCurImage->SizeOfData; ) { + ByteHead = igetc(); + if (iread(Colour, 1, 3) != 3) + return IL_FALSE; + for (j = 0; j < ByteHead; j++) { + iCurImage->Data[i++] = Colour[0]; + iCurImage->Data[i++] = Colour[1]; + iCurImage->Data[i++] = Colour[2]; + } + } + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + return ilFixImage(); +} + +#endif//IL_NO_PIX diff --git a/DevIL/src-IL/src/il_png.c b/DevIL/src-IL/src/il_png.c deleted file mode 100644 index a589dbe8..00000000 --- a/DevIL/src-IL/src/il_png.c +++ /dev/null @@ -1,738 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_png.c -// -// Description: Portable network graphics file (.png) functions -// -//----------------------------------------------------------------------------- - -// Most of the comments are left in this file from libpng's excellent example.c - -#include "il_internal.h" -#ifndef IL_NO_PNG -#include -#include -#if PNG_LIBPNG_VER < 10200 - #warning DevIL was designed with libpng 1.2.0 or higher in mind. Consider upgrading at www.libpng.org. -#endif - -#if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "libpng16_static.lib") - #pragma comment(lib, "zlibstatic.lib") - #else - #pragma comment(lib, "libpng16_staticd.lib") - #pragma comment(lib, "zlibstatic.lib") - #endif - #endif -#endif - - -ILboolean iIsValidPng(void); -ILboolean iLoadPngInternal(void); -ILboolean iSavePngInternal(void); - -ILint readpng_init(void); -ILboolean readpng_get_image(ILdouble display_exponent); -void readpng_cleanup(void); - -png_structp png_ptr = NULL; -png_infop info_ptr = NULL; -ILint png_color_type; - -#define GAMMA_CORRECTION 1.0 // Doesn't seem to be doing anything... - - -ILboolean ilIsValidPng(ILconst_string FileName) -{ - ILHANDLE PngFile; - ILboolean bPng = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("png"))) { - ilSetError(IL_INVALID_EXTENSION); - return bPng; - } - - PngFile = iopenr(FileName); - if (PngFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPng; - } - - bPng = ilIsValidPngF(PngFile); - icloser(PngFile); - - return bPng; -} - - -ILboolean ilIsValidPngF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidPng(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -ILboolean ilIsValidPngL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidPng(); -} - - -ILboolean iIsValidPng() -{ - ILubyte Signature[8]; - ILint Read; - - Read = iread(Signature, 1, 8); - iseek(-Read, IL_SEEK_CUR); - - return !png_sig_cmp(Signature, 0, 8); // DW 5/2/2016: They changed the behavior of this function? -} - - -// Reads a file -ILboolean ilLoadPng(ILconst_string FileName) -{ - ILHANDLE PngFile; - ILboolean bPng = IL_FALSE; - - PngFile = iopenr(FileName); - if (PngFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPng; - } - - bPng = ilLoadPngF(PngFile); - icloser(PngFile); - - return bPng; -} - - -// Reads an already-opened file -ILboolean ilLoadPngF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPngInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -// Reads from a memory "lump" -ILboolean ilLoadPngL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPngInternal(); -} - - -ILboolean iLoadPngInternal() -{ - png_ptr = NULL; - info_ptr = NULL; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - if (!iIsValidPng()) { - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - if (readpng_init()) - return IL_FALSE; - if (!readpng_get_image(GAMMA_CORRECTION)) - return IL_FALSE; - - readpng_cleanup(); - - return ilFixImage(); -} - - -static void png_read(png_structp png_ptr, png_bytep data, png_size_t length) -{ - (void)png_ptr; - iread(data, 1, (ILuint)length); - return; -} - - -static void png_error_func(png_structp png_ptr, png_const_charp message) -{ - ilSetError(IL_LIB_PNG_ERROR); - - /* - changed 20040224 - From the libpng docs: - "Errors handled through png_error() are fatal, meaning that png_error() - should never return to its caller. Currently, this is handled via - setjmp() and longjmp()" - */ - //return; - longjmp(png_jmpbuf(png_ptr), 1); -} - -static void png_warn_func(png_structp png_ptr, png_const_charp message) -{ - return; -} - - -ILint readpng_init() -{ - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func); - if (!png_ptr) - return 4; /* out of memory */ - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - return 4; /* out of memory */ - } - - - /* we could create a second info struct here (end_info), but it's only - * useful if we want to keep pre- and post-IDAT chunk info separated - * (mainly for PNG-aware image editors and converters) */ - - - /* setjmp() must be called in every function that calls a PNG-reading - * libpng function */ - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return 2; - } - - - png_set_read_fn(png_ptr, NULL, png_read); - png_set_error_fn(png_ptr, NULL, png_error_func, png_warn_func); - -// png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ - - png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ - - - /* alternatively, could make separate calls to png_get_image_width(), - * etc., but want bit_depth and png_color_type for later [don't care about - * compression_type and filter_type => NULLs] */ - - /* OK, that's all we need for now; return happy */ - - return 0; -} - - -/* display_exponent == LUT_exponent * CRT_exponent */ - -ILboolean readpng_get_image(ILdouble display_exponent) -{ - png_bytepp row_pointers = NULL; - png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness - ILdouble screen_gamma = 1.0; - ILuint i, channels; - ILenum format; - png_colorp palette; - ILint num_palette, j, bit_depth; -#if _WIN32 || DJGPP - ILdouble image_gamma; -#endif - - /* setjmp() must be called in every function that calls a PNG-reading - * libpng function */ - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return IL_FALSE; - } - - png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, - &bit_depth, &png_color_type, NULL, NULL, NULL); - - // Expand low-bit-depth grayscale images to 8 bits - if (png_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - } - - // Expand RGB images with transparency to full alpha channels - // so the data will be available as RGBA quartets. - // But don't expand paletted images, since we want alpha palettes! - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) && !(png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))) - png_set_tRNS_to_alpha(png_ptr); - - //refresh information (added 20040224) - png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, - &bit_depth, &png_color_type, NULL, NULL, NULL); - - if (bit_depth < 8) { // Expanded earlier for grayscale, now take care of palette and rgb - bit_depth = 8; - png_set_packing(png_ptr); - } - - // Perform gamma correction. - // @TODO: Determine if we should call png_set_gamma if image_gamma is 1.0. -#if _WIN32 || DJGPP - screen_gamma = 2.2; - if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) - png_set_gamma(png_ptr, screen_gamma, image_gamma); -#else - screen_gamma = screen_gamma; -#endif - - //fix endianess -#ifdef __LITTLE_ENDIAN__ - if (bit_depth == 16) - png_set_swap(png_ptr); -#endif - - - png_read_update_info(png_ptr, info_ptr); - channels = (ILint)png_get_channels(png_ptr, info_ptr); - //added 20040224: update png_color_type so that it has the correct value - //in iLoadPngInternal (globals rule...) - png_color_type = png_get_color_type(png_ptr, info_ptr); - - //determine internal format - switch(png_color_type) - { - case PNG_COLOR_TYPE_PALETTE: - format = IL_COLOUR_INDEX; - break; - case PNG_COLOR_TYPE_GRAY: - format = IL_LUMINANCE; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - format = IL_LUMINANCE_ALPHA; - break; - case PNG_COLOR_TYPE_RGB: - format = IL_RGB; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - format = IL_RGBA; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return IL_FALSE; - } - - if (!ilTexImage(width, height, 1, (ILubyte)channels, format, ilGetTypeBpc((ILubyte)(bit_depth >> 3)), NULL)) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - //copy palette - if (format == IL_COLOUR_INDEX) { - int chans; - png_bytep trans = NULL; - int num_trans = -1; - if (!png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return IL_FALSE; - } - - chans = 3; - iCurImage->Pal.PalType = IL_PAL_RGB24; - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); - iCurImage->Pal.PalType = IL_PAL_RGBA32; - chans = 4; - } - - iCurImage->Pal.PalSize = num_palette * chans; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - - for (j = 0; j < num_palette; ++j) { - iCurImage->Pal.Palette[chans*j + 0] = palette[j].red; - iCurImage->Pal.Palette[chans*j + 1] = palette[j].green; - iCurImage->Pal.Palette[chans*j + 2] = palette[j].blue; - if (trans!=NULL) { - if (jPal.Palette[chans*j + 3] = trans[j]; - else - iCurImage->Pal.Palette[chans*j + 3] = 255; - } - } - } - - //allocate row pointers - if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - return IL_FALSE; - } - - - // Set the individual row_pointers to point at the correct offsets */ - for (i = 0; i < height; i++) - row_pointers[i] = iCurImage->Data + i * iCurImage->Bps; - - - // Now we can go ahead and just read the whole image - png_read_image(png_ptr, row_pointers); - - - /* and we're done! (png_read_end() can be omitted if no processing of - * post-IDAT text/time/etc. is desired) */ - //png_read_end(png_ptr, NULL); - ifree(row_pointers); - - return IL_TRUE; -} - - -void readpng_cleanup() -{ - if (png_ptr && info_ptr) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - png_ptr = NULL; - info_ptr = NULL; - } -} - - -//! Writes a Png file -ILboolean ilSavePng(const ILstring FileName) -{ - ILHANDLE PngFile; - ILuint PngSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - PngFile = iopenw(FileName); - if (PngFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - PngSize = ilSavePngF(PngFile); - iclosew(PngFile); - - if (PngSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Png to an already-opened file -ILuint ilSavePngF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSavePngInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Png to a memory "lump" -ILuint ilSavePngL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSavePngInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -void png_write(png_structp png_ptr, png_bytep data, png_size_t length) -{ - (void)png_ptr; - iwrite(data, 1, (ILuint)length); - return; -} - -void flush_data(png_structp png_ptr) -{ - return; -} - - -// Internal function used to save the Png. -ILboolean iSavePngInternal() -{ - png_structp png_ptr; - png_infop info_ptr; - png_text text[4]; - ILenum PngType; - ILuint BitDepth, i, j; - ILubyte **RowPtr = NULL; - ILimage *Temp = NULL; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also check that - * the library version is compatible with the one used at compile time, - * in case we are using dynamically linked libraries. REQUIRED. - */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func); - if (png_ptr == NULL) { - ilSetError(IL_LIB_PNG_ERROR); - return IL_FALSE; - } - - // Allocate/initialize the image information data. REQUIRED - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) { - ilSetError(IL_LIB_PNG_ERROR); - goto error_label; - } - - /*// Set error handling. REQUIRED if you aren't supplying your own - // error handling functions in the png_create_write_struct() call. - if (setjmp(png_jmpbuf(png_ptr))) { - // If we get here, we had a problem reading the file - png_destroy_write_struct(&png_ptr, &info_ptr); - ilSetError(IL_LIB_PNG_ERROR); - return IL_FALSE; - }*/ - -// png_init_io(png_ptr, PngFile); - png_set_write_fn(png_ptr, NULL, png_write, flush_data); - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - Temp = iCurImage; - BitDepth = 8; - break; - case IL_SHORT: - case IL_UNSIGNED_SHORT: - Temp = iCurImage; - BitDepth = 16; - break; - case IL_INT: - case IL_UNSIGNED_INT: - Temp = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_SHORT); - if (Temp == NULL) { - png_destroy_write_struct(&png_ptr, &info_ptr); - return IL_FALSE; - } - BitDepth = 16; - break; - default: - ilSetError(IL_INTERNAL_ERROR); - goto error_label; - } - - switch (iCurImage->Format) - { - case IL_COLOUR_INDEX: - PngType = PNG_COLOR_TYPE_PALETTE; - break; - case IL_LUMINANCE: - PngType = PNG_COLOR_TYPE_GRAY; - break; - case IL_LUMINANCE_ALPHA: //added 20050328 - PngType = PNG_COLOR_TYPE_GRAY_ALPHA; - break; - case IL_RGB: - case IL_BGR: - PngType = PNG_COLOR_TYPE_RGB; - break; - case IL_RGBA: - case IL_BGRA: - PngType = PNG_COLOR_TYPE_RGB_ALPHA; - break; - default: - ilSetError(IL_INTERNAL_ERROR); - goto error_label; - } - - // Set the image information here. Width and height are up to 2^31, - // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on - // the png_color_type selected. png_color_type is one of PNG_COLOR_TYPE_GRAY, - // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, - // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or - // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST - // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED - if (iGetInt(IL_PNG_INTERLACE) == IL_TRUE) { - png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType, - PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - } - else { - png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - } - - // set the palette if there is one. REQUIRED for indexed-color images. - if (iCurImage->Format == IL_COLOUR_INDEX) { - ILpal *TempPal = NULL; - ILint palType; - ILint numCols; - - numCols = ilGetInteger(IL_PALETTE_NUM_COLS); - if(numCols>256) { - numCols = 256; // png maximum - } - - TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_RGB24); - png_set_PLTE(png_ptr, info_ptr, (png_colorp)TempPal->Palette, numCols); - ilClosePal(TempPal); - - palType = ilGetInteger(IL_PALETTE_TYPE); - if( palType==IL_PAL_RGBA32 || palType==IL_PAL_BGRA32 ) { - // the palette has transparency, so we need a tRNS chunk. - png_byte trans[256]; // png supports up to 256 palette entries - int maxTrans = -1; - int i; - for(i=0; iPal.Palette[(4*i) + 3]; - trans[i] = alpha; - if(alpha<255) { - // record the highest non-opaque index - maxTrans = i; - } - } - // only write tRNS chunk if we've got some non-opaque colours - if(maxTrans!=-1) { - png_set_tRNS(png_ptr, info_ptr, trans, maxTrans+1, 0); - } - } - } - - /* - // optional significant bit chunk - // if we are dealing with a grayscale image then - sig_bit.gray = true_bit_depth; - // otherwise, if we are dealing with a color image then - sig_bit.red = true_red_bit_depth; - sig_bit.green = true_green_bit_depth; - sig_bit.blue = true_blue_bit_depth; - // if the image has an alpha channel then - sig_bit.alpha = true_alpha_bit_depth; - png_set_sBIT(png_ptr, info_ptr, sig_bit);*/ - - - /* Optional gamma chunk is strongly suggested if you have any guess - * as to the correct gamma of the image. - */ - //png_set_gAMA(png_ptr, info_ptr, gamma); - - // Optionally write comments into the image. - imemclear(text, sizeof(png_text) * 4); - text[0].key = "Generated by"; - text[0].text = "Generated by the Developer's Image Library (DevIL)"; - text[0].compression = PNG_TEXT_COMPRESSION_NONE; - text[1].key = "Author"; - text[1].text = (char*)iGetString(IL_PNG_AUTHNAME_STRING); // Will not actually be modified! - text[1].compression = PNG_TEXT_COMPRESSION_NONE; - text[2].key = "Description"; - text[2].text = iGetString(IL_PNG_DESCRIPTION_STRING); - text[2].compression = PNG_TEXT_COMPRESSION_NONE; - text[3].key = "Title"; - text[3].text = iGetString(IL_PNG_TITLE_STRING); - text[3].compression = PNG_TEXT_COMPRESSION_NONE; - png_set_text(png_ptr, info_ptr, text, 3); - - // Write the file header information. REQUIRED. - png_write_info(png_ptr, info_ptr); - - // Free up our user-defined text. - if (text[1].text) - ifree(text[1].text); - if (text[2].text) - ifree(text[2].text); - if (text[3].text) - ifree(text[3].text); - - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ - //png_set_shift(png_ptr, &sig_bit); - - /* pack pixels into bytes */ - //png_set_packing(png_ptr); - - // swap location of alpha bytes from ARGB to RGBA - //png_set_swap_alpha(png_ptr); - - // flip BGR pixels to RGB - if (iCurImage->Format == IL_BGR || iCurImage->Format == IL_BGRA) - png_set_bgr(png_ptr); - - // swap bytes of 16-bit files to most significant byte first - #ifdef __LITTLE_ENDIAN__ - png_set_swap(png_ptr); - #endif//__LITTLE_ENDIAN__ - - RowPtr = (ILubyte**)ialloc(iCurImage->Height * sizeof(ILubyte*)); - if (RowPtr == NULL) - goto error_label; - if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) { - for (i = 0; i < iCurImage->Height; i++) { - RowPtr[i] = Temp->Data + i * Temp->Bps; - } - } - else { - j = iCurImage->Height - 1; - for (i = 0; i < iCurImage->Height; i++, j--) { - RowPtr[i] = Temp->Data + j * Temp->Bps; - } - } - - // Writes the image. - png_write_image(png_ptr, RowPtr); - - // It is REQUIRED to call this to finish writing the rest of the file - png_write_end(png_ptr, info_ptr); - - // clean up after the write, and ifree any memory allocated - png_destroy_write_struct(&png_ptr, &info_ptr); - - ifree(RowPtr); - - if (Temp != iCurImage) - ilCloseImage(Temp); - - return IL_TRUE; - -error_label: - png_destroy_write_struct(&png_ptr, &info_ptr); - ifree(RowPtr); - if (Temp != iCurImage) - ilCloseImage(Temp); - return IL_FALSE; -} - - -#endif//IL_NO_PNG diff --git a/DevIL/src-IL/src/il_png.cpp b/DevIL/src-IL/src/il_png.cpp new file mode 100644 index 00000000..a589dbe8 --- /dev/null +++ b/DevIL/src-IL/src/il_png.cpp @@ -0,0 +1,738 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_png.c +// +// Description: Portable network graphics file (.png) functions +// +//----------------------------------------------------------------------------- + +// Most of the comments are left in this file from libpng's excellent example.c + +#include "il_internal.h" +#ifndef IL_NO_PNG +#include +#include +#if PNG_LIBPNG_VER < 10200 + #warning DevIL was designed with libpng 1.2.0 or higher in mind. Consider upgrading at www.libpng.org. +#endif + +#if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "libpng16_static.lib") + #pragma comment(lib, "zlibstatic.lib") + #else + #pragma comment(lib, "libpng16_staticd.lib") + #pragma comment(lib, "zlibstatic.lib") + #endif + #endif +#endif + + +ILboolean iIsValidPng(void); +ILboolean iLoadPngInternal(void); +ILboolean iSavePngInternal(void); + +ILint readpng_init(void); +ILboolean readpng_get_image(ILdouble display_exponent); +void readpng_cleanup(void); + +png_structp png_ptr = NULL; +png_infop info_ptr = NULL; +ILint png_color_type; + +#define GAMMA_CORRECTION 1.0 // Doesn't seem to be doing anything... + + +ILboolean ilIsValidPng(ILconst_string FileName) +{ + ILHANDLE PngFile; + ILboolean bPng = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("png"))) { + ilSetError(IL_INVALID_EXTENSION); + return bPng; + } + + PngFile = iopenr(FileName); + if (PngFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPng; + } + + bPng = ilIsValidPngF(PngFile); + icloser(PngFile); + + return bPng; +} + + +ILboolean ilIsValidPngF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidPng(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +ILboolean ilIsValidPngL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidPng(); +} + + +ILboolean iIsValidPng() +{ + ILubyte Signature[8]; + ILint Read; + + Read = iread(Signature, 1, 8); + iseek(-Read, IL_SEEK_CUR); + + return !png_sig_cmp(Signature, 0, 8); // DW 5/2/2016: They changed the behavior of this function? +} + + +// Reads a file +ILboolean ilLoadPng(ILconst_string FileName) +{ + ILHANDLE PngFile; + ILboolean bPng = IL_FALSE; + + PngFile = iopenr(FileName); + if (PngFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPng; + } + + bPng = ilLoadPngF(PngFile); + icloser(PngFile); + + return bPng; +} + + +// Reads an already-opened file +ILboolean ilLoadPngF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPngInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +// Reads from a memory "lump" +ILboolean ilLoadPngL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPngInternal(); +} + + +ILboolean iLoadPngInternal() +{ + png_ptr = NULL; + info_ptr = NULL; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + if (!iIsValidPng()) { + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + if (readpng_init()) + return IL_FALSE; + if (!readpng_get_image(GAMMA_CORRECTION)) + return IL_FALSE; + + readpng_cleanup(); + + return ilFixImage(); +} + + +static void png_read(png_structp png_ptr, png_bytep data, png_size_t length) +{ + (void)png_ptr; + iread(data, 1, (ILuint)length); + return; +} + + +static void png_error_func(png_structp png_ptr, png_const_charp message) +{ + ilSetError(IL_LIB_PNG_ERROR); + + /* + changed 20040224 + From the libpng docs: + "Errors handled through png_error() are fatal, meaning that png_error() + should never return to its caller. Currently, this is handled via + setjmp() and longjmp()" + */ + //return; + longjmp(png_jmpbuf(png_ptr), 1); +} + +static void png_warn_func(png_structp png_ptr, png_const_charp message) +{ + return; +} + + +ILint readpng_init() +{ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func); + if (!png_ptr) + return 4; /* out of memory */ + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return 4; /* out of memory */ + } + + + /* we could create a second info struct here (end_info), but it's only + * useful if we want to keep pre- and post-IDAT chunk info separated + * (mainly for PNG-aware image editors and converters) */ + + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 2; + } + + + png_set_read_fn(png_ptr, NULL, png_read); + png_set_error_fn(png_ptr, NULL, png_error_func, png_warn_func); + +// png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ + + png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ + + + /* alternatively, could make separate calls to png_get_image_width(), + * etc., but want bit_depth and png_color_type for later [don't care about + * compression_type and filter_type => NULLs] */ + + /* OK, that's all we need for now; return happy */ + + return 0; +} + + +/* display_exponent == LUT_exponent * CRT_exponent */ + +ILboolean readpng_get_image(ILdouble display_exponent) +{ + png_bytepp row_pointers = NULL; + png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness + ILdouble screen_gamma = 1.0; + ILuint i, channels; + ILenum format; + png_colorp palette; + ILint num_palette, j, bit_depth; +#if _WIN32 || DJGPP + ILdouble image_gamma; +#endif + + /* setjmp() must be called in every function that calls a PNG-reading + * libpng function */ + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return IL_FALSE; + } + + png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, + &bit_depth, &png_color_type, NULL, NULL, NULL); + + // Expand low-bit-depth grayscale images to 8 bits + if (png_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + } + + // Expand RGB images with transparency to full alpha channels + // so the data will be available as RGBA quartets. + // But don't expand paletted images, since we want alpha palettes! + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) && !(png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))) + png_set_tRNS_to_alpha(png_ptr); + + //refresh information (added 20040224) + png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, + &bit_depth, &png_color_type, NULL, NULL, NULL); + + if (bit_depth < 8) { // Expanded earlier for grayscale, now take care of palette and rgb + bit_depth = 8; + png_set_packing(png_ptr); + } + + // Perform gamma correction. + // @TODO: Determine if we should call png_set_gamma if image_gamma is 1.0. +#if _WIN32 || DJGPP + screen_gamma = 2.2; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) + png_set_gamma(png_ptr, screen_gamma, image_gamma); +#else + screen_gamma = screen_gamma; +#endif + + //fix endianess +#ifdef __LITTLE_ENDIAN__ + if (bit_depth == 16) + png_set_swap(png_ptr); +#endif + + + png_read_update_info(png_ptr, info_ptr); + channels = (ILint)png_get_channels(png_ptr, info_ptr); + //added 20040224: update png_color_type so that it has the correct value + //in iLoadPngInternal (globals rule...) + png_color_type = png_get_color_type(png_ptr, info_ptr); + + //determine internal format + switch(png_color_type) + { + case PNG_COLOR_TYPE_PALETTE: + format = IL_COLOUR_INDEX; + break; + case PNG_COLOR_TYPE_GRAY: + format = IL_LUMINANCE; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + format = IL_LUMINANCE_ALPHA; + break; + case PNG_COLOR_TYPE_RGB: + format = IL_RGB; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + format = IL_RGBA; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return IL_FALSE; + } + + if (!ilTexImage(width, height, 1, (ILubyte)channels, format, ilGetTypeBpc((ILubyte)(bit_depth >> 3)), NULL)) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + //copy palette + if (format == IL_COLOUR_INDEX) { + int chans; + png_bytep trans = NULL; + int num_trans = -1; + if (!png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return IL_FALSE; + } + + chans = 3; + iCurImage->Pal.PalType = IL_PAL_RGB24; + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + iCurImage->Pal.PalType = IL_PAL_RGBA32; + chans = 4; + } + + iCurImage->Pal.PalSize = num_palette * chans; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + + for (j = 0; j < num_palette; ++j) { + iCurImage->Pal.Palette[chans*j + 0] = palette[j].red; + iCurImage->Pal.Palette[chans*j + 1] = palette[j].green; + iCurImage->Pal.Palette[chans*j + 2] = palette[j].blue; + if (trans!=NULL) { + if (jPal.Palette[chans*j + 3] = trans[j]; + else + iCurImage->Pal.Palette[chans*j + 3] = 255; + } + } + } + + //allocate row pointers + if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return IL_FALSE; + } + + + // Set the individual row_pointers to point at the correct offsets */ + for (i = 0; i < height; i++) + row_pointers[i] = iCurImage->Data + i * iCurImage->Bps; + + + // Now we can go ahead and just read the whole image + png_read_image(png_ptr, row_pointers); + + + /* and we're done! (png_read_end() can be omitted if no processing of + * post-IDAT text/time/etc. is desired) */ + //png_read_end(png_ptr, NULL); + ifree(row_pointers); + + return IL_TRUE; +} + + +void readpng_cleanup() +{ + if (png_ptr && info_ptr) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + png_ptr = NULL; + info_ptr = NULL; + } +} + + +//! Writes a Png file +ILboolean ilSavePng(const ILstring FileName) +{ + ILHANDLE PngFile; + ILuint PngSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + PngFile = iopenw(FileName); + if (PngFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + PngSize = ilSavePngF(PngFile); + iclosew(PngFile); + + if (PngSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Png to an already-opened file +ILuint ilSavePngF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSavePngInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Png to a memory "lump" +ILuint ilSavePngL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSavePngInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +void png_write(png_structp png_ptr, png_bytep data, png_size_t length) +{ + (void)png_ptr; + iwrite(data, 1, (ILuint)length); + return; +} + +void flush_data(png_structp png_ptr) +{ + return; +} + + +// Internal function used to save the Png. +ILboolean iSavePngInternal() +{ + png_structp png_ptr; + png_infop info_ptr; + png_text text[4]; + ILenum PngType; + ILuint BitDepth, i, j; + ILubyte **RowPtr = NULL; + ILimage *Temp = NULL; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func); + if (png_ptr == NULL) { + ilSetError(IL_LIB_PNG_ERROR); + return IL_FALSE; + } + + // Allocate/initialize the image information data. REQUIRED + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + ilSetError(IL_LIB_PNG_ERROR); + goto error_label; + } + + /*// Set error handling. REQUIRED if you aren't supplying your own + // error handling functions in the png_create_write_struct() call. + if (setjmp(png_jmpbuf(png_ptr))) { + // If we get here, we had a problem reading the file + png_destroy_write_struct(&png_ptr, &info_ptr); + ilSetError(IL_LIB_PNG_ERROR); + return IL_FALSE; + }*/ + +// png_init_io(png_ptr, PngFile); + png_set_write_fn(png_ptr, NULL, png_write, flush_data); + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + Temp = iCurImage; + BitDepth = 8; + break; + case IL_SHORT: + case IL_UNSIGNED_SHORT: + Temp = iCurImage; + BitDepth = 16; + break; + case IL_INT: + case IL_UNSIGNED_INT: + Temp = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_SHORT); + if (Temp == NULL) { + png_destroy_write_struct(&png_ptr, &info_ptr); + return IL_FALSE; + } + BitDepth = 16; + break; + default: + ilSetError(IL_INTERNAL_ERROR); + goto error_label; + } + + switch (iCurImage->Format) + { + case IL_COLOUR_INDEX: + PngType = PNG_COLOR_TYPE_PALETTE; + break; + case IL_LUMINANCE: + PngType = PNG_COLOR_TYPE_GRAY; + break; + case IL_LUMINANCE_ALPHA: //added 20050328 + PngType = PNG_COLOR_TYPE_GRAY_ALPHA; + break; + case IL_RGB: + case IL_BGR: + PngType = PNG_COLOR_TYPE_RGB; + break; + case IL_RGBA: + case IL_BGRA: + PngType = PNG_COLOR_TYPE_RGB_ALPHA; + break; + default: + ilSetError(IL_INTERNAL_ERROR); + goto error_label; + } + + // Set the image information here. Width and height are up to 2^31, + // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + // the png_color_type selected. png_color_type is one of PNG_COLOR_TYPE_GRAY, + // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + if (iGetInt(IL_PNG_INTERLACE) == IL_TRUE) { + png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType, + PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + } + else { + png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + } + + // set the palette if there is one. REQUIRED for indexed-color images. + if (iCurImage->Format == IL_COLOUR_INDEX) { + ILpal *TempPal = NULL; + ILint palType; + ILint numCols; + + numCols = ilGetInteger(IL_PALETTE_NUM_COLS); + if(numCols>256) { + numCols = 256; // png maximum + } + + TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_RGB24); + png_set_PLTE(png_ptr, info_ptr, (png_colorp)TempPal->Palette, numCols); + ilClosePal(TempPal); + + palType = ilGetInteger(IL_PALETTE_TYPE); + if( palType==IL_PAL_RGBA32 || palType==IL_PAL_BGRA32 ) { + // the palette has transparency, so we need a tRNS chunk. + png_byte trans[256]; // png supports up to 256 palette entries + int maxTrans = -1; + int i; + for(i=0; iPal.Palette[(4*i) + 3]; + trans[i] = alpha; + if(alpha<255) { + // record the highest non-opaque index + maxTrans = i; + } + } + // only write tRNS chunk if we've got some non-opaque colours + if(maxTrans!=-1) { + png_set_tRNS(png_ptr, info_ptr, trans, maxTrans+1, 0); + } + } + } + + /* + // optional significant bit chunk + // if we are dealing with a grayscale image then + sig_bit.gray = true_bit_depth; + // otherwise, if we are dealing with a color image then + sig_bit.red = true_red_bit_depth; + sig_bit.green = true_green_bit_depth; + sig_bit.blue = true_blue_bit_depth; + // if the image has an alpha channel then + sig_bit.alpha = true_alpha_bit_depth; + png_set_sBIT(png_ptr, info_ptr, sig_bit);*/ + + + /* Optional gamma chunk is strongly suggested if you have any guess + * as to the correct gamma of the image. + */ + //png_set_gAMA(png_ptr, info_ptr, gamma); + + // Optionally write comments into the image. + imemclear(text, sizeof(png_text) * 4); + text[0].key = "Generated by"; + text[0].text = "Generated by the Developer's Image Library (DevIL)"; + text[0].compression = PNG_TEXT_COMPRESSION_NONE; + text[1].key = "Author"; + text[1].text = (char*)iGetString(IL_PNG_AUTHNAME_STRING); // Will not actually be modified! + text[1].compression = PNG_TEXT_COMPRESSION_NONE; + text[2].key = "Description"; + text[2].text = iGetString(IL_PNG_DESCRIPTION_STRING); + text[2].compression = PNG_TEXT_COMPRESSION_NONE; + text[3].key = "Title"; + text[3].text = iGetString(IL_PNG_TITLE_STRING); + text[3].compression = PNG_TEXT_COMPRESSION_NONE; + png_set_text(png_ptr, info_ptr, text, 3); + + // Write the file header information. REQUIRED. + png_write_info(png_ptr, info_ptr); + + // Free up our user-defined text. + if (text[1].text) + ifree(text[1].text); + if (text[2].text) + ifree(text[2].text); + if (text[3].text) + ifree(text[3].text); + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + //png_set_shift(png_ptr, &sig_bit); + + /* pack pixels into bytes */ + //png_set_packing(png_ptr); + + // swap location of alpha bytes from ARGB to RGBA + //png_set_swap_alpha(png_ptr); + + // flip BGR pixels to RGB + if (iCurImage->Format == IL_BGR || iCurImage->Format == IL_BGRA) + png_set_bgr(png_ptr); + + // swap bytes of 16-bit files to most significant byte first + #ifdef __LITTLE_ENDIAN__ + png_set_swap(png_ptr); + #endif//__LITTLE_ENDIAN__ + + RowPtr = (ILubyte**)ialloc(iCurImage->Height * sizeof(ILubyte*)); + if (RowPtr == NULL) + goto error_label; + if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) { + for (i = 0; i < iCurImage->Height; i++) { + RowPtr[i] = Temp->Data + i * Temp->Bps; + } + } + else { + j = iCurImage->Height - 1; + for (i = 0; i < iCurImage->Height; i++, j--) { + RowPtr[i] = Temp->Data + j * Temp->Bps; + } + } + + // Writes the image. + png_write_image(png_ptr, RowPtr); + + // It is REQUIRED to call this to finish writing the rest of the file + png_write_end(png_ptr, info_ptr); + + // clean up after the write, and ifree any memory allocated + png_destroy_write_struct(&png_ptr, &info_ptr); + + ifree(RowPtr); + + if (Temp != iCurImage) + ilCloseImage(Temp); + + return IL_TRUE; + +error_label: + png_destroy_write_struct(&png_ptr, &info_ptr); + ifree(RowPtr); + if (Temp != iCurImage) + ilCloseImage(Temp); + return IL_FALSE; +} + + +#endif//IL_NO_PNG diff --git a/DevIL/src-IL/src/il_pnm.c b/DevIL/src-IL/src/il_pnm.c deleted file mode 100644 index a46fe4c4..00000000 --- a/DevIL/src-IL/src/il_pnm.c +++ /dev/null @@ -1,697 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_pnm.c -// -// Description: Reads/writes to/from pbm/pgm/ppm formats (enough slashes? =) -// -//----------------------------------------------------------------------------- - - - -#include "il_internal.h" -#ifndef IL_NO_PNM -#include "il_pnm.h" -#include // for maximum values -#include -#include "il_bits.h" - -// According to the ppm specs, it's 70, but PSP -// likes to output longer lines. -#define MAX_BUFFER 180 -static ILbyte LineBuffer[MAX_BUFFER]; -static ILbyte SmallBuff[MAX_BUFFER]; - -// Can't read direct bits from a lump yet -ILboolean IsLump = IL_FALSE; - - -//! Checks if the file specified in FileName is a valid .pnm file. -ILboolean ilIsValidPnm(ILconst_string FileName) -{ - ILHANDLE PnmFile; - ILboolean bPnm = IL_FALSE; - - if ( !iCheckExtension(FileName, IL_TEXT("pbm")) - && !iCheckExtension(FileName, IL_TEXT("pgm")) - && !iCheckExtension(FileName, IL_TEXT("ppm")) - && !iCheckExtension(FileName, IL_TEXT("pnm"))) { - ilSetError(IL_INVALID_EXTENSION); - return bPnm; - } - - PnmFile = iopenr(FileName); - if (PnmFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPnm; - } - - bPnm = ilIsValidPnmF(PnmFile); - icloser(PnmFile); - - return bPnm; -} - - -//! Checks if the ILHANDLE contains a valid .pnm file at the current position. -ILboolean ilIsValidPnmF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidPnm(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid .pnm lump. -ILboolean ilIsValidPnmL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidPnm(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidPnm() -{ - char Head[2]; - ILint Read; - - Read = iread(Head, 1, 2); - iseek(-Read, IL_SEEK_CUR); // Go ahead and restore to previous state - if (Read != 2) - return IL_FALSE; - - return iCheckPnm(Head); -} - - -// Internal function used to check if the HEADER is a valid .pnm header. -ILboolean iCheckPnm(char Header[2]) -{ - if (Header[0] != 'P') - return IL_FALSE; - switch (Header[1]) - { - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - return IL_TRUE; - } - - return IL_FALSE; -} - - -// Reads a file -ILboolean ilLoadPnm(ILconst_string FileName) -{ - ILHANDLE PnmFile; - ILboolean bPnm = IL_FALSE; - - PnmFile = iopenr(FileName); - if (PnmFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPnm; - } - - bPnm = ilLoadPnmF(PnmFile); - icloser(PnmFile); - - return bPnm; -} - - -// Reads an already-opened file -ILboolean ilLoadPnmF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPnmInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -// Reads from a memory "lump" -ILboolean ilLoadPnmL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPnmInternal(); -} - - -// Load either a pgm or a ppm -ILboolean iLoadPnmInternal() -{ - ILimage *PmImage = NULL; - PPMINFO Info; -// ILuint LineInc = 0, SmallInc = 0; - - Info.Type = 0; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - // Find out what type of pgm/ppm this is - if (iGetWord(IL_FALSE) == IL_FALSE) - return IL_FALSE; - - if (SmallBuff[0] != 'P') { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - switch( SmallBuff[1] ) { - case '1': - Info.Type = IL_PBM_ASCII; - break; - case '2': - Info.Type = IL_PGM_ASCII; - break; - case '3': - Info.Type = IL_PPM_ASCII; - break; - case '4': - Info.Type = IL_PBM_BINARY; - if (IsLump) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - break; - case '5': - Info.Type = IL_PGM_BINARY; - break; - case '6': - Info.Type = IL_PPM_BINARY; - break; - default: - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Retrieve the width and height - if (iGetWord(IL_FALSE) == IL_FALSE) - return IL_FALSE; - Info.Width = atoi((const char*)SmallBuff); - if (Info.Width == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (iGetWord(IL_FALSE) == IL_FALSE) - return IL_FALSE; - Info.Height = atoi((const char*)SmallBuff); - if (Info.Height == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Retrieve the maximum colour component value - if (Info.Type != IL_PBM_ASCII && Info.Type != IL_PBM_BINARY) { - if (iGetWord(IL_TRUE) == IL_FALSE) - return IL_FALSE; - if ((Info.MaxColour = atoi((const char*)SmallBuff)) == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - } else { - Info.MaxColour = 1; - } - - if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY || - Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) { - if (Info.Type == IL_PGM_ASCII) { - Info.Bpp = Info.MaxColour < 256 ? 1 : 2; - } else { - Info.Bpp = 1; - } - } else { - Info.Bpp = 3; - } - - switch (Info.Type) { - case IL_PBM_ASCII: - case IL_PGM_ASCII: - case IL_PPM_ASCII: - PmImage = ilReadAsciiPpm(&Info); - break; - case IL_PBM_BINARY: - PmImage = ilReadBitPbm(&Info); - break; - case IL_PGM_BINARY: - case IL_PPM_BINARY: - PmImage = ilReadBinaryPpm(&Info); - break; - default: - return IL_FALSE; - } - - if (PmImage == NULL) { - iCurImage->Format = ilGetFormatBpp(iCurImage->Bpp); - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; - } - - // Is this conversion needed? Just 0's and 1's shows up as all black - if (Info.Type == IL_PBM_ASCII) { - PbmMaximize(PmImage); - } - - if (Info.MaxColour > 255) - PmImage->Type = IL_UNSIGNED_SHORT; - PmImage->Origin = IL_ORIGIN_UPPER_LEFT; - if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY || - Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) - PmImage->Format = IL_LUMINANCE; - else - PmImage->Format = IL_RGB; - PmImage->Origin = IL_ORIGIN_UPPER_LEFT; - - if (PmImage == NULL) - return IL_FALSE; - return ilFixImage(); -} - - - -ILimage *ilReadAsciiPpm(PPMINFO *Info) -{ - ILint LineInc = 0, SmallInc = 0, DataInc = 0, Size; -// ILint BytesRead = 0; - - if (Info->MaxColour > 255) - Info->Bpp *= 2; - - Size = Info->Width * Info->Height * Info->Bpp; - - if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - if (Info->MaxColour > 255) - iCurImage->Type = IL_UNSIGNED_SHORT; - - while (DataInc < Size) { // && !feof(File)) { - LineInc = 0; - - if (iFgets((char *)LineBuffer, MAX_BUFFER) == NULL) { - //ilSetError(IL_ILLEGAL_FILE_VALUE); - //return NULL; - //return iCurImage; - break; - } - if (LineBuffer[0] == '#') { // Comment - continue; - } - - while ((LineBuffer[LineInc] != NUL) && (LineBuffer[LineInc] != '\n')) { - - SmallInc = 0; - while (!isalnum(LineBuffer[LineInc])) { // Skip any whitespace - LineInc++; - } - while (isalnum(LineBuffer[LineInc])) { - SmallBuff[SmallInc] = LineBuffer[LineInc]; - SmallInc++; - LineInc++; - } - SmallBuff[SmallInc] = NUL; - iCurImage->Data[DataInc] = atoi((const char*)SmallBuff); // Convert from string to colour - - // PSP likes to put whitespace at the end of lines...figures. =/ - while (!isalnum(LineBuffer[LineInc]) && LineBuffer[LineInc] != NUL) { // Skip any whitespace - LineInc++; - } - - // We should set some kind of state flag that enables this - //Image->Data[DataInc] *= (ILubyte)(255 / Info->MaxColour); // Scales to 0-255 - if (Info->MaxColour > 255) - DataInc++; - DataInc++; - } - } - - // If we read less than what we should have... - if (DataInc < Size) { - //ilCloseImage(iCurImage); - //ilSetCurImage(NULL); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return NULL; - } - - return iCurImage; -} - - -ILimage *ilReadBinaryPpm(PPMINFO *Info) -{ - ILuint Size; - - Size = Info->Width * Info->Height * Info->Bpp; - - if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - /* 4/3/2007 Dario Meloni - Here it seems we have eaten too much bytes and it is needed to fix - the starting point - works well on various images - - No more need of this workaround. fixed iGetWord - iseek(0,IL_SEEK_END); - ILuint size = itell(); - iseek(size-Size,IL_SEEK_SET); - */ - if (iread(iCurImage->Data, 1, Size ) != Size) { - ilCloseImage(iCurImage); - return NULL; - } - return iCurImage; -} - - -ILimage *ilReadBitPbm(PPMINFO *Info) -{ - ILuint m, j, x, CurrByte; - - if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - x = 0; - for (j = 0; j < iCurImage->SizeOfData;) { - CurrByte = igetc(); - for (m = 128; m > 0 && x < Info->Width; m >>= 1, ++x, ++j) { - iCurImage->Data[j] = (CurrByte & m)?255:0; - } - if (x == Info->Width) - x = 0; - } - - return iCurImage; -} - - -ILboolean iGetWord(ILboolean final) -{ - ILint WordPos = 0; - ILint Current = 0; - ILboolean Started = IL_FALSE; - ILboolean Looping = IL_TRUE; - - if (ieof()) - return IL_FALSE; - - while (Looping) { - while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') { - if (WordPos >= MAX_BUFFER) // We have hit the maximum line length. - return IL_FALSE; - - if (!isalnum(Current)) { - if (Started) { - Looping = IL_FALSE; - break; - } - continue; - } - - if (Looping) - SmallBuff[WordPos++] = Current; - } - if (Current == IL_EOF) - return IL_FALSE; - SmallBuff[WordPos] = 0; // 08-17-2008 - was NULL, changed to avoid warning - if (final == IL_TRUE) - break; - - if (!Looping) - break; - - if (Current == '#') { // '#' is a comment...read until end of line - while ((Current = igetc()) != IL_EOF && Current != '\n'); - } - - // Get rid of any erroneous spaces - while ((Current = igetc()) != IL_EOF) { - if (Current != ' ') - break; - } - iseek(-1, IL_SEEK_CUR); - - if (WordPos > 0) - break; - } - - if (Current == -1 || WordPos == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - return IL_TRUE; -} - - -ILstring FName = NULL; - -//! Writes a Pnm file -ILboolean ilSavePnm(const ILstring FileName) -{ - ILHANDLE PnmFile; - ILuint PnmSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - PnmFile = iopenw(FileName); - if (PnmFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - PnmSize = ilSavePnmF(PnmFile); - iclosew(PnmFile); - - if (PnmSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Pnm to an already-opened file -ILuint ilSavePnmF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSavePnmInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Pnm to a memory "lump" -ILuint ilSavePnmL(void *Lump, ILuint Size) -{ - ILuint Pos; - FName = NULL; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSavePnmInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the Pnm. -ILboolean iSavePnmInternal() -{ - ILuint Bpp, MaxVal = UCHAR_MAX, i = 0, j, k; - ILenum Type = 0; - ILuint LinePos = 0; // Cannot exceed 70 for pnm's! - ILboolean Binary; - ILimage *TempImage; - ILubyte *TempData; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (iCheckExtension(FName, IL_TEXT("pbm"))) - Type = IL_PBM_ASCII; - else if (iCheckExtension(FName, IL_TEXT("pgm"))) - Type = IL_PGM_ASCII; - else if (iCheckExtension(FName, IL_TEXT("ppm"))) - Type = IL_PPM_ASCII; - else - Type = IL_PPM_ASCII; - - /*if (!Type) { - ilSetError(IL_INVALID_EXTENSION); - return IL_FALSE; - }*/ - - if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) { - Type += 3; - Binary = IL_TRUE; - } - else { - Binary = IL_FALSE; - } - - if (iCurImage->Type == IL_UNSIGNED_BYTE) { - MaxVal = UCHAR_MAX; - } - else if (iCurImage->Type == IL_UNSIGNED_SHORT) { - MaxVal = USHRT_MAX; - } - else { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - if (MaxVal > UCHAR_MAX && Type >= IL_PBM_BINARY) { // binary cannot be higher than 255 - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - switch (Type) - { - case IL_PBM_ASCII: - Bpp = 1; - ilprintf("P1\n"); - TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE); - break; - //case IL_PBM_BINARY: // Don't want to mess with saving bits just yet... - //Bpp = 1; - //ilprintf("P4\n"); - //break; - case IL_PBM_BINARY: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - case IL_PGM_ASCII: - Bpp = 1; - ilprintf("P2\n"); - TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE); - break; - case IL_PGM_BINARY: - Bpp = 1; - ilprintf("P5\n"); - TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE); - break; - case IL_PPM_ASCII: - Bpp = 3; - ilprintf("P3\n"); - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - break; - case IL_PPM_BINARY: - Bpp = 3; - ilprintf("P6\n"); - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - break; - default: - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - if (TempImage == NULL) - return IL_FALSE; - - if (Bpp != TempImage->Bpp) { - ilSetError(IL_INVALID_CONVERSION); - return IL_FALSE; - } - - if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - ilCloseImage(TempImage); - return IL_FALSE; - } - } - else { - TempData = TempImage->Data; - } - - ilprintf("%d %d\n", TempImage->Width, TempImage->Height); - if (Type != IL_PBM_BINARY && Type != IL_PBM_ASCII) // not needed for .pbm's (only 0 and 1) - ilprintf("%d\n", MaxVal); - - while (i < TempImage->SizeOfPlane) { - for (j = 0; j < Bpp; j++) { - if (Binary) { - if (Type == IL_PBM_BINARY) { - iputc((ILubyte)(TempData[i] > 127 ? 1 : 0)); - } - else { - iputc(TempData[i]); - } - } - else { - if (TempImage->Type == IL_UNSIGNED_BYTE) - k = TempData[i]; - else // IL_UNSIGNED_SHORT - k = *((ILushort*)TempData + i); - if (Type == IL_PBM_ASCII) { - LinePos += ilprintf("%d ", TempData[i] > 127 ? 1 : 0); - } - else { - LinePos += ilprintf("%d ", TempData[i]); - } - } - - if (TempImage->Type == IL_UNSIGNED_SHORT) - i++; - i++; - } - - if (LinePos > 65) { // Just a good number =] - ilprintf("\n"); - LinePos = 0; - } - } - - if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) - ifree(TempData); - ilCloseImage(TempImage); - - return IL_TRUE; -} - - -// Converts a .pbm to something viewable. -void PbmMaximize(ILimage *Image) -{ - ILuint i = 0; - for (i = 0; i < Image->SizeOfPlane; i++) - if (Image->Data[i] == 1) - Image->Data[i] = 0xFF; - return; -} - - -#endif//IL_NO_PNM diff --git a/DevIL/src-IL/src/il_pnm.cpp b/DevIL/src-IL/src/il_pnm.cpp new file mode 100644 index 00000000..a46fe4c4 --- /dev/null +++ b/DevIL/src-IL/src/il_pnm.cpp @@ -0,0 +1,697 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_pnm.c +// +// Description: Reads/writes to/from pbm/pgm/ppm formats (enough slashes? =) +// +//----------------------------------------------------------------------------- + + + +#include "il_internal.h" +#ifndef IL_NO_PNM +#include "il_pnm.h" +#include // for maximum values +#include +#include "il_bits.h" + +// According to the ppm specs, it's 70, but PSP +// likes to output longer lines. +#define MAX_BUFFER 180 +static ILbyte LineBuffer[MAX_BUFFER]; +static ILbyte SmallBuff[MAX_BUFFER]; + +// Can't read direct bits from a lump yet +ILboolean IsLump = IL_FALSE; + + +//! Checks if the file specified in FileName is a valid .pnm file. +ILboolean ilIsValidPnm(ILconst_string FileName) +{ + ILHANDLE PnmFile; + ILboolean bPnm = IL_FALSE; + + if ( !iCheckExtension(FileName, IL_TEXT("pbm")) + && !iCheckExtension(FileName, IL_TEXT("pgm")) + && !iCheckExtension(FileName, IL_TEXT("ppm")) + && !iCheckExtension(FileName, IL_TEXT("pnm"))) { + ilSetError(IL_INVALID_EXTENSION); + return bPnm; + } + + PnmFile = iopenr(FileName); + if (PnmFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPnm; + } + + bPnm = ilIsValidPnmF(PnmFile); + icloser(PnmFile); + + return bPnm; +} + + +//! Checks if the ILHANDLE contains a valid .pnm file at the current position. +ILboolean ilIsValidPnmF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidPnm(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid .pnm lump. +ILboolean ilIsValidPnmL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidPnm(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidPnm() +{ + char Head[2]; + ILint Read; + + Read = iread(Head, 1, 2); + iseek(-Read, IL_SEEK_CUR); // Go ahead and restore to previous state + if (Read != 2) + return IL_FALSE; + + return iCheckPnm(Head); +} + + +// Internal function used to check if the HEADER is a valid .pnm header. +ILboolean iCheckPnm(char Header[2]) +{ + if (Header[0] != 'P') + return IL_FALSE; + switch (Header[1]) + { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + return IL_TRUE; + } + + return IL_FALSE; +} + + +// Reads a file +ILboolean ilLoadPnm(ILconst_string FileName) +{ + ILHANDLE PnmFile; + ILboolean bPnm = IL_FALSE; + + PnmFile = iopenr(FileName); + if (PnmFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPnm; + } + + bPnm = ilLoadPnmF(PnmFile); + icloser(PnmFile); + + return bPnm; +} + + +// Reads an already-opened file +ILboolean ilLoadPnmF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPnmInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +// Reads from a memory "lump" +ILboolean ilLoadPnmL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPnmInternal(); +} + + +// Load either a pgm or a ppm +ILboolean iLoadPnmInternal() +{ + ILimage *PmImage = NULL; + PPMINFO Info; +// ILuint LineInc = 0, SmallInc = 0; + + Info.Type = 0; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + // Find out what type of pgm/ppm this is + if (iGetWord(IL_FALSE) == IL_FALSE) + return IL_FALSE; + + if (SmallBuff[0] != 'P') { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + switch( SmallBuff[1] ) { + case '1': + Info.Type = IL_PBM_ASCII; + break; + case '2': + Info.Type = IL_PGM_ASCII; + break; + case '3': + Info.Type = IL_PPM_ASCII; + break; + case '4': + Info.Type = IL_PBM_BINARY; + if (IsLump) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + break; + case '5': + Info.Type = IL_PGM_BINARY; + break; + case '6': + Info.Type = IL_PPM_BINARY; + break; + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Retrieve the width and height + if (iGetWord(IL_FALSE) == IL_FALSE) + return IL_FALSE; + Info.Width = atoi((const char*)SmallBuff); + if (Info.Width == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (iGetWord(IL_FALSE) == IL_FALSE) + return IL_FALSE; + Info.Height = atoi((const char*)SmallBuff); + if (Info.Height == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Retrieve the maximum colour component value + if (Info.Type != IL_PBM_ASCII && Info.Type != IL_PBM_BINARY) { + if (iGetWord(IL_TRUE) == IL_FALSE) + return IL_FALSE; + if ((Info.MaxColour = atoi((const char*)SmallBuff)) == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + } else { + Info.MaxColour = 1; + } + + if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY || + Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) { + if (Info.Type == IL_PGM_ASCII) { + Info.Bpp = Info.MaxColour < 256 ? 1 : 2; + } else { + Info.Bpp = 1; + } + } else { + Info.Bpp = 3; + } + + switch (Info.Type) { + case IL_PBM_ASCII: + case IL_PGM_ASCII: + case IL_PPM_ASCII: + PmImage = ilReadAsciiPpm(&Info); + break; + case IL_PBM_BINARY: + PmImage = ilReadBitPbm(&Info); + break; + case IL_PGM_BINARY: + case IL_PPM_BINARY: + PmImage = ilReadBinaryPpm(&Info); + break; + default: + return IL_FALSE; + } + + if (PmImage == NULL) { + iCurImage->Format = ilGetFormatBpp(iCurImage->Bpp); + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; + } + + // Is this conversion needed? Just 0's and 1's shows up as all black + if (Info.Type == IL_PBM_ASCII) { + PbmMaximize(PmImage); + } + + if (Info.MaxColour > 255) + PmImage->Type = IL_UNSIGNED_SHORT; + PmImage->Origin = IL_ORIGIN_UPPER_LEFT; + if (Info.Type == IL_PBM_ASCII || Info.Type == IL_PBM_BINARY || + Info.Type == IL_PGM_ASCII || Info.Type == IL_PGM_BINARY) + PmImage->Format = IL_LUMINANCE; + else + PmImage->Format = IL_RGB; + PmImage->Origin = IL_ORIGIN_UPPER_LEFT; + + if (PmImage == NULL) + return IL_FALSE; + return ilFixImage(); +} + + + +ILimage *ilReadAsciiPpm(PPMINFO *Info) +{ + ILint LineInc = 0, SmallInc = 0, DataInc = 0, Size; +// ILint BytesRead = 0; + + if (Info->MaxColour > 255) + Info->Bpp *= 2; + + Size = Info->Width * Info->Height * Info->Bpp; + + if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + if (Info->MaxColour > 255) + iCurImage->Type = IL_UNSIGNED_SHORT; + + while (DataInc < Size) { // && !feof(File)) { + LineInc = 0; + + if (iFgets((char *)LineBuffer, MAX_BUFFER) == NULL) { + //ilSetError(IL_ILLEGAL_FILE_VALUE); + //return NULL; + //return iCurImage; + break; + } + if (LineBuffer[0] == '#') { // Comment + continue; + } + + while ((LineBuffer[LineInc] != NUL) && (LineBuffer[LineInc] != '\n')) { + + SmallInc = 0; + while (!isalnum(LineBuffer[LineInc])) { // Skip any whitespace + LineInc++; + } + while (isalnum(LineBuffer[LineInc])) { + SmallBuff[SmallInc] = LineBuffer[LineInc]; + SmallInc++; + LineInc++; + } + SmallBuff[SmallInc] = NUL; + iCurImage->Data[DataInc] = atoi((const char*)SmallBuff); // Convert from string to colour + + // PSP likes to put whitespace at the end of lines...figures. =/ + while (!isalnum(LineBuffer[LineInc]) && LineBuffer[LineInc] != NUL) { // Skip any whitespace + LineInc++; + } + + // We should set some kind of state flag that enables this + //Image->Data[DataInc] *= (ILubyte)(255 / Info->MaxColour); // Scales to 0-255 + if (Info->MaxColour > 255) + DataInc++; + DataInc++; + } + } + + // If we read less than what we should have... + if (DataInc < Size) { + //ilCloseImage(iCurImage); + //ilSetCurImage(NULL); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return NULL; + } + + return iCurImage; +} + + +ILimage *ilReadBinaryPpm(PPMINFO *Info) +{ + ILuint Size; + + Size = Info->Width * Info->Height * Info->Bpp; + + if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + /* 4/3/2007 Dario Meloni + Here it seems we have eaten too much bytes and it is needed to fix + the starting point + works well on various images + + No more need of this workaround. fixed iGetWord + iseek(0,IL_SEEK_END); + ILuint size = itell(); + iseek(size-Size,IL_SEEK_SET); + */ + if (iread(iCurImage->Data, 1, Size ) != Size) { + ilCloseImage(iCurImage); + return NULL; + } + return iCurImage; +} + + +ILimage *ilReadBitPbm(PPMINFO *Info) +{ + ILuint m, j, x, CurrByte; + + if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + x = 0; + for (j = 0; j < iCurImage->SizeOfData;) { + CurrByte = igetc(); + for (m = 128; m > 0 && x < Info->Width; m >>= 1, ++x, ++j) { + iCurImage->Data[j] = (CurrByte & m)?255:0; + } + if (x == Info->Width) + x = 0; + } + + return iCurImage; +} + + +ILboolean iGetWord(ILboolean final) +{ + ILint WordPos = 0; + ILint Current = 0; + ILboolean Started = IL_FALSE; + ILboolean Looping = IL_TRUE; + + if (ieof()) + return IL_FALSE; + + while (Looping) { + while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') { + if (WordPos >= MAX_BUFFER) // We have hit the maximum line length. + return IL_FALSE; + + if (!isalnum(Current)) { + if (Started) { + Looping = IL_FALSE; + break; + } + continue; + } + + if (Looping) + SmallBuff[WordPos++] = Current; + } + if (Current == IL_EOF) + return IL_FALSE; + SmallBuff[WordPos] = 0; // 08-17-2008 - was NULL, changed to avoid warning + if (final == IL_TRUE) + break; + + if (!Looping) + break; + + if (Current == '#') { // '#' is a comment...read until end of line + while ((Current = igetc()) != IL_EOF && Current != '\n'); + } + + // Get rid of any erroneous spaces + while ((Current = igetc()) != IL_EOF) { + if (Current != ' ') + break; + } + iseek(-1, IL_SEEK_CUR); + + if (WordPos > 0) + break; + } + + if (Current == -1 || WordPos == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + return IL_TRUE; +} + + +ILstring FName = NULL; + +//! Writes a Pnm file +ILboolean ilSavePnm(const ILstring FileName) +{ + ILHANDLE PnmFile; + ILuint PnmSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + PnmFile = iopenw(FileName); + if (PnmFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + PnmSize = ilSavePnmF(PnmFile); + iclosew(PnmFile); + + if (PnmSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Pnm to an already-opened file +ILuint ilSavePnmF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSavePnmInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Pnm to a memory "lump" +ILuint ilSavePnmL(void *Lump, ILuint Size) +{ + ILuint Pos; + FName = NULL; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSavePnmInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the Pnm. +ILboolean iSavePnmInternal() +{ + ILuint Bpp, MaxVal = UCHAR_MAX, i = 0, j, k; + ILenum Type = 0; + ILuint LinePos = 0; // Cannot exceed 70 for pnm's! + ILboolean Binary; + ILimage *TempImage; + ILubyte *TempData; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (iCheckExtension(FName, IL_TEXT("pbm"))) + Type = IL_PBM_ASCII; + else if (iCheckExtension(FName, IL_TEXT("pgm"))) + Type = IL_PGM_ASCII; + else if (iCheckExtension(FName, IL_TEXT("ppm"))) + Type = IL_PPM_ASCII; + else + Type = IL_PPM_ASCII; + + /*if (!Type) { + ilSetError(IL_INVALID_EXTENSION); + return IL_FALSE; + }*/ + + if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) { + Type += 3; + Binary = IL_TRUE; + } + else { + Binary = IL_FALSE; + } + + if (iCurImage->Type == IL_UNSIGNED_BYTE) { + MaxVal = UCHAR_MAX; + } + else if (iCurImage->Type == IL_UNSIGNED_SHORT) { + MaxVal = USHRT_MAX; + } + else { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + if (MaxVal > UCHAR_MAX && Type >= IL_PBM_BINARY) { // binary cannot be higher than 255 + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + switch (Type) + { + case IL_PBM_ASCII: + Bpp = 1; + ilprintf("P1\n"); + TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE); + break; + //case IL_PBM_BINARY: // Don't want to mess with saving bits just yet... + //Bpp = 1; + //ilprintf("P4\n"); + //break; + case IL_PBM_BINARY: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + case IL_PGM_ASCII: + Bpp = 1; + ilprintf("P2\n"); + TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE); + break; + case IL_PGM_BINARY: + Bpp = 1; + ilprintf("P5\n"); + TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE); + break; + case IL_PPM_ASCII: + Bpp = 3; + ilprintf("P3\n"); + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + break; + case IL_PPM_BINARY: + Bpp = 3; + ilprintf("P6\n"); + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + break; + default: + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + if (TempImage == NULL) + return IL_FALSE; + + if (Bpp != TempImage->Bpp) { + ilSetError(IL_INVALID_CONVERSION); + return IL_FALSE; + } + + if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + ilCloseImage(TempImage); + return IL_FALSE; + } + } + else { + TempData = TempImage->Data; + } + + ilprintf("%d %d\n", TempImage->Width, TempImage->Height); + if (Type != IL_PBM_BINARY && Type != IL_PBM_ASCII) // not needed for .pbm's (only 0 and 1) + ilprintf("%d\n", MaxVal); + + while (i < TempImage->SizeOfPlane) { + for (j = 0; j < Bpp; j++) { + if (Binary) { + if (Type == IL_PBM_BINARY) { + iputc((ILubyte)(TempData[i] > 127 ? 1 : 0)); + } + else { + iputc(TempData[i]); + } + } + else { + if (TempImage->Type == IL_UNSIGNED_BYTE) + k = TempData[i]; + else // IL_UNSIGNED_SHORT + k = *((ILushort*)TempData + i); + if (Type == IL_PBM_ASCII) { + LinePos += ilprintf("%d ", TempData[i] > 127 ? 1 : 0); + } + else { + LinePos += ilprintf("%d ", TempData[i]); + } + } + + if (TempImage->Type == IL_UNSIGNED_SHORT) + i++; + i++; + } + + if (LinePos > 65) { // Just a good number =] + ilprintf("\n"); + LinePos = 0; + } + } + + if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) + ifree(TempData); + ilCloseImage(TempImage); + + return IL_TRUE; +} + + +// Converts a .pbm to something viewable. +void PbmMaximize(ILimage *Image) +{ + ILuint i = 0; + for (i = 0; i < Image->SizeOfPlane; i++) + if (Image->Data[i] == 1) + Image->Data[i] = 0xFF; + return; +} + + +#endif//IL_NO_PNM diff --git a/DevIL/src-IL/src/il_profiles.c b/DevIL/src-IL/src/il_profiles.c deleted file mode 100644 index 80e416cc..00000000 --- a/DevIL/src-IL/src/il_profiles.c +++ /dev/null @@ -1,174 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2002 by Denton Woods -// Last modified: 01/23/2001 <--Y2K Compliant! =] -// -// Filename: src-IL/src/il_profiles.c -// -// Description: Colour profile handler -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_LCMS - -#ifdef PACKAGE_NAME -#define IL_PACKAGE_NAME PACKAGE_NAME; -#undef PACKAGE_NAME -#endif - -#if (!defined(_WIN32) && !defined(_WIN64)) - #define NON_WINDOWS 1 - #ifdef LCMS_NODIRINCLUDE - #include - #else - #include - #endif - -#else - #if defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "lcms2_static.lib") - #else - #pragma comment(lib, "lcms2_static.lib") - #endif - #endif - #endif - - #include -#endif//_WIN32 - -#ifdef PACKAGE_NAME -#undef PACKAGE_NAME -#endif - -#ifdef IL_PACKAGE_NAME -#define PACKAGE_NAME IL_PACKAGE_NAME -#undef IL_PACKAGE_NAME -#endif - -#endif//IL_NO_LCMS - -ILboolean ILAPIENTRY ilApplyProfile(ILstring InProfile, ILstring OutProfile) -{ -#ifndef IL_NO_LCMS - cmsHPROFILE hInProfile, hOutProfile; - cmsHTRANSFORM hTransform; - ILubyte *Temp; - ILint Format=0; -#ifdef _UNICODE - char AnsiName[512]; -#endif//_UNICODE - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - switch (iCurImage->Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - switch (iCurImage->Format) - { - case IL_LUMINANCE: - Format = TYPE_GRAY_8; - break; - case IL_RGB: - Format = TYPE_RGB_8; - break; - case IL_BGR: - Format = TYPE_BGR_8; - break; - case IL_RGBA: - Format = TYPE_RGBA_8; - break; - case IL_BGRA: - Format = TYPE_BGRA_8; - break; - default: - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - break; - - case IL_SHORT: - case IL_UNSIGNED_SHORT: - switch (iCurImage->Format) - { - case IL_LUMINANCE: - Format = TYPE_GRAY_16; - break; - case IL_RGB: - Format = TYPE_RGB_16; - break; - case IL_BGR: - Format = TYPE_BGR_16; - break; - case IL_RGBA: - Format = TYPE_RGBA_16; - break; - case IL_BGRA: - Format = TYPE_BGRA_16; - break; - default: - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - break; - - // These aren't supported right now. - case IL_INT: - case IL_UNSIGNED_INT: - case IL_FLOAT: - case IL_DOUBLE: - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - - if (InProfile == NULL) { - if (!iCurImage->Profile || !iCurImage->ProfileSize) { - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - hInProfile = iCurImage->Profile; - } - else { -#ifndef _UNICODE - hInProfile = cmsOpenProfileFromFile(InProfile, "r"); -#else - wcstombs(AnsiName, InProfile, 512); - hInProfile = cmsOpenProfileFromFile(AnsiName, "r"); -#endif//_UNICODE - } -#ifndef _UNICODE - hOutProfile = cmsOpenProfileFromFile(OutProfile, "r"); -#else - wcstombs(AnsiName, OutProfile, 512); - hOutProfile = cmsOpenProfileFromFile(AnsiName, "r"); -#endif//_UNICODE - - hTransform = cmsCreateTransform(hInProfile, Format, hOutProfile, Format, INTENT_PERCEPTUAL, 0); - - Temp = (ILubyte*)ialloc(iCurImage->SizeOfData); - if (Temp == NULL) { - return IL_FALSE; - } - - cmsDoTransform(hTransform, iCurImage->Data, Temp, iCurImage->SizeOfData / 3); - - ifree(iCurImage->Data); - iCurImage->Data = Temp; - - cmsDeleteTransform(hTransform); - if (InProfile != NULL) - cmsCloseProfile(hInProfile); - cmsCloseProfile(hOutProfile); - -#endif//IL_NO_LCMS - - return IL_TRUE; -} diff --git a/DevIL/src-IL/src/il_profiles.cpp b/DevIL/src-IL/src/il_profiles.cpp new file mode 100644 index 00000000..80e416cc --- /dev/null +++ b/DevIL/src-IL/src/il_profiles.cpp @@ -0,0 +1,174 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2002 by Denton Woods +// Last modified: 01/23/2001 <--Y2K Compliant! =] +// +// Filename: src-IL/src/il_profiles.c +// +// Description: Colour profile handler +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_LCMS + +#ifdef PACKAGE_NAME +#define IL_PACKAGE_NAME PACKAGE_NAME; +#undef PACKAGE_NAME +#endif + +#if (!defined(_WIN32) && !defined(_WIN64)) + #define NON_WINDOWS 1 + #ifdef LCMS_NODIRINCLUDE + #include + #else + #include + #endif + +#else + #if defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "lcms2_static.lib") + #else + #pragma comment(lib, "lcms2_static.lib") + #endif + #endif + #endif + + #include +#endif//_WIN32 + +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif + +#ifdef IL_PACKAGE_NAME +#define PACKAGE_NAME IL_PACKAGE_NAME +#undef IL_PACKAGE_NAME +#endif + +#endif//IL_NO_LCMS + +ILboolean ILAPIENTRY ilApplyProfile(ILstring InProfile, ILstring OutProfile) +{ +#ifndef IL_NO_LCMS + cmsHPROFILE hInProfile, hOutProfile; + cmsHTRANSFORM hTransform; + ILubyte *Temp; + ILint Format=0; +#ifdef _UNICODE + char AnsiName[512]; +#endif//_UNICODE + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + switch (iCurImage->Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + switch (iCurImage->Format) + { + case IL_LUMINANCE: + Format = TYPE_GRAY_8; + break; + case IL_RGB: + Format = TYPE_RGB_8; + break; + case IL_BGR: + Format = TYPE_BGR_8; + break; + case IL_RGBA: + Format = TYPE_RGBA_8; + break; + case IL_BGRA: + Format = TYPE_BGRA_8; + break; + default: + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + break; + + case IL_SHORT: + case IL_UNSIGNED_SHORT: + switch (iCurImage->Format) + { + case IL_LUMINANCE: + Format = TYPE_GRAY_16; + break; + case IL_RGB: + Format = TYPE_RGB_16; + break; + case IL_BGR: + Format = TYPE_BGR_16; + break; + case IL_RGBA: + Format = TYPE_RGBA_16; + break; + case IL_BGRA: + Format = TYPE_BGRA_16; + break; + default: + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + break; + + // These aren't supported right now. + case IL_INT: + case IL_UNSIGNED_INT: + case IL_FLOAT: + case IL_DOUBLE: + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + + if (InProfile == NULL) { + if (!iCurImage->Profile || !iCurImage->ProfileSize) { + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + hInProfile = iCurImage->Profile; + } + else { +#ifndef _UNICODE + hInProfile = cmsOpenProfileFromFile(InProfile, "r"); +#else + wcstombs(AnsiName, InProfile, 512); + hInProfile = cmsOpenProfileFromFile(AnsiName, "r"); +#endif//_UNICODE + } +#ifndef _UNICODE + hOutProfile = cmsOpenProfileFromFile(OutProfile, "r"); +#else + wcstombs(AnsiName, OutProfile, 512); + hOutProfile = cmsOpenProfileFromFile(AnsiName, "r"); +#endif//_UNICODE + + hTransform = cmsCreateTransform(hInProfile, Format, hOutProfile, Format, INTENT_PERCEPTUAL, 0); + + Temp = (ILubyte*)ialloc(iCurImage->SizeOfData); + if (Temp == NULL) { + return IL_FALSE; + } + + cmsDoTransform(hTransform, iCurImage->Data, Temp, iCurImage->SizeOfData / 3); + + ifree(iCurImage->Data); + iCurImage->Data = Temp; + + cmsDeleteTransform(hTransform); + if (InProfile != NULL) + cmsCloseProfile(hInProfile); + cmsCloseProfile(hOutProfile); + +#endif//IL_NO_LCMS + + return IL_TRUE; +} diff --git a/DevIL/src-IL/src/il_psd.c b/DevIL/src-IL/src/il_psd.c deleted file mode 100644 index 257584c2..00000000 --- a/DevIL/src-IL/src/il_psd.c +++ /dev/null @@ -1,1086 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_psd.c -// -// Description: Reads and writes Photoshop (.psd) files. -// -//----------------------------------------------------------------------------- - - -// Information about the .psd format was taken from Adobe's PhotoShop SDK at -// http://partners.adobe.com/asn/developer/gapsdk/PhotoshopSDK.html -// Information about the Packbits compression scheme was found at -// http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf - -#include "il_internal.h" -#ifndef IL_NO_PSD -#include "il_psd.h" - -static float ubyte_to_float(ILubyte val) -{ - return ((float)val) / 255.0f; -} -static float ushort_to_float(ILushort val) -{ - return ((float)val) / 65535.0f; -} - -static ILubyte float_to_ubyte(float val) -{ - return (ILubyte)(val * 255.0f); -} -static ILushort float_to_ushort(float val) -{ - return (ILushort)(val * 65535.0f); -} - - -//! Checks if the file specified in FileName is a valid Psd file. -ILboolean ilIsValidPsd(ILconst_string FileName) -{ - ILHANDLE PsdFile; - ILboolean bPsd = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("psd")) && - !iCheckExtension(FileName, IL_TEXT("pdd"))) { - ilSetError(IL_INVALID_EXTENSION); - return bPsd; - } - - PsdFile = iopenr(FileName); - if (PsdFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPsd; - } - - bPsd = ilIsValidPsdF(PsdFile); - icloser(PsdFile); - - return bPsd; -} - - -//! Checks if the ILHANDLE contains a valid Psd file at the current position. -ILboolean ilIsValidPsdF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidPsd(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid Psd lump. -ILboolean ilIsValidPsdL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidPsd(); -} - - -// Internal function used to get the Psd header from the current file. -ILboolean iGetPsdHead(PSDHEAD *Header) -{ - iread(Header->Signature, 1, 4); - Header->Version = GetBigUShort(); - iread(Header->Reserved, 1, 6); - Header->Channels = GetBigUShort(); - Header->Height = GetBigUInt(); - Header->Width = GetBigUInt(); - Header->Depth = GetBigUShort(); - Header->Mode = GetBigUShort(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidPsd() -{ - PSDHEAD Head; - - iGetPsdHead(&Head); - iseek(-(ILint)sizeof(PSDHEAD), IL_SEEK_CUR); - - return iCheckPsd(&Head); -} - - -// Internal function used to check if the HEADER is a valid Psd header. -ILboolean iCheckPsd(PSDHEAD *Header) -{ - ILuint i; - - if (strncmp((char*)Header->Signature, "8BPS", 4)) - return IL_FALSE; - if (Header->Version != 1) - return IL_FALSE; - for (i = 0; i < 6; i++) { - if (Header->Reserved[i] != 0) - return IL_FALSE; - } - if (Header->Channels < 1 || Header->Channels > 24) - return IL_FALSE; - if (Header->Height < 1 || Header->Width < 1) - return IL_FALSE; - if (Header->Depth != 1 && Header->Depth != 8 && Header->Depth != 16) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a Psd file -ILboolean ilLoadPsd(ILconst_string FileName) -{ - ILHANDLE PsdFile; - ILboolean bPsd = IL_FALSE; - - PsdFile = iopenr(FileName); - if (PsdFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPsd; - } - - bPsd = ilLoadPsdF(PsdFile); - icloser(PsdFile); - - return bPsd; -} - - -//! Reads an already-opened Psd file -ILboolean ilLoadPsdF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPsdInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Psd -ILboolean ilLoadPsdL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPsdInternal(); -} - - -// Internal function used to load the Psd. -ILboolean iLoadPsdInternal() -{ - PSDHEAD Header; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iGetPsdHead(&Header); - if (!iCheckPsd(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ReadPsd(&Header)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - return ilFixImage(); -} - - -ILboolean ReadPsd(PSDHEAD *Head) -{ - switch (Head->Mode) - { - case 1: // Greyscale - return ReadGrey(Head); - case 2: // Indexed - return ReadIndexed(Head); - case 3: // RGB - return ReadRGB(Head); - case 4: // CMYK - return ReadCMYK(Head); - } - - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; -} - - -ILboolean ReadGrey(PSDHEAD *Head) -{ - ILuint ColorMode, ResourceSize, MiscInfo; - ILushort Compressed; - ILenum Type; - ILubyte *Resources = NULL; - - ColorMode = GetBigUInt(); // Skip over the 'color mode data section' - iseek(ColorMode, IL_SEEK_CUR); - - ResourceSize = GetBigUInt(); // Read the 'image resources section' - Resources = (ILubyte*)ialloc(ResourceSize); - if (Resources == NULL) { - return IL_FALSE; - } - if (iread(Resources, 1, ResourceSize) != ResourceSize) - goto cleanup_error; - - MiscInfo = GetBigUInt(); - iseek(MiscInfo, IL_SEEK_CUR); - - Compressed = GetBigUShort(); - - ChannelNum = Head->Channels; - Head->Channels = 1; // Temporary to read only one channel...some greyscale .psd files have 2. - if (Head->Channels != 1) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - switch (Head->Depth) - { - case 8: - Type = IL_UNSIGNED_BYTE; - break; - case 16: - Type = IL_UNSIGNED_SHORT; - break; - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_LUMINANCE, Type, NULL)) - goto cleanup_error; - if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) - goto cleanup_error; - if (!ParseResources(ResourceSize, Resources)) - goto cleanup_error; - ifree(Resources); - - return IL_TRUE; - -cleanup_error: - ifree(Resources); - return IL_FALSE; -} - - -ILboolean ReadIndexed(PSDHEAD *Head) -{ - ILuint ColorMode, ResourceSize, MiscInfo, i, j, NumEnt; - ILushort Compressed; - ILubyte *Palette = NULL, *Resources = NULL; - - ColorMode = GetBigUInt(); // Skip over the 'color mode data section' - if (ColorMode % 3 != 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - Palette = (ILubyte*)ialloc(ColorMode); - if (Palette == NULL) - return IL_FALSE; - if (iread(Palette, 1, ColorMode) != ColorMode) - goto cleanup_error; - - ResourceSize = GetBigUInt(); // Read the 'image resources section' - Resources = (ILubyte*)ialloc(ResourceSize); - if (Resources == NULL) { - return IL_FALSE; - } - if (iread(Resources, 1, ResourceSize) != ResourceSize) - goto cleanup_error; - - MiscInfo = GetBigUInt(); - if (ieof()) - goto cleanup_error; - iseek(MiscInfo, IL_SEEK_CUR); - - Compressed = GetBigUShort(); - if (ieof()) - goto cleanup_error; - - if (Head->Channels != 1 || Head->Depth != 8) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - goto cleanup_error; - } - ChannelNum = Head->Channels; - - if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - goto cleanup_error; - - iCurImage->Pal.Palette = (ILubyte*)ialloc(ColorMode); - if (iCurImage->Pal.Palette == NULL) { - goto cleanup_error; - } - iCurImage->Pal.PalSize = ColorMode; - iCurImage->Pal.PalType = IL_PAL_RGB24; - - NumEnt = iCurImage->Pal.PalSize / 3; - for (i = 0, j = 0; i < iCurImage->Pal.PalSize; i += 3, j++) { - iCurImage->Pal.Palette[i ] = Palette[j]; - iCurImage->Pal.Palette[i+1] = Palette[j+NumEnt]; - iCurImage->Pal.Palette[i+2] = Palette[j+NumEnt*2]; - } - ifree(Palette); - Palette = NULL; - - if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) - goto cleanup_error; - - ParseResources(ResourceSize, Resources); - ifree(Resources); - Resources = NULL; - - return IL_TRUE; - -cleanup_error: - ifree(Palette); - ifree(Resources); - - return IL_FALSE; -} - - -ILboolean ReadRGB(PSDHEAD *Head) -{ - ILuint ColorMode, ResourceSize, MiscInfo; - ILushort Compressed; - ILenum Format, Type; - ILubyte *Resources = NULL; - - ColorMode = GetBigUInt(); // Skip over the 'color mode data section' - iseek(ColorMode, IL_SEEK_CUR); - - ResourceSize = GetBigUInt(); // Read the 'image resources section' - Resources = (ILubyte*)ialloc(ResourceSize); - if (Resources == NULL) - return IL_FALSE; - if (iread(Resources, 1, ResourceSize) != ResourceSize) - goto cleanup_error; - - MiscInfo = GetBigUInt(); - iseek(MiscInfo, IL_SEEK_CUR); - - Compressed = GetBigUShort(); - - ChannelNum = Head->Channels; - if (Head->Channels == 3) - { - Format = IL_RGB; - } - else if (Head->Channels == 4) - { - Format = IL_RGBA; - } - else if (Head->Channels >= 5) - { - // Additional channels are accumulated as a single alpha channel, since - // if an image does not have a layer set as the "background", but also - // has a real alpha channel, there will be 5 channels (or more). - Format = IL_RGBA; - } - else - { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - switch (Head->Depth) - { - case 8: - Type = IL_UNSIGNED_BYTE; - break; - case 16: - Type = IL_UNSIGNED_SHORT; - break; - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - if (!ilTexImage(Head->Width, Head->Height, 1, (Format==IL_RGB) ? 3 : 4, Format, Type, NULL)) - goto cleanup_error; - if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) - goto cleanup_error; - if (!ParseResources(ResourceSize, Resources)) - goto cleanup_error; - ifree(Resources); - - return IL_TRUE; - -cleanup_error: - ifree(Resources); - return IL_FALSE; -} - - -ILboolean ReadCMYK(PSDHEAD *Head) -{ - ILuint ColorMode, ResourceSize, MiscInfo, Size, i, j; - ILushort Compressed; - ILenum Format, Type; - ILubyte *Resources = NULL, *KChannel = NULL; - - ColorMode = GetBigUInt(); // Skip over the 'color mode data section' - iseek(ColorMode, IL_SEEK_CUR); - - ResourceSize = GetBigUInt(); // Read the 'image resources section' - Resources = (ILubyte*)ialloc(ResourceSize); - if (Resources == NULL) { - return IL_FALSE; - } - if (iread(Resources, 1, ResourceSize) != ResourceSize) - goto cleanup_error; - - MiscInfo = GetBigUInt(); - iseek(MiscInfo, IL_SEEK_CUR); - - Compressed = GetBigUShort(); - - switch (Head->Channels) - { - case 4: - Format = IL_RGB; - ChannelNum = 4; - Head->Channels = 3; - break; - case 5: - Format = IL_RGBA; - ChannelNum = 5; - Head->Channels = 4; - break; - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - switch (Head->Depth) - { - case 8: - Type = IL_UNSIGNED_BYTE; - break; - case 16: - Type = IL_UNSIGNED_SHORT; - break; - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - if (!ilTexImage(Head->Width, Head->Height, 1, (ILubyte)Head->Channels, Format, Type, NULL)) - goto cleanup_error; - if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) - goto cleanup_error; - - Size = iCurImage->Bpc * iCurImage->Width * iCurImage->Height; - KChannel = (ILubyte*)ialloc(Size); - if (KChannel == NULL) - goto cleanup_error; - if (!GetSingleChannel(Head, KChannel, (ILboolean)Compressed)) - goto cleanup_error; - - if (Format == IL_RGB) { - for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 3, j++) { - iCurImage->Data[i ] = (iCurImage->Data[i ] * KChannel[j]) >> 8; - iCurImage->Data[i+1] = (iCurImage->Data[i+1] * KChannel[j]) >> 8; - iCurImage->Data[i+2] = (iCurImage->Data[i+2] * KChannel[j]) >> 8; - } - } - else { // IL_RGBA - // The KChannel array really holds the alpha channel on this one. - for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 4, j++) { - iCurImage->Data[i ] = (iCurImage->Data[i ] * iCurImage->Data[i+3]) >> 8; - iCurImage->Data[i+1] = (iCurImage->Data[i+1] * iCurImage->Data[i+3]) >> 8; - iCurImage->Data[i+2] = (iCurImage->Data[i+2] * iCurImage->Data[i+3]) >> 8; - iCurImage->Data[i+3] = KChannel[j]; // Swap 'K' with alpha channel. - } - } - - if (!ParseResources(ResourceSize, Resources)) - goto cleanup_error; - - ifree(Resources); - ifree(KChannel); - - return IL_TRUE; - -cleanup_error: - ifree(Resources); - ifree(KChannel); - return IL_FALSE; -} - - -ILuint *GetCompChanLen(PSDHEAD *Head) -{ - ILushort *RleTable; - ILuint *ChanLen, c, i, j; - - RleTable = (ILushort*)ialloc(Head->Height * ChannelNum * sizeof(ILushort)); - ChanLen = (ILuint*)ialloc(ChannelNum * sizeof(ILuint)); - if (RleTable == NULL || ChanLen == NULL) { - return NULL; - } - - if (iread(RleTable, sizeof(ILushort), Head->Height * ChannelNum) != Head->Height * ChannelNum) { - ifree(RleTable); - ifree(ChanLen); - return NULL; - } -#ifdef __LITTLE_ENDIAN__ - for (i = 0; i < Head->Height * ChannelNum; i++) { - iSwapUShort(&RleTable[i]); - } -#endif - - imemclear(ChanLen, ChannelNum * sizeof(ILuint)); - for (c = 0; c < ChannelNum; c++) { - j = c * Head->Height; - for (i = 0; i < Head->Height; i++) { - ChanLen[c] += RleTable[i + j]; - } - } - - ifree(RleTable); - - return ChanLen; -} - - - -static const ILuint READ_COMPRESSED_SUCCESS = 0; -static const ILuint READ_COMPRESSED_ERROR_FILE_CORRUPT = 1; -static const ILuint READ_COMPRESSED_ERROR_FILE_READ_ERROR = 2; - -static ILuint ReadCompressedChannel(const ILuint ChanLen, ILuint Size, ILubyte* Channel) -{ - ILuint i; - ILint Run; - ILboolean PreCache = IL_FALSE; - ILbyte HeadByte; - - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - PreCache = IL_TRUE; - - if (PreCache) - iPreCache(ChanLen); - for (i = 0; i < Size; ) { - HeadByte = igetc(); - - if (HeadByte >= 0) { // && HeadByte <= 127 - if (i + HeadByte > Size) - { - if (PreCache) - iUnCache(); - return READ_COMPRESSED_ERROR_FILE_CORRUPT; - } - if (iread(Channel + i, HeadByte + 1, 1) != 1) - { - if (PreCache) - iUnCache(); - return READ_COMPRESSED_ERROR_FILE_READ_ERROR; - } - - i += HeadByte + 1; - } - if (HeadByte >= -127 && HeadByte <= -1) { - Run = igetc(); - if (Run == IL_EOF) - { - if (PreCache) - iUnCache(); - return READ_COMPRESSED_ERROR_FILE_READ_ERROR; - } - if (i + (-HeadByte + 1) > Size) - { - if (PreCache) - iUnCache(); - return READ_COMPRESSED_ERROR_FILE_CORRUPT; - } - - memset(Channel + i, Run, -HeadByte + 1); - i += -HeadByte + 1; - } - if (HeadByte == -128) - { } // Noop - } - if (PreCache) - iUnCache(); - - return READ_COMPRESSED_SUCCESS; -} - - -ILboolean PsdGetData(PSDHEAD *Head, void *Buffer, ILboolean Compressed) -{ - ILuint c, x, y, i, Size, ReadResult, NumChan; - ILubyte *Channel = NULL; - ILushort *ShortPtr; - ILuint *ChanLen = NULL; - - // Added 01-07-2009: This is needed to correctly load greyscale and - // paletted images. - switch (Head->Mode) - { - case 1: - case 2: - NumChan = 1; - break; - default: - NumChan = 3; - } - - Channel = (ILubyte*)ialloc(Head->Width * Head->Height * iCurImage->Bpc); - if (Channel == NULL) { - return IL_FALSE; - } - ShortPtr = (ILushort*)Channel; - - // @TODO: Add support for this in, though I have yet to run across a .psd - // file that uses this. - if (Compressed && iCurImage->Type == IL_UNSIGNED_SHORT) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - if (!Compressed) { - if (iCurImage->Bpc == 1) { - for (c = 0; c < NumChan; c++) { - i = 0; - if (iread(Channel, Head->Width * Head->Height, 1) != 1) { - ifree(Channel); - return IL_FALSE; - } - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { - iCurImage->Data[y + x + c] = Channel[i]; - } - } - } - // Accumulate any remaining channels into a single alpha channel - //@TODO: This needs to be changed for greyscale images. - for (; c < Head->Channels; c++) { - i = 0; - if (iread(Channel, Head->Width * Head->Height, 1) != 1) { - ifree(Channel); - return IL_FALSE; - } - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { - float curVal = ubyte_to_float(iCurImage->Data[y + x + 3]); - float newVal = ubyte_to_float(Channel[i]); - iCurImage->Data[y + x + 3] = float_to_ubyte(curVal * newVal); - } - } - } - } - else { // iCurImage->Bpc == 2 - for (c = 0; c < NumChan; c++) { - i = 0; - if (iread(Channel, Head->Width * Head->Height * 2, 1) != 1) { - ifree(Channel); - return IL_FALSE; - } - iCurImage->Bps /= 2; - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { - #ifndef WORDS_BIGENDIAN - iSwapUShort(ShortPtr+i); - #endif - ((ILushort*)iCurImage->Data)[y + x + c] = ShortPtr[i]; - } - } - iCurImage->Bps *= 2; - } - // Accumulate any remaining channels into a single alpha channel - //@TODO: This needs to be changed for greyscale images. - for (; c < Head->Channels; c++) { - i = 0; - if (iread(Channel, Head->Width * Head->Height * 2, 1) != 1) { - ifree(Channel); - return IL_FALSE; - } - iCurImage->Bps /= 2; - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { - float curVal = ushort_to_float(((ILushort*)iCurImage->Data)[y + x + 3]); - float newVal = ushort_to_float(ShortPtr[i]); - ((ILushort*)iCurImage->Data)[y + x + 3] = float_to_ushort(curVal * newVal); - } - } - iCurImage->Bps *= 2; - } - } - } - else { - ChanLen = GetCompChanLen(Head); - - Size = Head->Width * Head->Height; - for (c = 0; c < NumChan; c++) { - ReadResult = ReadCompressedChannel(ChanLen[c], Size, Channel); - if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) - goto file_corrupt; - else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) - goto file_read_error; - - i = 0; - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { - iCurImage->Data[y + x + c] = Channel[i]; - } - } - } - - // Initialize the alpha channel to solid - //@TODO: This needs to be changed for greyscale images. - if (Head->Channels >= 4) { - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp) { - iCurImage->Data[y + x + 3] = 255; - } - } - - for (; c < Head->Channels; c++) { - ReadResult = ReadCompressedChannel(ChanLen[c], Size, Channel); - if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) - goto file_corrupt; - else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) - goto file_read_error; - - i = 0; - for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { - for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { - float curVal = ubyte_to_float(iCurImage->Data[y + x + 3]); - float newVal = ubyte_to_float(Channel[i]); - iCurImage->Data[y + x + 3] = float_to_ubyte(curVal * newVal); - } - } - } - } - - ifree(ChanLen); - } - - ifree(Channel); - - return IL_TRUE; - -file_corrupt: - ifree(ChanLen); - ifree(Channel); - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - -file_read_error: - ifree(ChanLen); - ifree(Channel); - return IL_FALSE; -} - - -ILboolean ParseResources(ILuint ResourceSize, ILubyte *Resources) -{ - ILushort ID; - ILubyte NameLen; - ILuint Size; - - if (Resources == NULL) { - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - while (ResourceSize > 13) { // Absolutely has to be larger than this. - if (strncmp("8BIM", (const char*)Resources, 4)) { - //return IL_FALSE; - return IL_TRUE; // 05-30-2002: May not necessarily mean corrupt data... - } - Resources += 4; - - ID = *((ILushort*)Resources); - BigUShort(&ID); - Resources += 2; - - NameLen = *Resources++; - // NameLen + the byte it occupies must be padded to an even number, so NameLen must be odd. - NameLen = NameLen + (NameLen & 1 ? 0 : 1); - Resources += NameLen; - - // Get the resource data size. - Size = *((ILuint*)Resources); - BigUInt(&Size); - Resources += 4; - - ResourceSize -= (4 + 2 + 1 + NameLen + 4); - - switch (ID) - { - case 0x040F: // ICC Profile - if (Size > ResourceSize) { // Check to make sure we are not going past the end of Resources. - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - iCurImage->Profile = (ILubyte*)ialloc(Size); - if (iCurImage->Profile == NULL) { - return IL_FALSE; - } - memcpy(iCurImage->Profile, Resources, Size); - iCurImage->ProfileSize = Size; - break; - - default: - break; - } - - if (Size & 1) // Must be an even number. - Size++; - ResourceSize -= Size; - Resources += Size; - } - - return IL_TRUE; -} - - -ILboolean GetSingleChannel(PSDHEAD *Head, ILubyte *Buffer, ILboolean Compressed) -{ - ILuint i; - ILushort *ShortPtr; - ILbyte HeadByte; - ILint Run; - - ShortPtr = (ILushort*)Buffer; - - if (!Compressed) { - if (iCurImage->Bpc == 1) { - if (iread(Buffer, Head->Width * Head->Height, 1) != 1) - return IL_FALSE; - } - else { // iCurImage->Bpc == 2 - if (iread(Buffer, Head->Width * Head->Height * 2, 1) != 1) - return IL_FALSE; - } - } - else { - for (i = 0; i < Head->Width * Head->Height; ) { - HeadByte = igetc(); - - if (HeadByte >= 0) { // && HeadByte <= 127 - if (iread(Buffer + i, HeadByte + 1, 1) != 1) - return IL_FALSE; - i += HeadByte + 1; - } - if (HeadByte >= -127 && HeadByte <= -1) { - Run = igetc(); - if (Run == IL_EOF) - return IL_FALSE; - memset(Buffer + i, Run, -HeadByte + 1); - i += -HeadByte + 1; - } - if (HeadByte == -128) - { } // Noop - } - } - - return IL_TRUE; -} - - - -//! Writes a Psd file -ILboolean ilSavePsd(const ILstring FileName) -{ - ILHANDLE PsdFile; - ILuint PsdSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - PsdFile = iopenw(FileName); - if (PsdFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - PsdSize = ilSavePsdF(PsdFile); - iclosew(PsdFile); - - if (PsdSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Psd to an already-opened file -ILuint ilSavePsdF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSavePsdInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Psd to a memory "lump" -ILuint ilSavePsdL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSavePsdInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the Psd. -ILboolean iSavePsdInternal() -{ - ILubyte *Signature = (ILubyte*)"8BPS"; - ILimage *TempImage; - ILpal *TempPal; - ILuint c, i; - ILubyte *TempData; - ILushort *ShortPtr; - ILenum Format, Type; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Format = iCurImage->Format; - Type = iCurImage->Type; - - // All of these comprise the actual signature. - iwrite(Signature, 1, 4); - SaveBigShort(1); - SaveBigInt(0); - SaveBigShort(0); - - SaveBigShort(iCurImage->Bpp); - SaveBigInt(iCurImage->Height); - SaveBigInt(iCurImage->Width); - if (iCurImage->Bpc > 2) - Type = IL_UNSIGNED_SHORT; - - if (iCurImage->Format == IL_BGR) - Format = IL_RGB; - else if (iCurImage->Format == IL_BGRA) - Format = IL_RGBA; - - if (Format != iCurImage->Format || Type != iCurImage->Type) { - TempImage = iConvertImage(iCurImage, Format, Type); - if (TempImage == NULL) - return IL_FALSE; - } - else { - TempImage = iCurImage; - } - SaveBigShort((ILushort)(TempImage->Bpc * 8)); - - // @TODO: Put the other formats here. - switch (TempImage->Format) - { - case IL_COLOUR_INDEX: - SaveBigShort(2); - break; - case IL_LUMINANCE: - SaveBigShort(1); - break; - case IL_RGB: - case IL_RGBA: - SaveBigShort(3); - break; - default: - ilSetError(IL_INTERNAL_ERROR); - return IL_FALSE; - } - - if (TempImage->Format == IL_COLOUR_INDEX) { - // @TODO: We're currently making a potentially fatal assumption that - // iConvertImage was not called if the format is IL_COLOUR_INDEX. - TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24); - if (TempPal == NULL) - return IL_FALSE; - SaveBigInt(768); - - // Have to save the palette in a planar format. - for (c = 0; c < 3; c++) { - for (i = c; i < TempPal->PalSize; i += 3) { - iputc(TempPal->Palette[i]); - } - } - - ifree(TempPal->Palette); - } - else { - SaveBigInt(0); // No colour mode data. - } - - SaveBigInt(0); // No image resources. - SaveBigInt(0); // No layer information. - SaveBigShort(0); // Psd data, no compression. - - // @TODO: Add RLE compression. - - if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - ilCloseImage(TempImage); - return IL_FALSE; - } - } - else { - TempData = TempImage->Data; - } - - if (TempImage->Bpc == 1) { - for (c = 0; c < TempImage->Bpp; c++) { - for (i = c; i < TempImage->SizeOfPlane; i += TempImage->Bpp) { - iputc(TempData[i]); - } - } - } - else { // TempImage->Bpc == 2 - ShortPtr = (ILushort*)TempData; - TempImage->SizeOfPlane /= 2; - for (c = 0; c < TempImage->Bpp; c++) { - for (i = c; i < TempImage->SizeOfPlane; i += TempImage->Bpp) { - SaveBigUShort(ShortPtr[i]); - } - } - TempImage->SizeOfPlane *= 2; - } - - if (TempData != TempImage->Data) - ifree(TempData); - - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - - return IL_TRUE; -} - - -#endif//IL_NO_PSD diff --git a/DevIL/src-IL/src/il_psd.cpp b/DevIL/src-IL/src/il_psd.cpp new file mode 100644 index 00000000..257584c2 --- /dev/null +++ b/DevIL/src-IL/src/il_psd.cpp @@ -0,0 +1,1086 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_psd.c +// +// Description: Reads and writes Photoshop (.psd) files. +// +//----------------------------------------------------------------------------- + + +// Information about the .psd format was taken from Adobe's PhotoShop SDK at +// http://partners.adobe.com/asn/developer/gapsdk/PhotoshopSDK.html +// Information about the Packbits compression scheme was found at +// http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf + +#include "il_internal.h" +#ifndef IL_NO_PSD +#include "il_psd.h" + +static float ubyte_to_float(ILubyte val) +{ + return ((float)val) / 255.0f; +} +static float ushort_to_float(ILushort val) +{ + return ((float)val) / 65535.0f; +} + +static ILubyte float_to_ubyte(float val) +{ + return (ILubyte)(val * 255.0f); +} +static ILushort float_to_ushort(float val) +{ + return (ILushort)(val * 65535.0f); +} + + +//! Checks if the file specified in FileName is a valid Psd file. +ILboolean ilIsValidPsd(ILconst_string FileName) +{ + ILHANDLE PsdFile; + ILboolean bPsd = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("psd")) && + !iCheckExtension(FileName, IL_TEXT("pdd"))) { + ilSetError(IL_INVALID_EXTENSION); + return bPsd; + } + + PsdFile = iopenr(FileName); + if (PsdFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPsd; + } + + bPsd = ilIsValidPsdF(PsdFile); + icloser(PsdFile); + + return bPsd; +} + + +//! Checks if the ILHANDLE contains a valid Psd file at the current position. +ILboolean ilIsValidPsdF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidPsd(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid Psd lump. +ILboolean ilIsValidPsdL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidPsd(); +} + + +// Internal function used to get the Psd header from the current file. +ILboolean iGetPsdHead(PSDHEAD *Header) +{ + iread(Header->Signature, 1, 4); + Header->Version = GetBigUShort(); + iread(Header->Reserved, 1, 6); + Header->Channels = GetBigUShort(); + Header->Height = GetBigUInt(); + Header->Width = GetBigUInt(); + Header->Depth = GetBigUShort(); + Header->Mode = GetBigUShort(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidPsd() +{ + PSDHEAD Head; + + iGetPsdHead(&Head); + iseek(-(ILint)sizeof(PSDHEAD), IL_SEEK_CUR); + + return iCheckPsd(&Head); +} + + +// Internal function used to check if the HEADER is a valid Psd header. +ILboolean iCheckPsd(PSDHEAD *Header) +{ + ILuint i; + + if (strncmp((char*)Header->Signature, "8BPS", 4)) + return IL_FALSE; + if (Header->Version != 1) + return IL_FALSE; + for (i = 0; i < 6; i++) { + if (Header->Reserved[i] != 0) + return IL_FALSE; + } + if (Header->Channels < 1 || Header->Channels > 24) + return IL_FALSE; + if (Header->Height < 1 || Header->Width < 1) + return IL_FALSE; + if (Header->Depth != 1 && Header->Depth != 8 && Header->Depth != 16) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a Psd file +ILboolean ilLoadPsd(ILconst_string FileName) +{ + ILHANDLE PsdFile; + ILboolean bPsd = IL_FALSE; + + PsdFile = iopenr(FileName); + if (PsdFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPsd; + } + + bPsd = ilLoadPsdF(PsdFile); + icloser(PsdFile); + + return bPsd; +} + + +//! Reads an already-opened Psd file +ILboolean ilLoadPsdF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPsdInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Psd +ILboolean ilLoadPsdL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPsdInternal(); +} + + +// Internal function used to load the Psd. +ILboolean iLoadPsdInternal() +{ + PSDHEAD Header; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iGetPsdHead(&Header); + if (!iCheckPsd(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ReadPsd(&Header)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + return ilFixImage(); +} + + +ILboolean ReadPsd(PSDHEAD *Head) +{ + switch (Head->Mode) + { + case 1: // Greyscale + return ReadGrey(Head); + case 2: // Indexed + return ReadIndexed(Head); + case 3: // RGB + return ReadRGB(Head); + case 4: // CMYK + return ReadCMYK(Head); + } + + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; +} + + +ILboolean ReadGrey(PSDHEAD *Head) +{ + ILuint ColorMode, ResourceSize, MiscInfo; + ILushort Compressed; + ILenum Type; + ILubyte *Resources = NULL; + + ColorMode = GetBigUInt(); // Skip over the 'color mode data section' + iseek(ColorMode, IL_SEEK_CUR); + + ResourceSize = GetBigUInt(); // Read the 'image resources section' + Resources = (ILubyte*)ialloc(ResourceSize); + if (Resources == NULL) { + return IL_FALSE; + } + if (iread(Resources, 1, ResourceSize) != ResourceSize) + goto cleanup_error; + + MiscInfo = GetBigUInt(); + iseek(MiscInfo, IL_SEEK_CUR); + + Compressed = GetBigUShort(); + + ChannelNum = Head->Channels; + Head->Channels = 1; // Temporary to read only one channel...some greyscale .psd files have 2. + if (Head->Channels != 1) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + switch (Head->Depth) + { + case 8: + Type = IL_UNSIGNED_BYTE; + break; + case 16: + Type = IL_UNSIGNED_SHORT; + break; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_LUMINANCE, Type, NULL)) + goto cleanup_error; + if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) + goto cleanup_error; + if (!ParseResources(ResourceSize, Resources)) + goto cleanup_error; + ifree(Resources); + + return IL_TRUE; + +cleanup_error: + ifree(Resources); + return IL_FALSE; +} + + +ILboolean ReadIndexed(PSDHEAD *Head) +{ + ILuint ColorMode, ResourceSize, MiscInfo, i, j, NumEnt; + ILushort Compressed; + ILubyte *Palette = NULL, *Resources = NULL; + + ColorMode = GetBigUInt(); // Skip over the 'color mode data section' + if (ColorMode % 3 != 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + Palette = (ILubyte*)ialloc(ColorMode); + if (Palette == NULL) + return IL_FALSE; + if (iread(Palette, 1, ColorMode) != ColorMode) + goto cleanup_error; + + ResourceSize = GetBigUInt(); // Read the 'image resources section' + Resources = (ILubyte*)ialloc(ResourceSize); + if (Resources == NULL) { + return IL_FALSE; + } + if (iread(Resources, 1, ResourceSize) != ResourceSize) + goto cleanup_error; + + MiscInfo = GetBigUInt(); + if (ieof()) + goto cleanup_error; + iseek(MiscInfo, IL_SEEK_CUR); + + Compressed = GetBigUShort(); + if (ieof()) + goto cleanup_error; + + if (Head->Channels != 1 || Head->Depth != 8) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + goto cleanup_error; + } + ChannelNum = Head->Channels; + + if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + goto cleanup_error; + + iCurImage->Pal.Palette = (ILubyte*)ialloc(ColorMode); + if (iCurImage->Pal.Palette == NULL) { + goto cleanup_error; + } + iCurImage->Pal.PalSize = ColorMode; + iCurImage->Pal.PalType = IL_PAL_RGB24; + + NumEnt = iCurImage->Pal.PalSize / 3; + for (i = 0, j = 0; i < iCurImage->Pal.PalSize; i += 3, j++) { + iCurImage->Pal.Palette[i ] = Palette[j]; + iCurImage->Pal.Palette[i+1] = Palette[j+NumEnt]; + iCurImage->Pal.Palette[i+2] = Palette[j+NumEnt*2]; + } + ifree(Palette); + Palette = NULL; + + if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) + goto cleanup_error; + + ParseResources(ResourceSize, Resources); + ifree(Resources); + Resources = NULL; + + return IL_TRUE; + +cleanup_error: + ifree(Palette); + ifree(Resources); + + return IL_FALSE; +} + + +ILboolean ReadRGB(PSDHEAD *Head) +{ + ILuint ColorMode, ResourceSize, MiscInfo; + ILushort Compressed; + ILenum Format, Type; + ILubyte *Resources = NULL; + + ColorMode = GetBigUInt(); // Skip over the 'color mode data section' + iseek(ColorMode, IL_SEEK_CUR); + + ResourceSize = GetBigUInt(); // Read the 'image resources section' + Resources = (ILubyte*)ialloc(ResourceSize); + if (Resources == NULL) + return IL_FALSE; + if (iread(Resources, 1, ResourceSize) != ResourceSize) + goto cleanup_error; + + MiscInfo = GetBigUInt(); + iseek(MiscInfo, IL_SEEK_CUR); + + Compressed = GetBigUShort(); + + ChannelNum = Head->Channels; + if (Head->Channels == 3) + { + Format = IL_RGB; + } + else if (Head->Channels == 4) + { + Format = IL_RGBA; + } + else if (Head->Channels >= 5) + { + // Additional channels are accumulated as a single alpha channel, since + // if an image does not have a layer set as the "background", but also + // has a real alpha channel, there will be 5 channels (or more). + Format = IL_RGBA; + } + else + { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + switch (Head->Depth) + { + case 8: + Type = IL_UNSIGNED_BYTE; + break; + case 16: + Type = IL_UNSIGNED_SHORT; + break; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + if (!ilTexImage(Head->Width, Head->Height, 1, (Format==IL_RGB) ? 3 : 4, Format, Type, NULL)) + goto cleanup_error; + if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) + goto cleanup_error; + if (!ParseResources(ResourceSize, Resources)) + goto cleanup_error; + ifree(Resources); + + return IL_TRUE; + +cleanup_error: + ifree(Resources); + return IL_FALSE; +} + + +ILboolean ReadCMYK(PSDHEAD *Head) +{ + ILuint ColorMode, ResourceSize, MiscInfo, Size, i, j; + ILushort Compressed; + ILenum Format, Type; + ILubyte *Resources = NULL, *KChannel = NULL; + + ColorMode = GetBigUInt(); // Skip over the 'color mode data section' + iseek(ColorMode, IL_SEEK_CUR); + + ResourceSize = GetBigUInt(); // Read the 'image resources section' + Resources = (ILubyte*)ialloc(ResourceSize); + if (Resources == NULL) { + return IL_FALSE; + } + if (iread(Resources, 1, ResourceSize) != ResourceSize) + goto cleanup_error; + + MiscInfo = GetBigUInt(); + iseek(MiscInfo, IL_SEEK_CUR); + + Compressed = GetBigUShort(); + + switch (Head->Channels) + { + case 4: + Format = IL_RGB; + ChannelNum = 4; + Head->Channels = 3; + break; + case 5: + Format = IL_RGBA; + ChannelNum = 5; + Head->Channels = 4; + break; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + switch (Head->Depth) + { + case 8: + Type = IL_UNSIGNED_BYTE; + break; + case 16: + Type = IL_UNSIGNED_SHORT; + break; + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + if (!ilTexImage(Head->Width, Head->Height, 1, (ILubyte)Head->Channels, Format, Type, NULL)) + goto cleanup_error; + if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) + goto cleanup_error; + + Size = iCurImage->Bpc * iCurImage->Width * iCurImage->Height; + KChannel = (ILubyte*)ialloc(Size); + if (KChannel == NULL) + goto cleanup_error; + if (!GetSingleChannel(Head, KChannel, (ILboolean)Compressed)) + goto cleanup_error; + + if (Format == IL_RGB) { + for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 3, j++) { + iCurImage->Data[i ] = (iCurImage->Data[i ] * KChannel[j]) >> 8; + iCurImage->Data[i+1] = (iCurImage->Data[i+1] * KChannel[j]) >> 8; + iCurImage->Data[i+2] = (iCurImage->Data[i+2] * KChannel[j]) >> 8; + } + } + else { // IL_RGBA + // The KChannel array really holds the alpha channel on this one. + for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 4, j++) { + iCurImage->Data[i ] = (iCurImage->Data[i ] * iCurImage->Data[i+3]) >> 8; + iCurImage->Data[i+1] = (iCurImage->Data[i+1] * iCurImage->Data[i+3]) >> 8; + iCurImage->Data[i+2] = (iCurImage->Data[i+2] * iCurImage->Data[i+3]) >> 8; + iCurImage->Data[i+3] = KChannel[j]; // Swap 'K' with alpha channel. + } + } + + if (!ParseResources(ResourceSize, Resources)) + goto cleanup_error; + + ifree(Resources); + ifree(KChannel); + + return IL_TRUE; + +cleanup_error: + ifree(Resources); + ifree(KChannel); + return IL_FALSE; +} + + +ILuint *GetCompChanLen(PSDHEAD *Head) +{ + ILushort *RleTable; + ILuint *ChanLen, c, i, j; + + RleTable = (ILushort*)ialloc(Head->Height * ChannelNum * sizeof(ILushort)); + ChanLen = (ILuint*)ialloc(ChannelNum * sizeof(ILuint)); + if (RleTable == NULL || ChanLen == NULL) { + return NULL; + } + + if (iread(RleTable, sizeof(ILushort), Head->Height * ChannelNum) != Head->Height * ChannelNum) { + ifree(RleTable); + ifree(ChanLen); + return NULL; + } +#ifdef __LITTLE_ENDIAN__ + for (i = 0; i < Head->Height * ChannelNum; i++) { + iSwapUShort(&RleTable[i]); + } +#endif + + imemclear(ChanLen, ChannelNum * sizeof(ILuint)); + for (c = 0; c < ChannelNum; c++) { + j = c * Head->Height; + for (i = 0; i < Head->Height; i++) { + ChanLen[c] += RleTable[i + j]; + } + } + + ifree(RleTable); + + return ChanLen; +} + + + +static const ILuint READ_COMPRESSED_SUCCESS = 0; +static const ILuint READ_COMPRESSED_ERROR_FILE_CORRUPT = 1; +static const ILuint READ_COMPRESSED_ERROR_FILE_READ_ERROR = 2; + +static ILuint ReadCompressedChannel(const ILuint ChanLen, ILuint Size, ILubyte* Channel) +{ + ILuint i; + ILint Run; + ILboolean PreCache = IL_FALSE; + ILbyte HeadByte; + + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + PreCache = IL_TRUE; + + if (PreCache) + iPreCache(ChanLen); + for (i = 0; i < Size; ) { + HeadByte = igetc(); + + if (HeadByte >= 0) { // && HeadByte <= 127 + if (i + HeadByte > Size) + { + if (PreCache) + iUnCache(); + return READ_COMPRESSED_ERROR_FILE_CORRUPT; + } + if (iread(Channel + i, HeadByte + 1, 1) != 1) + { + if (PreCache) + iUnCache(); + return READ_COMPRESSED_ERROR_FILE_READ_ERROR; + } + + i += HeadByte + 1; + } + if (HeadByte >= -127 && HeadByte <= -1) { + Run = igetc(); + if (Run == IL_EOF) + { + if (PreCache) + iUnCache(); + return READ_COMPRESSED_ERROR_FILE_READ_ERROR; + } + if (i + (-HeadByte + 1) > Size) + { + if (PreCache) + iUnCache(); + return READ_COMPRESSED_ERROR_FILE_CORRUPT; + } + + memset(Channel + i, Run, -HeadByte + 1); + i += -HeadByte + 1; + } + if (HeadByte == -128) + { } // Noop + } + if (PreCache) + iUnCache(); + + return READ_COMPRESSED_SUCCESS; +} + + +ILboolean PsdGetData(PSDHEAD *Head, void *Buffer, ILboolean Compressed) +{ + ILuint c, x, y, i, Size, ReadResult, NumChan; + ILubyte *Channel = NULL; + ILushort *ShortPtr; + ILuint *ChanLen = NULL; + + // Added 01-07-2009: This is needed to correctly load greyscale and + // paletted images. + switch (Head->Mode) + { + case 1: + case 2: + NumChan = 1; + break; + default: + NumChan = 3; + } + + Channel = (ILubyte*)ialloc(Head->Width * Head->Height * iCurImage->Bpc); + if (Channel == NULL) { + return IL_FALSE; + } + ShortPtr = (ILushort*)Channel; + + // @TODO: Add support for this in, though I have yet to run across a .psd + // file that uses this. + if (Compressed && iCurImage->Type == IL_UNSIGNED_SHORT) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + if (!Compressed) { + if (iCurImage->Bpc == 1) { + for (c = 0; c < NumChan; c++) { + i = 0; + if (iread(Channel, Head->Width * Head->Height, 1) != 1) { + ifree(Channel); + return IL_FALSE; + } + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { + iCurImage->Data[y + x + c] = Channel[i]; + } + } + } + // Accumulate any remaining channels into a single alpha channel + //@TODO: This needs to be changed for greyscale images. + for (; c < Head->Channels; c++) { + i = 0; + if (iread(Channel, Head->Width * Head->Height, 1) != 1) { + ifree(Channel); + return IL_FALSE; + } + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { + float curVal = ubyte_to_float(iCurImage->Data[y + x + 3]); + float newVal = ubyte_to_float(Channel[i]); + iCurImage->Data[y + x + 3] = float_to_ubyte(curVal * newVal); + } + } + } + } + else { // iCurImage->Bpc == 2 + for (c = 0; c < NumChan; c++) { + i = 0; + if (iread(Channel, Head->Width * Head->Height * 2, 1) != 1) { + ifree(Channel); + return IL_FALSE; + } + iCurImage->Bps /= 2; + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { + #ifndef WORDS_BIGENDIAN + iSwapUShort(ShortPtr+i); + #endif + ((ILushort*)iCurImage->Data)[y + x + c] = ShortPtr[i]; + } + } + iCurImage->Bps *= 2; + } + // Accumulate any remaining channels into a single alpha channel + //@TODO: This needs to be changed for greyscale images. + for (; c < Head->Channels; c++) { + i = 0; + if (iread(Channel, Head->Width * Head->Height * 2, 1) != 1) { + ifree(Channel); + return IL_FALSE; + } + iCurImage->Bps /= 2; + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { + float curVal = ushort_to_float(((ILushort*)iCurImage->Data)[y + x + 3]); + float newVal = ushort_to_float(ShortPtr[i]); + ((ILushort*)iCurImage->Data)[y + x + 3] = float_to_ushort(curVal * newVal); + } + } + iCurImage->Bps *= 2; + } + } + } + else { + ChanLen = GetCompChanLen(Head); + + Size = Head->Width * Head->Height; + for (c = 0; c < NumChan; c++) { + ReadResult = ReadCompressedChannel(ChanLen[c], Size, Channel); + if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) + goto file_corrupt; + else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) + goto file_read_error; + + i = 0; + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { + iCurImage->Data[y + x + c] = Channel[i]; + } + } + } + + // Initialize the alpha channel to solid + //@TODO: This needs to be changed for greyscale images. + if (Head->Channels >= 4) { + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp) { + iCurImage->Data[y + x + 3] = 255; + } + } + + for (; c < Head->Channels; c++) { + ReadResult = ReadCompressedChannel(ChanLen[c], Size, Channel); + if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) + goto file_corrupt; + else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) + goto file_read_error; + + i = 0; + for (y = 0; y < Head->Height * iCurImage->Bps; y += iCurImage->Bps) { + for (x = 0; x < iCurImage->Bps; x += iCurImage->Bpp, i++) { + float curVal = ubyte_to_float(iCurImage->Data[y + x + 3]); + float newVal = ubyte_to_float(Channel[i]); + iCurImage->Data[y + x + 3] = float_to_ubyte(curVal * newVal); + } + } + } + } + + ifree(ChanLen); + } + + ifree(Channel); + + return IL_TRUE; + +file_corrupt: + ifree(ChanLen); + ifree(Channel); + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + +file_read_error: + ifree(ChanLen); + ifree(Channel); + return IL_FALSE; +} + + +ILboolean ParseResources(ILuint ResourceSize, ILubyte *Resources) +{ + ILushort ID; + ILubyte NameLen; + ILuint Size; + + if (Resources == NULL) { + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + while (ResourceSize > 13) { // Absolutely has to be larger than this. + if (strncmp("8BIM", (const char*)Resources, 4)) { + //return IL_FALSE; + return IL_TRUE; // 05-30-2002: May not necessarily mean corrupt data... + } + Resources += 4; + + ID = *((ILushort*)Resources); + BigUShort(&ID); + Resources += 2; + + NameLen = *Resources++; + // NameLen + the byte it occupies must be padded to an even number, so NameLen must be odd. + NameLen = NameLen + (NameLen & 1 ? 0 : 1); + Resources += NameLen; + + // Get the resource data size. + Size = *((ILuint*)Resources); + BigUInt(&Size); + Resources += 4; + + ResourceSize -= (4 + 2 + 1 + NameLen + 4); + + switch (ID) + { + case 0x040F: // ICC Profile + if (Size > ResourceSize) { // Check to make sure we are not going past the end of Resources. + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + iCurImage->Profile = (ILubyte*)ialloc(Size); + if (iCurImage->Profile == NULL) { + return IL_FALSE; + } + memcpy(iCurImage->Profile, Resources, Size); + iCurImage->ProfileSize = Size; + break; + + default: + break; + } + + if (Size & 1) // Must be an even number. + Size++; + ResourceSize -= Size; + Resources += Size; + } + + return IL_TRUE; +} + + +ILboolean GetSingleChannel(PSDHEAD *Head, ILubyte *Buffer, ILboolean Compressed) +{ + ILuint i; + ILushort *ShortPtr; + ILbyte HeadByte; + ILint Run; + + ShortPtr = (ILushort*)Buffer; + + if (!Compressed) { + if (iCurImage->Bpc == 1) { + if (iread(Buffer, Head->Width * Head->Height, 1) != 1) + return IL_FALSE; + } + else { // iCurImage->Bpc == 2 + if (iread(Buffer, Head->Width * Head->Height * 2, 1) != 1) + return IL_FALSE; + } + } + else { + for (i = 0; i < Head->Width * Head->Height; ) { + HeadByte = igetc(); + + if (HeadByte >= 0) { // && HeadByte <= 127 + if (iread(Buffer + i, HeadByte + 1, 1) != 1) + return IL_FALSE; + i += HeadByte + 1; + } + if (HeadByte >= -127 && HeadByte <= -1) { + Run = igetc(); + if (Run == IL_EOF) + return IL_FALSE; + memset(Buffer + i, Run, -HeadByte + 1); + i += -HeadByte + 1; + } + if (HeadByte == -128) + { } // Noop + } + } + + return IL_TRUE; +} + + + +//! Writes a Psd file +ILboolean ilSavePsd(const ILstring FileName) +{ + ILHANDLE PsdFile; + ILuint PsdSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + PsdFile = iopenw(FileName); + if (PsdFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + PsdSize = ilSavePsdF(PsdFile); + iclosew(PsdFile); + + if (PsdSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Psd to an already-opened file +ILuint ilSavePsdF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSavePsdInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Psd to a memory "lump" +ILuint ilSavePsdL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSavePsdInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the Psd. +ILboolean iSavePsdInternal() +{ + ILubyte *Signature = (ILubyte*)"8BPS"; + ILimage *TempImage; + ILpal *TempPal; + ILuint c, i; + ILubyte *TempData; + ILushort *ShortPtr; + ILenum Format, Type; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Format = iCurImage->Format; + Type = iCurImage->Type; + + // All of these comprise the actual signature. + iwrite(Signature, 1, 4); + SaveBigShort(1); + SaveBigInt(0); + SaveBigShort(0); + + SaveBigShort(iCurImage->Bpp); + SaveBigInt(iCurImage->Height); + SaveBigInt(iCurImage->Width); + if (iCurImage->Bpc > 2) + Type = IL_UNSIGNED_SHORT; + + if (iCurImage->Format == IL_BGR) + Format = IL_RGB; + else if (iCurImage->Format == IL_BGRA) + Format = IL_RGBA; + + if (Format != iCurImage->Format || Type != iCurImage->Type) { + TempImage = iConvertImage(iCurImage, Format, Type); + if (TempImage == NULL) + return IL_FALSE; + } + else { + TempImage = iCurImage; + } + SaveBigShort((ILushort)(TempImage->Bpc * 8)); + + // @TODO: Put the other formats here. + switch (TempImage->Format) + { + case IL_COLOUR_INDEX: + SaveBigShort(2); + break; + case IL_LUMINANCE: + SaveBigShort(1); + break; + case IL_RGB: + case IL_RGBA: + SaveBigShort(3); + break; + default: + ilSetError(IL_INTERNAL_ERROR); + return IL_FALSE; + } + + if (TempImage->Format == IL_COLOUR_INDEX) { + // @TODO: We're currently making a potentially fatal assumption that + // iConvertImage was not called if the format is IL_COLOUR_INDEX. + TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24); + if (TempPal == NULL) + return IL_FALSE; + SaveBigInt(768); + + // Have to save the palette in a planar format. + for (c = 0; c < 3; c++) { + for (i = c; i < TempPal->PalSize; i += 3) { + iputc(TempPal->Palette[i]); + } + } + + ifree(TempPal->Palette); + } + else { + SaveBigInt(0); // No colour mode data. + } + + SaveBigInt(0); // No image resources. + SaveBigInt(0); // No layer information. + SaveBigShort(0); // Psd data, no compression. + + // @TODO: Add RLE compression. + + if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + ilCloseImage(TempImage); + return IL_FALSE; + } + } + else { + TempData = TempImage->Data; + } + + if (TempImage->Bpc == 1) { + for (c = 0; c < TempImage->Bpp; c++) { + for (i = c; i < TempImage->SizeOfPlane; i += TempImage->Bpp) { + iputc(TempData[i]); + } + } + } + else { // TempImage->Bpc == 2 + ShortPtr = (ILushort*)TempData; + TempImage->SizeOfPlane /= 2; + for (c = 0; c < TempImage->Bpp; c++) { + for (i = c; i < TempImage->SizeOfPlane; i += TempImage->Bpp) { + SaveBigUShort(ShortPtr[i]); + } + } + TempImage->SizeOfPlane *= 2; + } + + if (TempData != TempImage->Data) + ifree(TempData); + + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + + return IL_TRUE; +} + + +#endif//IL_NO_PSD diff --git a/DevIL/src-IL/src/il_psp.c b/DevIL/src-IL/src/il_psp.c deleted file mode 100644 index b431a317..00000000 --- a/DevIL/src-IL/src/il_psp.c +++ /dev/null @@ -1,712 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_psp.c -// -// Description: Reads a Paint Shop Pro file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include "il_psp.h" -#ifndef IL_NO_PSP - - -ILubyte PSPSignature[32] = { - 0x50, 0x61, 0x69, 0x6E, 0x74, 0x20, 0x53, 0x68, 0x6F, 0x70, 0x20, 0x50, 0x72, 0x6F, 0x20, 0x49, - 0x6D, 0x61, 0x67, 0x65, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x0A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -ILubyte GenAttHead[4] = { - 0x7E, 0x42, 0x4B, 0x00 -}; - - -// Make these global, since they contain most of the image information. -GENATT_CHUNK AttChunk; -PSPHEAD Header; -ILuint NumChannels; -ILubyte **Channels = NULL; -ILubyte *Alpha = NULL; -ILpal Pal; - - - -//! Checks if the file specified in FileName is a valid Psp file. -ILboolean ilIsValidPsp(ILconst_string FileName) -{ - ILHANDLE PspFile; - ILboolean bPsp = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("psp"))) { - ilSetError(IL_INVALID_EXTENSION); - return bPsp; - } - - PspFile = iopenr(FileName); - if (PspFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPsp; - } - - bPsp = ilIsValidPspF(PspFile); - icloser(PspFile); - - return bPsp; -} - - -//! Checks if the ILHANDLE contains a valid Psp file at the current position. -ILboolean ilIsValidPspF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidPsp(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid Psp lump. -ILboolean ilIsValidPspL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidPsp(); -} - - -// Internal function used to get the Psp header from the current file. -ILboolean iGetPspHead() -{ - if (iread(Header.FileSig, 1, 32) != 32) - return IL_FALSE; - Header.MajorVersion = GetLittleUShort(); - Header.MinorVersion = GetLittleUShort(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidPsp() -{ - if (!iGetPspHead()) - return IL_FALSE; - iseek(-(ILint)sizeof(PSPHEAD), IL_SEEK_CUR); - - return iCheckPsp(); -} - - -// Internal function used to check if the HEADER is a valid Psp header. -ILboolean iCheckPsp() -{ - if (stricmp(Header.FileSig, "Paint Shop Pro Image File\n\x1a")) - return IL_FALSE; - if (Header.MajorVersion < 3 || Header.MajorVersion > 5) - return IL_FALSE; - if (Header.MinorVersion != 0) - return IL_FALSE; - - - return IL_TRUE; -} - - -//! Reads a PSP file -ILboolean ilLoadPsp(ILconst_string FileName) -{ - ILHANDLE PSPFile; - ILboolean bPsp = IL_FALSE; - - PSPFile = iopenr(FileName); - if (PSPFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPsp; - } - - bPsp = ilLoadPspF(PSPFile); - icloser(PSPFile); - - return bPsp; -} - - -//! Reads an already-opened PSP file -ILboolean ilLoadPspF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPspInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a PSP -ILboolean ilLoadPspL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPspInternal(); -} - - -// Internal function used to load the PSP. -ILboolean iLoadPspInternal() -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Channels = NULL; - Alpha = NULL; - Pal.Palette = NULL; - - if (!iGetPspHead()) - return IL_FALSE; - if (!iCheckPsp()) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ReadGenAttributes()) - return IL_FALSE; - if (!ParseChunks()) - return IL_FALSE; - if (!AssembleImage()) - return IL_FALSE; - - Cleanup(); - return ilFixImage(); -} - - -ILboolean ReadGenAttributes() -{ - BLOCKHEAD AttHead; - ILint Padding; - ILuint ChunkLen; - - if (iread(&AttHead, sizeof(AttHead), 1) != 1) - return IL_FALSE; - UShort(&AttHead.BlockID); - UInt(&AttHead.BlockLen); - - if (AttHead.HeadID[0] != 0x7E || AttHead.HeadID[1] != 0x42 || - AttHead.HeadID[2] != 0x4B || AttHead.HeadID[3] != 0x00) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - if (AttHead.BlockID != PSP_IMAGE_BLOCK) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - ChunkLen = GetLittleUInt(); - if (Header.MajorVersion != 3) - ChunkLen -= 4; - if (iread(&AttChunk, IL_MIN(sizeof(AttChunk), ChunkLen), 1) != 1) - return IL_FALSE; - - // Can have new entries in newer versions of the spec (4.0). - Padding = (ChunkLen) - sizeof(AttChunk); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - - // @TODO: Anything but 24 not supported yet... - if (AttChunk.BitDepth != 24 && AttChunk.BitDepth != 8) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // @TODO; Add support for compression... - if (AttChunk.Compression != PSP_COMP_NONE && AttChunk.Compression != PSP_COMP_RLE) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // @TODO: Check more things in the general attributes chunk here. - - return IL_TRUE; -} - - -ILboolean ParseChunks() -{ - BLOCKHEAD Block; - ILuint Pos; - - do { - if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) { - ilGetError(); // Get rid of the erroneous IL_FILE_READ_ERROR. - return IL_TRUE; - } - if (Header.MajorVersion == 3) - Block.BlockLen = GetLittleUInt(); - else - UInt(&Block.BlockLen); - - if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || - Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { - return IL_TRUE; - } - UShort(&Block.BlockID); - UInt(&Block.BlockLen); - - Pos = itell(); - - switch (Block.BlockID) - { - case PSP_LAYER_START_BLOCK: - if (!ReadLayerBlock(Block.BlockLen)) - return IL_FALSE; - break; - - case PSP_ALPHA_BANK_BLOCK: - if (!ReadAlphaBlock(Block.BlockLen)) - return IL_FALSE; - break; - - case PSP_COLOR_BLOCK: - if (!ReadPalette(Block.BlockLen)) - return IL_FALSE; - break; - - // Gets done in the next iseek, so this is now commented out. - //default: - //iseek(Block.BlockLen, IL_SEEK_CUR); - } - - // Skip to next block just in case we didn't read the entire block. - iseek(Pos + Block.BlockLen, IL_SEEK_SET); - - // @TODO: Do stuff here. - - } while (1); - - return IL_TRUE; -} - - -ILboolean ReadLayerBlock(ILuint BlockLen) -{ - BLOCKHEAD Block; - LAYERINFO_CHUNK LayerInfo; - LAYERBITMAP_CHUNK Bitmap; - ILuint ChunkSize, Padding, i, j; - ILushort NumChars; - - BlockLen; - - // Layer sub-block header - if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) - return IL_FALSE; - if (Header.MajorVersion == 3) - Block.BlockLen = GetLittleUInt(); - else - UInt(&Block.BlockLen); - - if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || - Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { - return IL_FALSE; - } - if (Block.BlockID != PSP_LAYER_BLOCK) - return IL_FALSE; - - - if (Header.MajorVersion == 3) { - iseek(256, IL_SEEK_CUR); // We don't care about the name of the layer. - iread(&LayerInfo, sizeof(LayerInfo), 1); - if (iread(&Bitmap, sizeof(Bitmap), 1) != 1) - return IL_FALSE; - } - else { // Header.MajorVersion >= 4 - ChunkSize = GetLittleUInt(); - NumChars = GetLittleUShort(); - iseek(NumChars, IL_SEEK_CUR); // We don't care about the layer's name. - - ChunkSize -= (2 + 4 + NumChars); - - if (iread(&LayerInfo, IL_MIN(sizeof(LayerInfo), ChunkSize), 1) != 1) - return IL_FALSE; - - // Can have new entries in newer versions of the spec (5.0). - Padding = (ChunkSize) - sizeof(LayerInfo); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - - ChunkSize = GetLittleUInt(); - if (iread(&Bitmap, sizeof(Bitmap), 1) != 1) - return IL_FALSE; - Padding = (ChunkSize - 4) - sizeof(Bitmap); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - } - - - Channels = (ILubyte**)ialloc(sizeof(ILubyte*) * Bitmap.NumChannels); - if (Channels == NULL) { - return IL_FALSE; - } - - NumChannels = Bitmap.NumChannels; - - for (i = 0; i < NumChannels; i++) { - Channels[i] = GetChannel(); - if (Channels[i] == NULL) { - for (j = 0; j < i; j++) - ifree(Channels[j]); - return IL_FALSE; - } - } - - return IL_TRUE; -} - - -ILboolean ReadAlphaBlock(ILuint BlockLen) -{ - BLOCKHEAD Block; - ALPHAINFO_CHUNK AlphaInfo; - ALPHA_CHUNK AlphaChunk; - ILushort NumAlpha, StringSize; - ILuint ChunkSize, Padding; - - if (Header.MajorVersion == 3) { - NumAlpha = GetLittleUShort(); - } - else { - ChunkSize = GetLittleUInt(); - NumAlpha = GetLittleUShort(); - Padding = (ChunkSize - 4 - 2); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - } - - // Alpha channel header - if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) - return IL_FALSE; - if (Header.MajorVersion == 3) - Block.BlockLen = GetLittleUInt(); - else - UInt(&Block.BlockLen); - - if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || - Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { - return IL_FALSE; - } - if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK) - return IL_FALSE; - - - if (Header.MajorVersion >= 4) { - ChunkSize = GetLittleUInt(); - StringSize = GetLittleUShort(); - iseek(StringSize, IL_SEEK_CUR); - if (iread(&AlphaInfo, sizeof(AlphaInfo), 1) != 1) - return IL_FALSE; - Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo)); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - - ChunkSize = GetLittleUInt(); - if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) - return IL_FALSE; - Padding = (ChunkSize - 4 - sizeof(AlphaChunk)); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - } - else { - iseek(256, IL_SEEK_CUR); - iread(&AlphaInfo, sizeof(AlphaInfo), 1); - if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) - return IL_FALSE; - } - - - /*Alpha = (ILubyte*)ialloc(AlphaInfo.AlphaRect.x2 * AlphaInfo.AlphaRect.y2); - if (Alpha == NULL) { - return IL_FALSE; - }*/ - - - Alpha = GetChannel(); - if (Alpha == NULL) - return IL_FALSE; - - return IL_TRUE; -} - - -ILubyte *GetChannel() -{ - BLOCKHEAD Block; - CHANNEL_CHUNK Channel; - ILubyte *CompData, *Data; - ILuint ChunkSize, Padding; - - if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) - return NULL; - if (Header.MajorVersion == 3) - Block.BlockLen = GetLittleUInt(); - else - UInt(&Block.BlockLen); - - if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || - Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return NULL; - } - if (Block.BlockID != PSP_CHANNEL_BLOCK) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return NULL; - } - - - if (Header.MajorVersion >= 4) { - ChunkSize = GetLittleUInt(); - if (iread(&Channel, sizeof(Channel), 1) != 1) - return NULL; - - Padding = (ChunkSize - 4) - sizeof(Channel); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - } - else { - if (iread(&Channel, sizeof(Channel), 1) != 1) - return NULL; - } - - - CompData = (ILubyte*)ialloc(Channel.CompLen); - Data = (ILubyte*)ialloc(AttChunk.Width * AttChunk.Height); - if (CompData == NULL || Data == NULL) { - ifree(Data); - ifree(CompData); - return NULL; - } - - if (iread(CompData, 1, Channel.CompLen) != Channel.CompLen) { - ifree(CompData); - ifree(Data); - return NULL; - } - - switch (AttChunk.Compression) - { - case PSP_COMP_NONE: - ifree(Data); - return CompData; - break; - - case PSP_COMP_RLE: - if (!UncompRLE(CompData, Data, Channel.CompLen)) { - ifree(CompData); - ifree(Data); - return IL_FALSE; - } - break; - - default: - ifree(CompData); - ifree(Data); - ilSetError(IL_INVALID_FILE_HEADER); - return NULL; - } - - ifree(CompData); - - return Data; -} - - -ILboolean UncompRLE(ILubyte *CompData, ILubyte *Data, ILuint CompLen) -{ - ILubyte Run, Colour; - ILint i, /*x, y,*/ Count/*, Total = 0*/; - - /*for (y = 0; y < AttChunk.Height; y++) { - for (x = 0, Count = 0; x < AttChunk.Width; ) { - Run = *CompData++; - if (Run > 128) { - Run -= 128; - Colour = *CompData++; - memset(Data, Colour, Run); - Data += Run; - Count += 2; - } - else { - memcpy(Data, CompData, Run); - CompData += Run; - Data += Run; - Count += Run; - } - x += Run; - } - - Total += Count; - - if (Count % 4) { // Has to be on a 4-byte boundary. - CompData += (4 - (Count % 4)) % 4; - Total += (4 - (Count % 4)) % 4; - } - - if (Total >= CompLen) - return IL_FALSE; - }*/ - - for (i = 0, Count = 0; i < (ILint)CompLen; ) { - Run = *CompData++; - i++; - if (Run > 128) { - Run -= 128; - Colour = *CompData++; - i++; - memset(Data, Colour, Run); - } - else { - memcpy(Data, CompData, Run); - CompData += Run; - i += Run; - } - Data += Run; - Count += Run; - } - - return IL_TRUE; -} - - -ILboolean ReadPalette(ILuint BlockLen) -{ - ILuint ChunkSize, PalCount, Padding; - - if (Header.MajorVersion >= 4) { - ChunkSize = GetLittleUInt(); - PalCount = GetLittleUInt(); - Padding = (ChunkSize - 4 - 4); - if (Padding > 0) - iseek(Padding, IL_SEEK_CUR); - } - else { - PalCount = GetLittleUInt(); - } - - Pal.PalSize = PalCount * 4; - Pal.PalType = IL_PAL_BGRA32; - Pal.Palette = (ILubyte*)ialloc(Pal.PalSize); - if (Pal.Palette == NULL) - return IL_FALSE; - - if (iread(Pal.Palette, Pal.PalSize, 1) != 1) { - ifree(Pal.Palette); - return IL_FALSE; - } - - return IL_TRUE; -} - - -ILboolean AssembleImage() -{ - ILuint Size, i, j; - - Size = AttChunk.Width * AttChunk.Height; - - if (NumChannels == 1) { - ilTexImage(AttChunk.Width, AttChunk.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); - for (i = 0; i < Size; i++) { - iCurImage->Data[i] = Channels[0][i]; - } - - if (Pal.Palette) { - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalSize = Pal.PalSize; - iCurImage->Pal.PalType = Pal.PalType; - iCurImage->Pal.Palette = Pal.Palette; - } - } - else { - if (Alpha) { - ilTexImage(AttChunk.Width, AttChunk.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - for (i = 0, j = 0; i < Size; i++, j += 4) { - iCurImage->Data[j ] = Channels[0][i]; - iCurImage->Data[j+1] = Channels[1][i]; - iCurImage->Data[j+2] = Channels[2][i]; - iCurImage->Data[j+3] = Alpha[i]; - } - } - - else if (NumChannels == 4) { - - ilTexImage(AttChunk.Width, AttChunk.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - - for (i = 0, j = 0; i < Size; i++, j += 4) { - - iCurImage->Data[j ] = Channels[0][i]; - - iCurImage->Data[j+1] = Channels[1][i]; - - iCurImage->Data[j+2] = Channels[2][i]; - - iCurImage->Data[j+3] = Channels[3][i]; - - } - - } - else if (NumChannels == 3) { - ilTexImage(AttChunk.Width, AttChunk.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); - for (i = 0, j = 0; i < Size; i++, j += 3) { - iCurImage->Data[j ] = Channels[0][i]; - iCurImage->Data[j+1] = Channels[1][i]; - iCurImage->Data[j+2] = Channels[2][i]; - } - } - else - return IL_FALSE; - } - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - return IL_TRUE; -} - - -ILboolean Cleanup() -{ - ILuint i; - - if (Channels) { - for (i = 0; i < NumChannels; i++) { - ifree(Channels[i]); - } - ifree(Channels); - } - - if (Alpha) { - ifree(Alpha); - } - - Channels = NULL; - Alpha = NULL; - Pal.Palette = NULL; - - return IL_TRUE; -} - - - -#endif//IL_NO_PSP diff --git a/DevIL/src-IL/src/il_psp.cpp b/DevIL/src-IL/src/il_psp.cpp new file mode 100644 index 00000000..b431a317 --- /dev/null +++ b/DevIL/src-IL/src/il_psp.cpp @@ -0,0 +1,712 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_psp.c +// +// Description: Reads a Paint Shop Pro file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include "il_psp.h" +#ifndef IL_NO_PSP + + +ILubyte PSPSignature[32] = { + 0x50, 0x61, 0x69, 0x6E, 0x74, 0x20, 0x53, 0x68, 0x6F, 0x70, 0x20, 0x50, 0x72, 0x6F, 0x20, 0x49, + 0x6D, 0x61, 0x67, 0x65, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x0A, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +ILubyte GenAttHead[4] = { + 0x7E, 0x42, 0x4B, 0x00 +}; + + +// Make these global, since they contain most of the image information. +GENATT_CHUNK AttChunk; +PSPHEAD Header; +ILuint NumChannels; +ILubyte **Channels = NULL; +ILubyte *Alpha = NULL; +ILpal Pal; + + + +//! Checks if the file specified in FileName is a valid Psp file. +ILboolean ilIsValidPsp(ILconst_string FileName) +{ + ILHANDLE PspFile; + ILboolean bPsp = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("psp"))) { + ilSetError(IL_INVALID_EXTENSION); + return bPsp; + } + + PspFile = iopenr(FileName); + if (PspFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPsp; + } + + bPsp = ilIsValidPspF(PspFile); + icloser(PspFile); + + return bPsp; +} + + +//! Checks if the ILHANDLE contains a valid Psp file at the current position. +ILboolean ilIsValidPspF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidPsp(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid Psp lump. +ILboolean ilIsValidPspL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidPsp(); +} + + +// Internal function used to get the Psp header from the current file. +ILboolean iGetPspHead() +{ + if (iread(Header.FileSig, 1, 32) != 32) + return IL_FALSE; + Header.MajorVersion = GetLittleUShort(); + Header.MinorVersion = GetLittleUShort(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidPsp() +{ + if (!iGetPspHead()) + return IL_FALSE; + iseek(-(ILint)sizeof(PSPHEAD), IL_SEEK_CUR); + + return iCheckPsp(); +} + + +// Internal function used to check if the HEADER is a valid Psp header. +ILboolean iCheckPsp() +{ + if (stricmp(Header.FileSig, "Paint Shop Pro Image File\n\x1a")) + return IL_FALSE; + if (Header.MajorVersion < 3 || Header.MajorVersion > 5) + return IL_FALSE; + if (Header.MinorVersion != 0) + return IL_FALSE; + + + return IL_TRUE; +} + + +//! Reads a PSP file +ILboolean ilLoadPsp(ILconst_string FileName) +{ + ILHANDLE PSPFile; + ILboolean bPsp = IL_FALSE; + + PSPFile = iopenr(FileName); + if (PSPFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPsp; + } + + bPsp = ilLoadPspF(PSPFile); + icloser(PSPFile); + + return bPsp; +} + + +//! Reads an already-opened PSP file +ILboolean ilLoadPspF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPspInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a PSP +ILboolean ilLoadPspL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPspInternal(); +} + + +// Internal function used to load the PSP. +ILboolean iLoadPspInternal() +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Channels = NULL; + Alpha = NULL; + Pal.Palette = NULL; + + if (!iGetPspHead()) + return IL_FALSE; + if (!iCheckPsp()) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ReadGenAttributes()) + return IL_FALSE; + if (!ParseChunks()) + return IL_FALSE; + if (!AssembleImage()) + return IL_FALSE; + + Cleanup(); + return ilFixImage(); +} + + +ILboolean ReadGenAttributes() +{ + BLOCKHEAD AttHead; + ILint Padding; + ILuint ChunkLen; + + if (iread(&AttHead, sizeof(AttHead), 1) != 1) + return IL_FALSE; + UShort(&AttHead.BlockID); + UInt(&AttHead.BlockLen); + + if (AttHead.HeadID[0] != 0x7E || AttHead.HeadID[1] != 0x42 || + AttHead.HeadID[2] != 0x4B || AttHead.HeadID[3] != 0x00) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + if (AttHead.BlockID != PSP_IMAGE_BLOCK) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + ChunkLen = GetLittleUInt(); + if (Header.MajorVersion != 3) + ChunkLen -= 4; + if (iread(&AttChunk, IL_MIN(sizeof(AttChunk), ChunkLen), 1) != 1) + return IL_FALSE; + + // Can have new entries in newer versions of the spec (4.0). + Padding = (ChunkLen) - sizeof(AttChunk); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + + // @TODO: Anything but 24 not supported yet... + if (AttChunk.BitDepth != 24 && AttChunk.BitDepth != 8) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // @TODO; Add support for compression... + if (AttChunk.Compression != PSP_COMP_NONE && AttChunk.Compression != PSP_COMP_RLE) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // @TODO: Check more things in the general attributes chunk here. + + return IL_TRUE; +} + + +ILboolean ParseChunks() +{ + BLOCKHEAD Block; + ILuint Pos; + + do { + if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) { + ilGetError(); // Get rid of the erroneous IL_FILE_READ_ERROR. + return IL_TRUE; + } + if (Header.MajorVersion == 3) + Block.BlockLen = GetLittleUInt(); + else + UInt(&Block.BlockLen); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || + Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { + return IL_TRUE; + } + UShort(&Block.BlockID); + UInt(&Block.BlockLen); + + Pos = itell(); + + switch (Block.BlockID) + { + case PSP_LAYER_START_BLOCK: + if (!ReadLayerBlock(Block.BlockLen)) + return IL_FALSE; + break; + + case PSP_ALPHA_BANK_BLOCK: + if (!ReadAlphaBlock(Block.BlockLen)) + return IL_FALSE; + break; + + case PSP_COLOR_BLOCK: + if (!ReadPalette(Block.BlockLen)) + return IL_FALSE; + break; + + // Gets done in the next iseek, so this is now commented out. + //default: + //iseek(Block.BlockLen, IL_SEEK_CUR); + } + + // Skip to next block just in case we didn't read the entire block. + iseek(Pos + Block.BlockLen, IL_SEEK_SET); + + // @TODO: Do stuff here. + + } while (1); + + return IL_TRUE; +} + + +ILboolean ReadLayerBlock(ILuint BlockLen) +{ + BLOCKHEAD Block; + LAYERINFO_CHUNK LayerInfo; + LAYERBITMAP_CHUNK Bitmap; + ILuint ChunkSize, Padding, i, j; + ILushort NumChars; + + BlockLen; + + // Layer sub-block header + if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) + return IL_FALSE; + if (Header.MajorVersion == 3) + Block.BlockLen = GetLittleUInt(); + else + UInt(&Block.BlockLen); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || + Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { + return IL_FALSE; + } + if (Block.BlockID != PSP_LAYER_BLOCK) + return IL_FALSE; + + + if (Header.MajorVersion == 3) { + iseek(256, IL_SEEK_CUR); // We don't care about the name of the layer. + iread(&LayerInfo, sizeof(LayerInfo), 1); + if (iread(&Bitmap, sizeof(Bitmap), 1) != 1) + return IL_FALSE; + } + else { // Header.MajorVersion >= 4 + ChunkSize = GetLittleUInt(); + NumChars = GetLittleUShort(); + iseek(NumChars, IL_SEEK_CUR); // We don't care about the layer's name. + + ChunkSize -= (2 + 4 + NumChars); + + if (iread(&LayerInfo, IL_MIN(sizeof(LayerInfo), ChunkSize), 1) != 1) + return IL_FALSE; + + // Can have new entries in newer versions of the spec (5.0). + Padding = (ChunkSize) - sizeof(LayerInfo); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + + ChunkSize = GetLittleUInt(); + if (iread(&Bitmap, sizeof(Bitmap), 1) != 1) + return IL_FALSE; + Padding = (ChunkSize - 4) - sizeof(Bitmap); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + } + + + Channels = (ILubyte**)ialloc(sizeof(ILubyte*) * Bitmap.NumChannels); + if (Channels == NULL) { + return IL_FALSE; + } + + NumChannels = Bitmap.NumChannels; + + for (i = 0; i < NumChannels; i++) { + Channels[i] = GetChannel(); + if (Channels[i] == NULL) { + for (j = 0; j < i; j++) + ifree(Channels[j]); + return IL_FALSE; + } + } + + return IL_TRUE; +} + + +ILboolean ReadAlphaBlock(ILuint BlockLen) +{ + BLOCKHEAD Block; + ALPHAINFO_CHUNK AlphaInfo; + ALPHA_CHUNK AlphaChunk; + ILushort NumAlpha, StringSize; + ILuint ChunkSize, Padding; + + if (Header.MajorVersion == 3) { + NumAlpha = GetLittleUShort(); + } + else { + ChunkSize = GetLittleUInt(); + NumAlpha = GetLittleUShort(); + Padding = (ChunkSize - 4 - 2); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + } + + // Alpha channel header + if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) + return IL_FALSE; + if (Header.MajorVersion == 3) + Block.BlockLen = GetLittleUInt(); + else + UInt(&Block.BlockLen); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || + Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { + return IL_FALSE; + } + if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK) + return IL_FALSE; + + + if (Header.MajorVersion >= 4) { + ChunkSize = GetLittleUInt(); + StringSize = GetLittleUShort(); + iseek(StringSize, IL_SEEK_CUR); + if (iread(&AlphaInfo, sizeof(AlphaInfo), 1) != 1) + return IL_FALSE; + Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo)); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + + ChunkSize = GetLittleUInt(); + if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) + return IL_FALSE; + Padding = (ChunkSize - 4 - sizeof(AlphaChunk)); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + } + else { + iseek(256, IL_SEEK_CUR); + iread(&AlphaInfo, sizeof(AlphaInfo), 1); + if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) + return IL_FALSE; + } + + + /*Alpha = (ILubyte*)ialloc(AlphaInfo.AlphaRect.x2 * AlphaInfo.AlphaRect.y2); + if (Alpha == NULL) { + return IL_FALSE; + }*/ + + + Alpha = GetChannel(); + if (Alpha == NULL) + return IL_FALSE; + + return IL_TRUE; +} + + +ILubyte *GetChannel() +{ + BLOCKHEAD Block; + CHANNEL_CHUNK Channel; + ILubyte *CompData, *Data; + ILuint ChunkSize, Padding; + + if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) + return NULL; + if (Header.MajorVersion == 3) + Block.BlockLen = GetLittleUInt(); + else + UInt(&Block.BlockLen); + + if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || + Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return NULL; + } + if (Block.BlockID != PSP_CHANNEL_BLOCK) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return NULL; + } + + + if (Header.MajorVersion >= 4) { + ChunkSize = GetLittleUInt(); + if (iread(&Channel, sizeof(Channel), 1) != 1) + return NULL; + + Padding = (ChunkSize - 4) - sizeof(Channel); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + } + else { + if (iread(&Channel, sizeof(Channel), 1) != 1) + return NULL; + } + + + CompData = (ILubyte*)ialloc(Channel.CompLen); + Data = (ILubyte*)ialloc(AttChunk.Width * AttChunk.Height); + if (CompData == NULL || Data == NULL) { + ifree(Data); + ifree(CompData); + return NULL; + } + + if (iread(CompData, 1, Channel.CompLen) != Channel.CompLen) { + ifree(CompData); + ifree(Data); + return NULL; + } + + switch (AttChunk.Compression) + { + case PSP_COMP_NONE: + ifree(Data); + return CompData; + break; + + case PSP_COMP_RLE: + if (!UncompRLE(CompData, Data, Channel.CompLen)) { + ifree(CompData); + ifree(Data); + return IL_FALSE; + } + break; + + default: + ifree(CompData); + ifree(Data); + ilSetError(IL_INVALID_FILE_HEADER); + return NULL; + } + + ifree(CompData); + + return Data; +} + + +ILboolean UncompRLE(ILubyte *CompData, ILubyte *Data, ILuint CompLen) +{ + ILubyte Run, Colour; + ILint i, /*x, y,*/ Count/*, Total = 0*/; + + /*for (y = 0; y < AttChunk.Height; y++) { + for (x = 0, Count = 0; x < AttChunk.Width; ) { + Run = *CompData++; + if (Run > 128) { + Run -= 128; + Colour = *CompData++; + memset(Data, Colour, Run); + Data += Run; + Count += 2; + } + else { + memcpy(Data, CompData, Run); + CompData += Run; + Data += Run; + Count += Run; + } + x += Run; + } + + Total += Count; + + if (Count % 4) { // Has to be on a 4-byte boundary. + CompData += (4 - (Count % 4)) % 4; + Total += (4 - (Count % 4)) % 4; + } + + if (Total >= CompLen) + return IL_FALSE; + }*/ + + for (i = 0, Count = 0; i < (ILint)CompLen; ) { + Run = *CompData++; + i++; + if (Run > 128) { + Run -= 128; + Colour = *CompData++; + i++; + memset(Data, Colour, Run); + } + else { + memcpy(Data, CompData, Run); + CompData += Run; + i += Run; + } + Data += Run; + Count += Run; + } + + return IL_TRUE; +} + + +ILboolean ReadPalette(ILuint BlockLen) +{ + ILuint ChunkSize, PalCount, Padding; + + if (Header.MajorVersion >= 4) { + ChunkSize = GetLittleUInt(); + PalCount = GetLittleUInt(); + Padding = (ChunkSize - 4 - 4); + if (Padding > 0) + iseek(Padding, IL_SEEK_CUR); + } + else { + PalCount = GetLittleUInt(); + } + + Pal.PalSize = PalCount * 4; + Pal.PalType = IL_PAL_BGRA32; + Pal.Palette = (ILubyte*)ialloc(Pal.PalSize); + if (Pal.Palette == NULL) + return IL_FALSE; + + if (iread(Pal.Palette, Pal.PalSize, 1) != 1) { + ifree(Pal.Palette); + return IL_FALSE; + } + + return IL_TRUE; +} + + +ILboolean AssembleImage() +{ + ILuint Size, i, j; + + Size = AttChunk.Width * AttChunk.Height; + + if (NumChannels == 1) { + ilTexImage(AttChunk.Width, AttChunk.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); + for (i = 0; i < Size; i++) { + iCurImage->Data[i] = Channels[0][i]; + } + + if (Pal.Palette) { + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalSize = Pal.PalSize; + iCurImage->Pal.PalType = Pal.PalType; + iCurImage->Pal.Palette = Pal.Palette; + } + } + else { + if (Alpha) { + ilTexImage(AttChunk.Width, AttChunk.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + for (i = 0, j = 0; i < Size; i++, j += 4) { + iCurImage->Data[j ] = Channels[0][i]; + iCurImage->Data[j+1] = Channels[1][i]; + iCurImage->Data[j+2] = Channels[2][i]; + iCurImage->Data[j+3] = Alpha[i]; + } + } + + else if (NumChannels == 4) { + + ilTexImage(AttChunk.Width, AttChunk.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + + for (i = 0, j = 0; i < Size; i++, j += 4) { + + iCurImage->Data[j ] = Channels[0][i]; + + iCurImage->Data[j+1] = Channels[1][i]; + + iCurImage->Data[j+2] = Channels[2][i]; + + iCurImage->Data[j+3] = Channels[3][i]; + + } + + } + else if (NumChannels == 3) { + ilTexImage(AttChunk.Width, AttChunk.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); + for (i = 0, j = 0; i < Size; i++, j += 3) { + iCurImage->Data[j ] = Channels[0][i]; + iCurImage->Data[j+1] = Channels[1][i]; + iCurImage->Data[j+2] = Channels[2][i]; + } + } + else + return IL_FALSE; + } + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + return IL_TRUE; +} + + +ILboolean Cleanup() +{ + ILuint i; + + if (Channels) { + for (i = 0; i < NumChannels; i++) { + ifree(Channels[i]); + } + ifree(Channels); + } + + if (Alpha) { + ifree(Alpha); + } + + Channels = NULL; + Alpha = NULL; + Pal.Palette = NULL; + + return IL_TRUE; +} + + + +#endif//IL_NO_PSP diff --git a/DevIL/src-IL/src/il_pxr.c b/DevIL/src-IL/src/il_pxr.c deleted file mode 100644 index b185003e..00000000 --- a/DevIL/src-IL/src/il_pxr.c +++ /dev/null @@ -1,119 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2002 by Denton Woods -// Last modified: 05/26/2002 <--Y2K Compliant! =] -// -// Filename: src-IL/src/il_pxr.c -// -// Description: Reads from a Pxrar (.pxr) file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_PXR -#include "il_endian.h" - - -#ifdef _MSC_VER -#pragma pack(push, pxr_struct, 1) -#endif -typedef struct PIXHEAD -{ - ILushort Signature; - ILubyte Reserved1[413]; - ILushort Height; - ILushort Width; - ILubyte Reserved2[4]; - ILubyte BppInfo; - ILubyte Reserved3[598]; -} IL_PACKSTRUCT PIXHEAD; -#ifdef _MSC_VER -#pragma pack(pop, pxr_struct) -#endif - -ILboolean iLoadPxrInternal(void); - - -//! Reads a Pxr file -ILboolean ilLoadPxr(ILconst_string FileName) -{ - ILHANDLE PxrFile; - ILboolean bPxr = IL_FALSE; - - PxrFile = iopenr(FileName); - if (PxrFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bPxr; - } - - bPxr = ilLoadPxrF(PxrFile); - icloser(PxrFile); - - return bPxr; -} - - -//! Reads an already-opened Pxr file -ILboolean ilLoadPxrF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadPxrInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Pxr -ILboolean ilLoadPxrL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadPxrInternal(); -} - - -// Internal function used to load the Pxr. -ILboolean iLoadPxrInternal() -{ - ILushort Width, Height; - ILubyte Bpp; - - Width = sizeof(PIXHEAD); - - iseek(416, IL_SEEK_SET); - Height = GetLittleUShort(); - Width = GetLittleUShort(); - iseek(424, IL_SEEK_SET); - Bpp = (ILubyte)igetc(); - - switch (Bpp) - { - case 0x08: - ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); - break; - case 0x0E: - ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); - break; - case 0x0F: - ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); - break; - default: - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - iseek(1024, IL_SEEK_SET); - iread(iCurImage->Data, 1, iCurImage->SizeOfData); - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - return IL_TRUE; -} - - -#endif//IL_NO_PXR diff --git a/DevIL/src-IL/src/il_pxr.cpp b/DevIL/src-IL/src/il_pxr.cpp new file mode 100644 index 00000000..b185003e --- /dev/null +++ b/DevIL/src-IL/src/il_pxr.cpp @@ -0,0 +1,119 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2002 by Denton Woods +// Last modified: 05/26/2002 <--Y2K Compliant! =] +// +// Filename: src-IL/src/il_pxr.c +// +// Description: Reads from a Pxrar (.pxr) file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_PXR +#include "il_endian.h" + + +#ifdef _MSC_VER +#pragma pack(push, pxr_struct, 1) +#endif +typedef struct PIXHEAD +{ + ILushort Signature; + ILubyte Reserved1[413]; + ILushort Height; + ILushort Width; + ILubyte Reserved2[4]; + ILubyte BppInfo; + ILubyte Reserved3[598]; +} IL_PACKSTRUCT PIXHEAD; +#ifdef _MSC_VER +#pragma pack(pop, pxr_struct) +#endif + +ILboolean iLoadPxrInternal(void); + + +//! Reads a Pxr file +ILboolean ilLoadPxr(ILconst_string FileName) +{ + ILHANDLE PxrFile; + ILboolean bPxr = IL_FALSE; + + PxrFile = iopenr(FileName); + if (PxrFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bPxr; + } + + bPxr = ilLoadPxrF(PxrFile); + icloser(PxrFile); + + return bPxr; +} + + +//! Reads an already-opened Pxr file +ILboolean ilLoadPxrF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadPxrInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Pxr +ILboolean ilLoadPxrL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadPxrInternal(); +} + + +// Internal function used to load the Pxr. +ILboolean iLoadPxrInternal() +{ + ILushort Width, Height; + ILubyte Bpp; + + Width = sizeof(PIXHEAD); + + iseek(416, IL_SEEK_SET); + Height = GetLittleUShort(); + Width = GetLittleUShort(); + iseek(424, IL_SEEK_SET); + Bpp = (ILubyte)igetc(); + + switch (Bpp) + { + case 0x08: + ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); + break; + case 0x0E: + ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); + break; + case 0x0F: + ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); + break; + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + iseek(1024, IL_SEEK_SET); + iread(iCurImage->Data, 1, iCurImage->SizeOfData); + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + return IL_TRUE; +} + + +#endif//IL_NO_PXR diff --git a/DevIL/src-IL/src/il_quantizer.c b/DevIL/src-IL/src/il_quantizer.c deleted file mode 100644 index 0e005728..00000000 --- a/DevIL/src-IL/src/il_quantizer.c +++ /dev/null @@ -1,643 +0,0 @@ -//----------------------------------------------------------------------- -// Color Quantization Demo -// -// Author: Roman Podobedov -// Email: romka@ut.ee -// Romka Graphics: www.ut.ee/~romka -// -// Also in this file implemented Wu's Color Quantizer algorithm (v. 2) -// For details see Graphics Gems vol. II, pp. 126-133 -// -// Wu's Color Quantizer Algorithm: -// Author: Xiaolin Wu -// Dept. of Computer Science -// Univ. of Western Ontario -// London, Ontario N6A 5B7 -// wu@csd.uwo.ca -// http://www.csd.uwo.ca/faculty/wu/ -//----------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// by Denton Woods -// Last modified: 01/04/2009 -// -// Filename: src-IL/src/il_quantizer.c -// -// Description: Heavily modified by Denton Woods. -// -// 20040223 XIX : Modified so it works better with color requests < 256 -// pallete always has memory space for 256 entries -// used so we can quant down to 255 colors then add a transparent color in there. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" - -#define MAXCOLOR 256 -#define RED 2 -#define GREEN 1 -#define BLUE 0 - -typedef struct Box -{ - ILint r0; // min value, exclusive - ILint r1; // max value, inclusive - ILint g0; - ILint g1; - ILint b0; - ILint b1; - ILint vol; -} Box; - -/* Histogram is in elements 1..HISTSIZE along each axis, - * element 0 is for base or marginal value - * NB: these must start out 0! - */ - -ILfloat gm2[33][33][33]; -ILint wt[33][33][33], mr[33][33][33], mg[33][33][33], mb[33][33][33]; -ILuint size; //image size -ILint K; //colour look-up table size -ILushort *Qadd; - - -ILint WindW, WindH, WindD; -ILint i; -ILubyte *buffer; -static ILint Width, Height, Depth, Comp; -/*ILint TotalColors; -ILint a, b; -ILubyte *buf1, *buf2;*/ - -ILuint n2(ILint s) -{ - ILint i; - ILint res; - - res = 1; - for (i = 0; i < s; i++) { - res = res*2; - } - - return res; -} - - -// Build 3-D color histogram of counts, r/g/b, c^2 -ILboolean Hist3d(ILubyte *Ir, ILubyte *Ig, ILubyte *Ib, ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2) -{ - ILint ind, r, g, b; - ILint inr, ing, inb, table[2560]; - ILuint i; - - for (i = 0; i < 256; i++) - { - table[i] = i * i; - } - Qadd = (ILushort*)ialloc(sizeof(ILushort) * size); - if (Qadd == NULL) - { - return IL_FALSE; - } - - imemclear(Qadd, sizeof(ILushort) * size); - - for (i = 0; i < size; i++) - { - r = Ir[i]; g = Ig[i]; b = Ib[i]; - inr = (r>>3) + 1; - ing = (g>>3) + 1; - inb = (b>>3) + 1; - Qadd[i] = ind = (inr<<10)+(inr<<6)+inr+(ing<<5)+ing+inb; - //[inr][ing][inb] - vwt[ind]++; - vmr[ind] += r; - vmg[ind] += g; - vmb[ind] += b; - m2[ind] += (ILfloat)(table[r]+table[g]+table[b]); - } - return IL_TRUE; -} - -/* At conclusion of the histogram step, we can interpret - * wt[r][g][b] = sum over voxel of P(c) - * mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb - * m2[r][g][b] = sum over voxel of c^2*P(c) - * Actually each of these should be divided by 'size' to give the usual - * interpretation of P() as ranging from 0 to 1, but we needn't do that here. - */ - -/* We now convert histogram into moments so that we can rapidly calculate - * the sums of the above quantities over any desired Box. - */ - - -// Compute cumulative moments -void M3d(ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2) -{ - ILushort ind1, ind2; - ILubyte i, r, g, b; - ILint line, line_r, line_g, line_b, area[33], area_r[33], area_g[33], area_b[33]; - ILfloat line2, area2[33]; - - for (r = 1; r <= 32; r++) { - for (i = 0; i <= 32; i++) { - area2[i] = 0.0f; - area[i]=area_r[i]=area_g[i]=area_b[i]=0; - } - for (g = 1; g <= 32; g++) { - line2 = 0.0f; - line = line_r = line_g = line_b = 0; - for (b = 1; b <= 32; b++) { - ind1 = (r<<10) + (r<<6) + r + (g<<5) + g + b; // [r][g][b] - line += vwt[ind1]; - line_r += vmr[ind1]; - line_g += vmg[ind1]; - line_b += vmb[ind1]; - line2 += m2[ind1]; - area[b] += line; - area_r[b] += line_r; - area_g[b] += line_g; - area_b[b] += line_b; - area2[b] += line2; - ind2 = ind1 - 1089; // [r-1][g][b] - vwt[ind1] = vwt[ind2] + area[b]; - vmr[ind1] = vmr[ind2] + area_r[b]; - vmg[ind1] = vmg[ind2] + area_g[b]; - vmb[ind1] = vmb[ind2] + area_b[b]; - m2[ind1] = m2[ind2] + area2[b]; - } - } - } - - return; -} - - -// Compute sum over a Box of any given statistic -ILint Vol(Box *cube, ILint mmt[33][33][33]) -{ - return( mmt[cube->r1][cube->g1][cube->b1] - -mmt[cube->r1][cube->g1][cube->b0] - -mmt[cube->r1][cube->g0][cube->b1] - +mmt[cube->r1][cube->g0][cube->b0] - -mmt[cube->r0][cube->g1][cube->b1] - +mmt[cube->r0][cube->g1][cube->b0] - +mmt[cube->r0][cube->g0][cube->b1] - -mmt[cube->r0][cube->g0][cube->b0] ); -} - -/* The next two routines allow a slightly more efficient calculation - * of Vol() for a proposed subBox of a given Box. The sum of Top() - * and Bottom() is the Vol() of a subBox split in the given direction - * and with the specified new upper bound. - */ - -// Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 -// (depending on dir) -ILint Bottom(Box *cube, ILubyte dir, ILint mmt[33][33][33]) -{ - switch(dir) - { - case RED: - return( -mmt[cube->r0][cube->g1][cube->b1] - +mmt[cube->r0][cube->g1][cube->b0] - +mmt[cube->r0][cube->g0][cube->b1] - -mmt[cube->r0][cube->g0][cube->b0] ); - break; - case GREEN: - return( -mmt[cube->r1][cube->g0][cube->b1] - +mmt[cube->r1][cube->g0][cube->b0] - +mmt[cube->r0][cube->g0][cube->b1] - -mmt[cube->r0][cube->g0][cube->b0] ); - break; - case BLUE: - return( -mmt[cube->r1][cube->g1][cube->b0] - +mmt[cube->r1][cube->g0][cube->b0] - +mmt[cube->r0][cube->g1][cube->b0] - -mmt[cube->r0][cube->g0][cube->b0] ); - break; - } - return 0; -} - - -// Compute remainder of Vol(cube, mmt), substituting pos for -// r1, g1, or b1 (depending on dir) -ILint Top(Box *cube, ILubyte dir, ILint pos, ILint mmt[33][33][33]) -{ - switch (dir) - { - case RED: - return( mmt[pos][cube->g1][cube->b1] - -mmt[pos][cube->g1][cube->b0] - -mmt[pos][cube->g0][cube->b1] - +mmt[pos][cube->g0][cube->b0] ); - break; - case GREEN: - return( mmt[cube->r1][pos][cube->b1] - -mmt[cube->r1][pos][cube->b0] - -mmt[cube->r0][pos][cube->b1] - +mmt[cube->r0][pos][cube->b0] ); - break; - case BLUE: - return( mmt[cube->r1][cube->g1][pos] - -mmt[cube->r1][cube->g0][pos] - -mmt[cube->r0][cube->g1][pos] - +mmt[cube->r0][cube->g0][pos] ); - break; - } - - return 0; -} - - -// Compute the weighted variance of a Box -// NB: as with the raw statistics, this is really the variance * size -ILfloat Var(Box *cube) -{ - ILfloat dr, dg, db, xx; - - dr = (ILfloat)Vol(cube, mr); - dg = (ILfloat)Vol(cube, mg); - db = (ILfloat)Vol(cube, mb); - xx = gm2[cube->r1][cube->g1][cube->b1] - -gm2[cube->r1][cube->g1][cube->b0] - -gm2[cube->r1][cube->g0][cube->b1] - +gm2[cube->r1][cube->g0][cube->b0] - -gm2[cube->r0][cube->g1][cube->b1] - +gm2[cube->r0][cube->g1][cube->b0] - +gm2[cube->r0][cube->g0][cube->b1] - -gm2[cube->r0][cube->g0][cube->b0]; - - return xx - (dr*dr+dg*dg+db*db) / (ILfloat)Vol(cube, wt); -} - -/* We want to minimize the sum of the variances of two subBoxes. - * The sum(c^2) terms can be ignored since their sum over both subBoxes - * is the same (the sum for the whole Box) no matter where we split. - * The remaining terms have a minus sign in the variance formula, - * so we drop the minus sign and MAXIMIZE the sum of the two terms. - */ - -ILfloat Maximize(Box *cube, ILubyte dir, ILint first, ILint last, ILint *cut, - ILint whole_r, ILint whole_g, ILint whole_b, ILint whole_w) -{ - ILint half_r, half_g, half_b, half_w; - ILint base_r, base_g, base_b, base_w; - ILint i; - ILfloat temp, max; - - base_r = Bottom(cube, dir, mr); - base_g = Bottom(cube, dir, mg); - base_b = Bottom(cube, dir, mb); - base_w = Bottom(cube, dir, wt); - max = 0.0; - *cut = -1; - - for (i = first; i < last; ++i) { - half_r = base_r + Top(cube, dir, i, mr); - half_g = base_g + Top(cube, dir, i, mg); - half_b = base_b + Top(cube, dir, i, mb); - half_w = base_w + Top(cube, dir, i, wt); - // Now half_x is sum over lower half of Box, if split at i - if (half_w == 0) { // subBox could be empty of pixels! - continue; // never split into an empty Box - } - else { - temp = ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g + - (ILfloat)half_b*half_b) / half_w; - } - - half_r = whole_r - half_r; - half_g = whole_g - half_g; - half_b = whole_b - half_b; - half_w = whole_w - half_w; - if (half_w == 0) { // subBox could be empty of pixels! - continue; // never split into an empty Box - } - else { - temp += ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g + - (ILfloat)half_b*half_b) / half_w; - } - - if (temp > max) { - max = temp; - *cut = i; - } - } - - return max; -} - - -ILint Cut(Box *set1, Box *set2) -{ - ILubyte dir; - ILint cutr, cutg, cutb; - ILfloat maxr, maxg, maxb; - ILint whole_r, whole_g, whole_b, whole_w; - - whole_r = Vol(set1, mr); - whole_g = Vol(set1, mg); - whole_b = Vol(set1, mb); - whole_w = Vol(set1, wt); - - maxr = Maximize(set1, RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w); - maxg = Maximize(set1, GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w); - maxb = Maximize(set1, BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w); - - if ((maxr >= maxg) && (maxr >= maxb)) { - dir = RED; - if (cutr < 0) - return 0; // can't split the Box - } - else if ((maxg >= maxr) && (maxg >= maxb)) - dir = GREEN; - else - dir = BLUE; - - set2->r1 = set1->r1; - set2->g1 = set1->g1; - set2->b1 = set1->b1; - - switch (dir) - { - case RED: - set2->r0 = set1->r1 = cutr; - set2->g0 = set1->g0; - set2->b0 = set1->b0; - break; - case GREEN: - set2->g0 = set1->g1 = cutg; - set2->r0 = set1->r0; - set2->b0 = set1->b0; - break; - case BLUE: - set2->b0 = set1->b1 = cutb; - set2->r0 = set1->r0; - set2->g0 = set1->g0; - break; - } - - set1->vol = (set1->r1-set1->r0) * (set1->g1-set1->g0) * (set1->b1-set1->b0); - set2->vol = (set2->r1-set2->r0) * (set2->g1-set2->g0) * (set2->b1-set2->b0); - - return 1; -} - - -void Mark(struct Box *cube, int label, unsigned char *tag) -{ - ILint r, g, b; - - for (r = cube->r0 + 1; r <= cube->r1; r++) { - for (g = cube->g0 + 1; g <= cube->g1; g++) { - for (b = cube->b0 + 1; b <= cube->b1; b++) { - tag[(r<<10) + (r<<6) + r + (g<<5) + g + b] = label; - } - } - } - return; -} - - -ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols) -{ - Box cube[MAXCOLOR]; - ILubyte *tag = NULL; - ILubyte lut_r[MAXCOLOR], lut_g[MAXCOLOR], lut_b[MAXCOLOR]; - ILint next; - ILint weight; - ILuint k; - ILfloat vv[MAXCOLOR], temp; - //ILint color_num; - ILubyte *NewData = NULL, *Palette = NULL; - ILimage *TempImage = NULL, *NewImage = NULL; - ILubyte *Ir = NULL, *Ig = NULL, *Ib = NULL; - - ILint num_alloced_colors; // number of colors we allocated space for in palette, as NumCols but will not be less than 256 - - num_alloced_colors=NumCols; - if(num_alloced_colors<256) { num_alloced_colors=256; } - - - NewImage = iCurImage; - iCurImage = Image; - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - iCurImage = NewImage; - - - - if (TempImage == NULL) - return NULL; - - buffer = Image->Data; - WindW = Width = Image->Width; - WindH = Height = Image->Height; - WindD = Depth = Image->Depth; - Comp = Image->Bpp; - Qadd = NULL; - - //color_num = ImagePrecalculate(Image); - - NewData = (ILubyte*)ialloc(Image->Width * Image->Height * Image->Depth); - Palette = (ILubyte*)ialloc(3 * num_alloced_colors); - if (!NewData || !Palette) { - ifree(NewData); - ifree(Palette); - return NULL; - } - - Ir = (ILubyte*)ialloc(Width * Height * Depth); - Ig = (ILubyte*)ialloc(Width * Height * Depth); - Ib = (ILubyte*)ialloc(Width * Height * Depth); - if (!Ir || !Ig || !Ib) { - ifree(Ir); - ifree(Ig); - ifree(Ib); - ifree(NewData); - ifree(Palette); - return NULL; - } - - size = Width * Height * Depth; - - #ifdef ALTIVEC_GCC - register ILuint v_size = size>>4; - register ILuint pos = 0; - v_size = v_size /3; - register vector unsigned char d0,d1,d2; - register vector unsigned char red[3],blu[3],green[3]; - - register union{ - vector unsigned char vec; - vector unsigned int load; - } mask_1, mask_2, mask_3; - - mask_1.load = (vector unsigned int){0xFF0000FF,0x0000FF00,0x00FF0000,0xFF0000FF}; - mask_2.load = (vector unsigned int){0x00FF0000,0xFF0000FF,0x0000FF00,0x00FF0000}; - mask_2.load = (vector unsigned int){0x0000FF00,0x00FF0000,0xFF0000FF,0x0000FF00}; - - while( v_size >= 0 ) { - d0 = vec_ld(pos,TempImage->Data); - d1 = vec_ld(pos+16,TempImage->Data); - d2 = vec_ld(pos+32,TempImage->Data); - - red[0] = vec_and(d0,mask_1.vec); - green[0] = vec_and(d0,mask_2.vec); - blu[0] = vec_and(d0,mask_3.vec); - - red[1] = vec_and(d1,mask_3.vec); - green[1] = vec_and(d1,mask_1.vec); - blu[1] = vec_and(d1,mask_2.vec); - - red[2] = vec_and(d2,mask_2.vec); - green[2] = vec_and(d2,mask_3.vec); - blu[2] = vec_and(d2,mask_1.vec); - - vec_st(red[0],pos,Ir); - vec_st(red[1],pos+16,Ir); - vec_st(red[2],pos+32,Ir); - - vec_st(blu[0],pos,Ib); - vec_st(blu[1],pos+16,Ib); - vec_st(blu[2],pos+32,Ib); - - vec_st(green[0],pos,Ig); - vec_st(green[1],pos+16,Ig); - vec_st(green[2],pos+32,Ig); - - pos += 48; - } - size -= pos; - #endif - - for (k = 0; k < size; k++) { - Ir[k] = TempImage->Data[k * 3]; - Ig[k] = TempImage->Data[k * 3 + 1]; - Ib[k] = TempImage->Data[k * 3 + 2]; - } - - #ifdef ALTIVEC_GCC - size = Width * Height * Depth; - #endif - - // Set new colors number - K = NumCols; - - if (K <= 256) { - // Begin Wu's color quantization algorithm - - // May have "leftovers" from a previous run. - - imemclear(gm2, 33 * 33 * 33 * sizeof(ILfloat)); - imemclear(wt, 33 * 33 * 33 * sizeof(ILint)); - imemclear(mr, 33 * 33 * 33 * sizeof(ILint)); - imemclear(mg, 33 * 33 * 33 * sizeof(ILint)); - imemclear(mb, 33 * 33 * 33 * sizeof(ILint)); - - if (!Hist3d(Ir, Ig, Ib, (ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2)) - goto error_label; - - M3d((ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2); - - cube[0].r0 = cube[0].g0 = cube[0].b0 = 0; - cube[0].r1 = cube[0].g1 = cube[0].b1 = 32; - next = 0; - for (i = 1; i < K; ++i) { - if (Cut(&cube[next], &cube[i])) { // volume test ensures we won't try to cut one-cell Box */ - vv[next] = (cube[next].vol>1) ? Var(&cube[next]) : 0.0f; - vv[i] = (cube[i].vol>1) ? Var(&cube[i]) : 0.0f; - } - else { - vv[next] = 0.0; // don't try to split this Box again - i--; // didn't create Box i - } - next = 0; - temp = vv[0]; - for (k = 1; (ILint)k <= i; ++k) { - if (vv[k] > temp) { - temp = vv[k]; next = k; - } - } - - if (temp <= 0.0) { - K = i+1; - // Only got K Boxes - break; - } - } - - tag = (ILubyte*)ialloc(33 * 33 * 33 * sizeof(ILubyte)); - if (tag == NULL) - goto error_label; - for (k = 0; (ILint)k < K; k++) { - Mark(&cube[k], k, tag); - weight = Vol(&cube[k], wt); - if (weight) { - lut_r[k] = (ILubyte)(Vol(&cube[k], mr) / weight); - lut_g[k] = (ILubyte)(Vol(&cube[k], mg) / weight); - lut_b[k] = (ILubyte)(Vol(&cube[k], mb) / weight); - } - else { - // Bogus Box - lut_r[k] = lut_g[k] = lut_b[k] = 0; - } - } - - for (i = 0; i < (ILint)size; i++) { - NewData[i] = tag[Qadd[i]]; - } - ifree(tag); - ifree(Qadd); - - for (k = 0; k < NumCols; k++) { - Palette[k * 3] = lut_b[k]; - Palette[k * 3 + 1] = lut_g[k]; - Palette[k * 3 + 2] = lut_r[k]; - } - } - else { // If colors more than 256 - // Begin Octree quantization - //Quant_Octree(Image->Width, Image->Height, Image->Bpp, buffer2, NewData, Palette, K); - ilSetError(IL_INTERNAL_ERROR); // Can't get much more specific than this. - goto error_label; - } - - ifree(Ig); - ifree(Ib); - ifree(Ir); - ilCloseImage(TempImage); - - NewImage = (ILimage*)icalloc(sizeof(ILimage), 1); - if (NewImage == NULL) { - return NULL; - } - ilCopyImageAttr(NewImage, Image); - NewImage->Bpp = 1; - NewImage->Bps = Image->Width; - NewImage->SizeOfPlane = NewImage->Bps * Image->Height; - NewImage->SizeOfData = NewImage->SizeOfPlane; - NewImage->Format = IL_COLOUR_INDEX; - NewImage->Type = IL_UNSIGNED_BYTE; - - NewImage->Pal.Palette = Palette; - NewImage->Pal.PalSize = 256 * 3; - NewImage->Pal.PalType = IL_PAL_BGR24; - NewImage->Data = NewData; - - return NewImage; - -error_label: - ifree(NewData); - ifree(Palette); - ifree(Ig); - ifree(Ib); - ifree(Ir); - ifree(tag); - ifree(Qadd); - return NULL; -} diff --git a/DevIL/src-IL/src/il_quantizer.cpp b/DevIL/src-IL/src/il_quantizer.cpp new file mode 100644 index 00000000..0e005728 --- /dev/null +++ b/DevIL/src-IL/src/il_quantizer.cpp @@ -0,0 +1,643 @@ +//----------------------------------------------------------------------- +// Color Quantization Demo +// +// Author: Roman Podobedov +// Email: romka@ut.ee +// Romka Graphics: www.ut.ee/~romka +// +// Also in this file implemented Wu's Color Quantizer algorithm (v. 2) +// For details see Graphics Gems vol. II, pp. 126-133 +// +// Wu's Color Quantizer Algorithm: +// Author: Xiaolin Wu +// Dept. of Computer Science +// Univ. of Western Ontario +// London, Ontario N6A 5B7 +// wu@csd.uwo.ca +// http://www.csd.uwo.ca/faculty/wu/ +//----------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// by Denton Woods +// Last modified: 01/04/2009 +// +// Filename: src-IL/src/il_quantizer.c +// +// Description: Heavily modified by Denton Woods. +// +// 20040223 XIX : Modified so it works better with color requests < 256 +// pallete always has memory space for 256 entries +// used so we can quant down to 255 colors then add a transparent color in there. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" + +#define MAXCOLOR 256 +#define RED 2 +#define GREEN 1 +#define BLUE 0 + +typedef struct Box +{ + ILint r0; // min value, exclusive + ILint r1; // max value, inclusive + ILint g0; + ILint g1; + ILint b0; + ILint b1; + ILint vol; +} Box; + +/* Histogram is in elements 1..HISTSIZE along each axis, + * element 0 is for base or marginal value + * NB: these must start out 0! + */ + +ILfloat gm2[33][33][33]; +ILint wt[33][33][33], mr[33][33][33], mg[33][33][33], mb[33][33][33]; +ILuint size; //image size +ILint K; //colour look-up table size +ILushort *Qadd; + + +ILint WindW, WindH, WindD; +ILint i; +ILubyte *buffer; +static ILint Width, Height, Depth, Comp; +/*ILint TotalColors; +ILint a, b; +ILubyte *buf1, *buf2;*/ + +ILuint n2(ILint s) +{ + ILint i; + ILint res; + + res = 1; + for (i = 0; i < s; i++) { + res = res*2; + } + + return res; +} + + +// Build 3-D color histogram of counts, r/g/b, c^2 +ILboolean Hist3d(ILubyte *Ir, ILubyte *Ig, ILubyte *Ib, ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2) +{ + ILint ind, r, g, b; + ILint inr, ing, inb, table[2560]; + ILuint i; + + for (i = 0; i < 256; i++) + { + table[i] = i * i; + } + Qadd = (ILushort*)ialloc(sizeof(ILushort) * size); + if (Qadd == NULL) + { + return IL_FALSE; + } + + imemclear(Qadd, sizeof(ILushort) * size); + + for (i = 0; i < size; i++) + { + r = Ir[i]; g = Ig[i]; b = Ib[i]; + inr = (r>>3) + 1; + ing = (g>>3) + 1; + inb = (b>>3) + 1; + Qadd[i] = ind = (inr<<10)+(inr<<6)+inr+(ing<<5)+ing+inb; + //[inr][ing][inb] + vwt[ind]++; + vmr[ind] += r; + vmg[ind] += g; + vmb[ind] += b; + m2[ind] += (ILfloat)(table[r]+table[g]+table[b]); + } + return IL_TRUE; +} + +/* At conclusion of the histogram step, we can interpret + * wt[r][g][b] = sum over voxel of P(c) + * mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb + * m2[r][g][b] = sum over voxel of c^2*P(c) + * Actually each of these should be divided by 'size' to give the usual + * interpretation of P() as ranging from 0 to 1, but we needn't do that here. + */ + +/* We now convert histogram into moments so that we can rapidly calculate + * the sums of the above quantities over any desired Box. + */ + + +// Compute cumulative moments +void M3d(ILint *vwt, ILint *vmr, ILint *vmg, ILint *vmb, ILfloat *m2) +{ + ILushort ind1, ind2; + ILubyte i, r, g, b; + ILint line, line_r, line_g, line_b, area[33], area_r[33], area_g[33], area_b[33]; + ILfloat line2, area2[33]; + + for (r = 1; r <= 32; r++) { + for (i = 0; i <= 32; i++) { + area2[i] = 0.0f; + area[i]=area_r[i]=area_g[i]=area_b[i]=0; + } + for (g = 1; g <= 32; g++) { + line2 = 0.0f; + line = line_r = line_g = line_b = 0; + for (b = 1; b <= 32; b++) { + ind1 = (r<<10) + (r<<6) + r + (g<<5) + g + b; // [r][g][b] + line += vwt[ind1]; + line_r += vmr[ind1]; + line_g += vmg[ind1]; + line_b += vmb[ind1]; + line2 += m2[ind1]; + area[b] += line; + area_r[b] += line_r; + area_g[b] += line_g; + area_b[b] += line_b; + area2[b] += line2; + ind2 = ind1 - 1089; // [r-1][g][b] + vwt[ind1] = vwt[ind2] + area[b]; + vmr[ind1] = vmr[ind2] + area_r[b]; + vmg[ind1] = vmg[ind2] + area_g[b]; + vmb[ind1] = vmb[ind2] + area_b[b]; + m2[ind1] = m2[ind2] + area2[b]; + } + } + } + + return; +} + + +// Compute sum over a Box of any given statistic +ILint Vol(Box *cube, ILint mmt[33][33][33]) +{ + return( mmt[cube->r1][cube->g1][cube->b1] + -mmt[cube->r1][cube->g1][cube->b0] + -mmt[cube->r1][cube->g0][cube->b1] + +mmt[cube->r1][cube->g0][cube->b0] + -mmt[cube->r0][cube->g1][cube->b1] + +mmt[cube->r0][cube->g1][cube->b0] + +mmt[cube->r0][cube->g0][cube->b1] + -mmt[cube->r0][cube->g0][cube->b0] ); +} + +/* The next two routines allow a slightly more efficient calculation + * of Vol() for a proposed subBox of a given Box. The sum of Top() + * and Bottom() is the Vol() of a subBox split in the given direction + * and with the specified new upper bound. + */ + +// Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1 +// (depending on dir) +ILint Bottom(Box *cube, ILubyte dir, ILint mmt[33][33][33]) +{ + switch(dir) + { + case RED: + return( -mmt[cube->r0][cube->g1][cube->b1] + +mmt[cube->r0][cube->g1][cube->b0] + +mmt[cube->r0][cube->g0][cube->b1] + -mmt[cube->r0][cube->g0][cube->b0] ); + break; + case GREEN: + return( -mmt[cube->r1][cube->g0][cube->b1] + +mmt[cube->r1][cube->g0][cube->b0] + +mmt[cube->r0][cube->g0][cube->b1] + -mmt[cube->r0][cube->g0][cube->b0] ); + break; + case BLUE: + return( -mmt[cube->r1][cube->g1][cube->b0] + +mmt[cube->r1][cube->g0][cube->b0] + +mmt[cube->r0][cube->g1][cube->b0] + -mmt[cube->r0][cube->g0][cube->b0] ); + break; + } + return 0; +} + + +// Compute remainder of Vol(cube, mmt), substituting pos for +// r1, g1, or b1 (depending on dir) +ILint Top(Box *cube, ILubyte dir, ILint pos, ILint mmt[33][33][33]) +{ + switch (dir) + { + case RED: + return( mmt[pos][cube->g1][cube->b1] + -mmt[pos][cube->g1][cube->b0] + -mmt[pos][cube->g0][cube->b1] + +mmt[pos][cube->g0][cube->b0] ); + break; + case GREEN: + return( mmt[cube->r1][pos][cube->b1] + -mmt[cube->r1][pos][cube->b0] + -mmt[cube->r0][pos][cube->b1] + +mmt[cube->r0][pos][cube->b0] ); + break; + case BLUE: + return( mmt[cube->r1][cube->g1][pos] + -mmt[cube->r1][cube->g0][pos] + -mmt[cube->r0][cube->g1][pos] + +mmt[cube->r0][cube->g0][pos] ); + break; + } + + return 0; +} + + +// Compute the weighted variance of a Box +// NB: as with the raw statistics, this is really the variance * size +ILfloat Var(Box *cube) +{ + ILfloat dr, dg, db, xx; + + dr = (ILfloat)Vol(cube, mr); + dg = (ILfloat)Vol(cube, mg); + db = (ILfloat)Vol(cube, mb); + xx = gm2[cube->r1][cube->g1][cube->b1] + -gm2[cube->r1][cube->g1][cube->b0] + -gm2[cube->r1][cube->g0][cube->b1] + +gm2[cube->r1][cube->g0][cube->b0] + -gm2[cube->r0][cube->g1][cube->b1] + +gm2[cube->r0][cube->g1][cube->b0] + +gm2[cube->r0][cube->g0][cube->b1] + -gm2[cube->r0][cube->g0][cube->b0]; + + return xx - (dr*dr+dg*dg+db*db) / (ILfloat)Vol(cube, wt); +} + +/* We want to minimize the sum of the variances of two subBoxes. + * The sum(c^2) terms can be ignored since their sum over both subBoxes + * is the same (the sum for the whole Box) no matter where we split. + * The remaining terms have a minus sign in the variance formula, + * so we drop the minus sign and MAXIMIZE the sum of the two terms. + */ + +ILfloat Maximize(Box *cube, ILubyte dir, ILint first, ILint last, ILint *cut, + ILint whole_r, ILint whole_g, ILint whole_b, ILint whole_w) +{ + ILint half_r, half_g, half_b, half_w; + ILint base_r, base_g, base_b, base_w; + ILint i; + ILfloat temp, max; + + base_r = Bottom(cube, dir, mr); + base_g = Bottom(cube, dir, mg); + base_b = Bottom(cube, dir, mb); + base_w = Bottom(cube, dir, wt); + max = 0.0; + *cut = -1; + + for (i = first; i < last; ++i) { + half_r = base_r + Top(cube, dir, i, mr); + half_g = base_g + Top(cube, dir, i, mg); + half_b = base_b + Top(cube, dir, i, mb); + half_w = base_w + Top(cube, dir, i, wt); + // Now half_x is sum over lower half of Box, if split at i + if (half_w == 0) { // subBox could be empty of pixels! + continue; // never split into an empty Box + } + else { + temp = ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g + + (ILfloat)half_b*half_b) / half_w; + } + + half_r = whole_r - half_r; + half_g = whole_g - half_g; + half_b = whole_b - half_b; + half_w = whole_w - half_w; + if (half_w == 0) { // subBox could be empty of pixels! + continue; // never split into an empty Box + } + else { + temp += ((ILfloat)half_r*half_r + (ILfloat)half_g * half_g + + (ILfloat)half_b*half_b) / half_w; + } + + if (temp > max) { + max = temp; + *cut = i; + } + } + + return max; +} + + +ILint Cut(Box *set1, Box *set2) +{ + ILubyte dir; + ILint cutr, cutg, cutb; + ILfloat maxr, maxg, maxb; + ILint whole_r, whole_g, whole_b, whole_w; + + whole_r = Vol(set1, mr); + whole_g = Vol(set1, mg); + whole_b = Vol(set1, mb); + whole_w = Vol(set1, wt); + + maxr = Maximize(set1, RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w); + maxg = Maximize(set1, GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w); + maxb = Maximize(set1, BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w); + + if ((maxr >= maxg) && (maxr >= maxb)) { + dir = RED; + if (cutr < 0) + return 0; // can't split the Box + } + else if ((maxg >= maxr) && (maxg >= maxb)) + dir = GREEN; + else + dir = BLUE; + + set2->r1 = set1->r1; + set2->g1 = set1->g1; + set2->b1 = set1->b1; + + switch (dir) + { + case RED: + set2->r0 = set1->r1 = cutr; + set2->g0 = set1->g0; + set2->b0 = set1->b0; + break; + case GREEN: + set2->g0 = set1->g1 = cutg; + set2->r0 = set1->r0; + set2->b0 = set1->b0; + break; + case BLUE: + set2->b0 = set1->b1 = cutb; + set2->r0 = set1->r0; + set2->g0 = set1->g0; + break; + } + + set1->vol = (set1->r1-set1->r0) * (set1->g1-set1->g0) * (set1->b1-set1->b0); + set2->vol = (set2->r1-set2->r0) * (set2->g1-set2->g0) * (set2->b1-set2->b0); + + return 1; +} + + +void Mark(struct Box *cube, int label, unsigned char *tag) +{ + ILint r, g, b; + + for (r = cube->r0 + 1; r <= cube->r1; r++) { + for (g = cube->g0 + 1; g <= cube->g1; g++) { + for (b = cube->b0 + 1; b <= cube->b1; b++) { + tag[(r<<10) + (r<<6) + r + (g<<5) + g + b] = label; + } + } + } + return; +} + + +ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols) +{ + Box cube[MAXCOLOR]; + ILubyte *tag = NULL; + ILubyte lut_r[MAXCOLOR], lut_g[MAXCOLOR], lut_b[MAXCOLOR]; + ILint next; + ILint weight; + ILuint k; + ILfloat vv[MAXCOLOR], temp; + //ILint color_num; + ILubyte *NewData = NULL, *Palette = NULL; + ILimage *TempImage = NULL, *NewImage = NULL; + ILubyte *Ir = NULL, *Ig = NULL, *Ib = NULL; + + ILint num_alloced_colors; // number of colors we allocated space for in palette, as NumCols but will not be less than 256 + + num_alloced_colors=NumCols; + if(num_alloced_colors<256) { num_alloced_colors=256; } + + + NewImage = iCurImage; + iCurImage = Image; + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + iCurImage = NewImage; + + + + if (TempImage == NULL) + return NULL; + + buffer = Image->Data; + WindW = Width = Image->Width; + WindH = Height = Image->Height; + WindD = Depth = Image->Depth; + Comp = Image->Bpp; + Qadd = NULL; + + //color_num = ImagePrecalculate(Image); + + NewData = (ILubyte*)ialloc(Image->Width * Image->Height * Image->Depth); + Palette = (ILubyte*)ialloc(3 * num_alloced_colors); + if (!NewData || !Palette) { + ifree(NewData); + ifree(Palette); + return NULL; + } + + Ir = (ILubyte*)ialloc(Width * Height * Depth); + Ig = (ILubyte*)ialloc(Width * Height * Depth); + Ib = (ILubyte*)ialloc(Width * Height * Depth); + if (!Ir || !Ig || !Ib) { + ifree(Ir); + ifree(Ig); + ifree(Ib); + ifree(NewData); + ifree(Palette); + return NULL; + } + + size = Width * Height * Depth; + + #ifdef ALTIVEC_GCC + register ILuint v_size = size>>4; + register ILuint pos = 0; + v_size = v_size /3; + register vector unsigned char d0,d1,d2; + register vector unsigned char red[3],blu[3],green[3]; + + register union{ + vector unsigned char vec; + vector unsigned int load; + } mask_1, mask_2, mask_3; + + mask_1.load = (vector unsigned int){0xFF0000FF,0x0000FF00,0x00FF0000,0xFF0000FF}; + mask_2.load = (vector unsigned int){0x00FF0000,0xFF0000FF,0x0000FF00,0x00FF0000}; + mask_2.load = (vector unsigned int){0x0000FF00,0x00FF0000,0xFF0000FF,0x0000FF00}; + + while( v_size >= 0 ) { + d0 = vec_ld(pos,TempImage->Data); + d1 = vec_ld(pos+16,TempImage->Data); + d2 = vec_ld(pos+32,TempImage->Data); + + red[0] = vec_and(d0,mask_1.vec); + green[0] = vec_and(d0,mask_2.vec); + blu[0] = vec_and(d0,mask_3.vec); + + red[1] = vec_and(d1,mask_3.vec); + green[1] = vec_and(d1,mask_1.vec); + blu[1] = vec_and(d1,mask_2.vec); + + red[2] = vec_and(d2,mask_2.vec); + green[2] = vec_and(d2,mask_3.vec); + blu[2] = vec_and(d2,mask_1.vec); + + vec_st(red[0],pos,Ir); + vec_st(red[1],pos+16,Ir); + vec_st(red[2],pos+32,Ir); + + vec_st(blu[0],pos,Ib); + vec_st(blu[1],pos+16,Ib); + vec_st(blu[2],pos+32,Ib); + + vec_st(green[0],pos,Ig); + vec_st(green[1],pos+16,Ig); + vec_st(green[2],pos+32,Ig); + + pos += 48; + } + size -= pos; + #endif + + for (k = 0; k < size; k++) { + Ir[k] = TempImage->Data[k * 3]; + Ig[k] = TempImage->Data[k * 3 + 1]; + Ib[k] = TempImage->Data[k * 3 + 2]; + } + + #ifdef ALTIVEC_GCC + size = Width * Height * Depth; + #endif + + // Set new colors number + K = NumCols; + + if (K <= 256) { + // Begin Wu's color quantization algorithm + + // May have "leftovers" from a previous run. + + imemclear(gm2, 33 * 33 * 33 * sizeof(ILfloat)); + imemclear(wt, 33 * 33 * 33 * sizeof(ILint)); + imemclear(mr, 33 * 33 * 33 * sizeof(ILint)); + imemclear(mg, 33 * 33 * 33 * sizeof(ILint)); + imemclear(mb, 33 * 33 * 33 * sizeof(ILint)); + + if (!Hist3d(Ir, Ig, Ib, (ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2)) + goto error_label; + + M3d((ILint*)wt, (ILint*)mr, (ILint*)mg, (ILint*)mb, (ILfloat*)gm2); + + cube[0].r0 = cube[0].g0 = cube[0].b0 = 0; + cube[0].r1 = cube[0].g1 = cube[0].b1 = 32; + next = 0; + for (i = 1; i < K; ++i) { + if (Cut(&cube[next], &cube[i])) { // volume test ensures we won't try to cut one-cell Box */ + vv[next] = (cube[next].vol>1) ? Var(&cube[next]) : 0.0f; + vv[i] = (cube[i].vol>1) ? Var(&cube[i]) : 0.0f; + } + else { + vv[next] = 0.0; // don't try to split this Box again + i--; // didn't create Box i + } + next = 0; + temp = vv[0]; + for (k = 1; (ILint)k <= i; ++k) { + if (vv[k] > temp) { + temp = vv[k]; next = k; + } + } + + if (temp <= 0.0) { + K = i+1; + // Only got K Boxes + break; + } + } + + tag = (ILubyte*)ialloc(33 * 33 * 33 * sizeof(ILubyte)); + if (tag == NULL) + goto error_label; + for (k = 0; (ILint)k < K; k++) { + Mark(&cube[k], k, tag); + weight = Vol(&cube[k], wt); + if (weight) { + lut_r[k] = (ILubyte)(Vol(&cube[k], mr) / weight); + lut_g[k] = (ILubyte)(Vol(&cube[k], mg) / weight); + lut_b[k] = (ILubyte)(Vol(&cube[k], mb) / weight); + } + else { + // Bogus Box + lut_r[k] = lut_g[k] = lut_b[k] = 0; + } + } + + for (i = 0; i < (ILint)size; i++) { + NewData[i] = tag[Qadd[i]]; + } + ifree(tag); + ifree(Qadd); + + for (k = 0; k < NumCols; k++) { + Palette[k * 3] = lut_b[k]; + Palette[k * 3 + 1] = lut_g[k]; + Palette[k * 3 + 2] = lut_r[k]; + } + } + else { // If colors more than 256 + // Begin Octree quantization + //Quant_Octree(Image->Width, Image->Height, Image->Bpp, buffer2, NewData, Palette, K); + ilSetError(IL_INTERNAL_ERROR); // Can't get much more specific than this. + goto error_label; + } + + ifree(Ig); + ifree(Ib); + ifree(Ir); + ilCloseImage(TempImage); + + NewImage = (ILimage*)icalloc(sizeof(ILimage), 1); + if (NewImage == NULL) { + return NULL; + } + ilCopyImageAttr(NewImage, Image); + NewImage->Bpp = 1; + NewImage->Bps = Image->Width; + NewImage->SizeOfPlane = NewImage->Bps * Image->Height; + NewImage->SizeOfData = NewImage->SizeOfPlane; + NewImage->Format = IL_COLOUR_INDEX; + NewImage->Type = IL_UNSIGNED_BYTE; + + NewImage->Pal.Palette = Palette; + NewImage->Pal.PalSize = 256 * 3; + NewImage->Pal.PalType = IL_PAL_BGR24; + NewImage->Data = NewData; + + return NewImage; + +error_label: + ifree(NewData); + ifree(Palette); + ifree(Ig); + ifree(Ib); + ifree(Ir); + ifree(tag); + ifree(Qadd); + return NULL; +} diff --git a/DevIL/src-IL/src/il_raw.c b/DevIL/src-IL/src/il_raw.c deleted file mode 100644 index 659b8a72..00000000 --- a/DevIL/src-IL/src/il_raw.c +++ /dev/null @@ -1,188 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_raw.c -// -// Description: "Raw" file functions -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_RAW - - -ILboolean iLoadRawInternal(void); -ILboolean iSaveRawInternal(void); - - -//! Reads a raw file -ILboolean ilLoadRaw(ILconst_string FileName) -{ - ILHANDLE RawFile; - ILboolean bRaw = IL_FALSE; - - // No need to check for raw - /*if (!iCheckExtension(FileName, "raw")) { - ilSetError(IL_INVALID_EXTENSION); - return bRaw; - }*/ - - RawFile = iopenr(FileName); - if (RawFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bRaw; - } - - bRaw = ilLoadRawF(RawFile); - icloser(RawFile); - - return bRaw; -} - - -//! Reads an already-opened raw file -ILboolean ilLoadRawF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadRawInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a raw memory "lump" -ILboolean ilLoadRawL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadRawInternal(); -} - - -// Internal function to load a raw image -ILboolean iLoadRawInternal() -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - - iCurImage->Width = GetLittleUInt(); - - iCurImage->Height = GetLittleUInt(); - - iCurImage->Depth = GetLittleUInt(); - - iCurImage->Bpp = (ILubyte)igetc(); - - if (iread(&iCurImage->Bpc, 1, 1) != 1) - return IL_FALSE; - - if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, iCurImage->Bpp, 0, ilGetTypeBpc(iCurImage->Bpc), NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - // Tries to read the correct amount of data - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) < iCurImage->SizeOfData) - return IL_FALSE; - - if (ilIsEnabled(IL_ORIGIN_SET)) { - iCurImage->Origin = ilGetInteger(IL_ORIGIN_MODE); - } - else { - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - } - - if (iCurImage->Bpp == 1) - iCurImage->Format = IL_LUMINANCE; - else if (iCurImage->Bpp == 3) - iCurImage->Format = IL_RGB; - else // 4 - iCurImage->Format = IL_RGBA; - - return ilFixImage(); -} - - -//! Writes a Raw file -ILboolean ilSaveRaw(const ILstring FileName) -{ - ILHANDLE RawFile; - ILuint RawSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - RawFile = iopenw(FileName); - if (RawFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - RawSize = ilSaveRawF(RawFile); - iclosew(RawFile); - - if (RawSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes Raw to an already-opened file -ILuint ilSaveRawF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveRawInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes Raw to a memory "lump" -ILuint ilSaveRawL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveRawInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to load the raw data. -ILboolean iSaveRawInternal() -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - SaveLittleUInt(iCurImage->Width); - SaveLittleUInt(iCurImage->Height); - SaveLittleUInt(iCurImage->Depth); - iputc(iCurImage->Bpp); - iputc(iCurImage->Bpc); - iwrite(iCurImage->Data, 1, iCurImage->SizeOfData); - - return IL_TRUE; -} - - -#endif//IL_NO_RAW diff --git a/DevIL/src-IL/src/il_raw.cpp b/DevIL/src-IL/src/il_raw.cpp new file mode 100644 index 00000000..659b8a72 --- /dev/null +++ b/DevIL/src-IL/src/il_raw.cpp @@ -0,0 +1,188 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_raw.c +// +// Description: "Raw" file functions +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_RAW + + +ILboolean iLoadRawInternal(void); +ILboolean iSaveRawInternal(void); + + +//! Reads a raw file +ILboolean ilLoadRaw(ILconst_string FileName) +{ + ILHANDLE RawFile; + ILboolean bRaw = IL_FALSE; + + // No need to check for raw + /*if (!iCheckExtension(FileName, "raw")) { + ilSetError(IL_INVALID_EXTENSION); + return bRaw; + }*/ + + RawFile = iopenr(FileName); + if (RawFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bRaw; + } + + bRaw = ilLoadRawF(RawFile); + icloser(RawFile); + + return bRaw; +} + + +//! Reads an already-opened raw file +ILboolean ilLoadRawF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadRawInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a raw memory "lump" +ILboolean ilLoadRawL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadRawInternal(); +} + + +// Internal function to load a raw image +ILboolean iLoadRawInternal() +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + + iCurImage->Width = GetLittleUInt(); + + iCurImage->Height = GetLittleUInt(); + + iCurImage->Depth = GetLittleUInt(); + + iCurImage->Bpp = (ILubyte)igetc(); + + if (iread(&iCurImage->Bpc, 1, 1) != 1) + return IL_FALSE; + + if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, iCurImage->Bpp, 0, ilGetTypeBpc(iCurImage->Bpc), NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + // Tries to read the correct amount of data + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) < iCurImage->SizeOfData) + return IL_FALSE; + + if (ilIsEnabled(IL_ORIGIN_SET)) { + iCurImage->Origin = ilGetInteger(IL_ORIGIN_MODE); + } + else { + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + } + + if (iCurImage->Bpp == 1) + iCurImage->Format = IL_LUMINANCE; + else if (iCurImage->Bpp == 3) + iCurImage->Format = IL_RGB; + else // 4 + iCurImage->Format = IL_RGBA; + + return ilFixImage(); +} + + +//! Writes a Raw file +ILboolean ilSaveRaw(const ILstring FileName) +{ + ILHANDLE RawFile; + ILuint RawSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + RawFile = iopenw(FileName); + if (RawFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + RawSize = ilSaveRawF(RawFile); + iclosew(RawFile); + + if (RawSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes Raw to an already-opened file +ILuint ilSaveRawF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveRawInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes Raw to a memory "lump" +ILuint ilSaveRawL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveRawInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to load the raw data. +ILboolean iSaveRawInternal() +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + SaveLittleUInt(iCurImage->Width); + SaveLittleUInt(iCurImage->Height); + SaveLittleUInt(iCurImage->Depth); + iputc(iCurImage->Bpp); + iputc(iCurImage->Bpc); + iwrite(iCurImage->Data, 1, iCurImage->SizeOfData); + + return IL_TRUE; +} + + +#endif//IL_NO_RAW diff --git a/DevIL/src-IL/src/il_rawdata.c b/DevIL/src-IL/src/il_rawdata.c deleted file mode 100644 index 8cfce003..00000000 --- a/DevIL/src-IL/src/il_rawdata.c +++ /dev/null @@ -1,120 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/rawdata.c -// -// Description: "Raw" file functions -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -//#ifndef IL_NO_DATA - - -ILboolean iLoadDataInternal(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp); - - -//! Reads a raw data file -ILboolean ILAPIENTRY ilLoadData(ILconst_string FileName, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) -{ - ILHANDLE RawFile; - ILboolean bRaw = IL_FALSE; - - // No need to check for raw data - /*if (!iCheckExtension(FileName, "raw")) { - ilSetError(IL_INVALID_EXTENSION); - return bRaw; - }*/ - - RawFile = iopenr(FileName); - if (RawFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bRaw; - } - - bRaw = ilLoadDataF(RawFile, Width, Height, Depth, Bpp); - icloser(RawFile); - - return bRaw; -} - - -//! Reads an already-opened raw data file -ILboolean ILAPIENTRY ilLoadDataF(ILHANDLE File, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadDataInternal(Width, Height, Depth, Bpp); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a raw data memory "lump" -ILboolean ILAPIENTRY ilLoadDataL(void *Lump, ILuint Size, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) -{ - iSetInputLump(Lump, Size); - return iLoadDataInternal(Width, Height, Depth, Bpp); -} - - -// Internal function to load a raw data image -ILboolean iLoadDataInternal(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) -{ - if (iCurImage == NULL || ((Bpp != 1) && (Bpp != 3) && (Bpp != 4))) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!ilTexImage(Width, Height, Depth, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - // Tries to read the correct amount of data - if (iread(iCurImage->Data, Width * Height * Depth * Bpp, 1) != 1) - return IL_FALSE; - - if (iCurImage->Bpp == 1) - iCurImage->Format = IL_LUMINANCE; - else if (iCurImage->Bpp == 3) - iCurImage->Format = IL_RGB; - else // 4 - iCurImage->Format = IL_RGBA; - - return ilFixImage(); -} - - -//! Save the current image to FileName as raw data -ILboolean ILAPIENTRY ilSaveData(ILconst_string FileName) -{ - ILHANDLE DataFile; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - DataFile = iopenr(FileName); - if (DataFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - iwrite(iCurImage->Data, 1, iCurImage->SizeOfData); - icloser(DataFile); - - return IL_TRUE; -} - - -//#endif//IL_NO_DATA diff --git a/DevIL/src-IL/src/il_rawdata.cpp b/DevIL/src-IL/src/il_rawdata.cpp new file mode 100644 index 00000000..8cfce003 --- /dev/null +++ b/DevIL/src-IL/src/il_rawdata.cpp @@ -0,0 +1,120 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/rawdata.c +// +// Description: "Raw" file functions +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +//#ifndef IL_NO_DATA + + +ILboolean iLoadDataInternal(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp); + + +//! Reads a raw data file +ILboolean ILAPIENTRY ilLoadData(ILconst_string FileName, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) +{ + ILHANDLE RawFile; + ILboolean bRaw = IL_FALSE; + + // No need to check for raw data + /*if (!iCheckExtension(FileName, "raw")) { + ilSetError(IL_INVALID_EXTENSION); + return bRaw; + }*/ + + RawFile = iopenr(FileName); + if (RawFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bRaw; + } + + bRaw = ilLoadDataF(RawFile, Width, Height, Depth, Bpp); + icloser(RawFile); + + return bRaw; +} + + +//! Reads an already-opened raw data file +ILboolean ILAPIENTRY ilLoadDataF(ILHANDLE File, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadDataInternal(Width, Height, Depth, Bpp); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a raw data memory "lump" +ILboolean ILAPIENTRY ilLoadDataL(void *Lump, ILuint Size, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) +{ + iSetInputLump(Lump, Size); + return iLoadDataInternal(Width, Height, Depth, Bpp); +} + + +// Internal function to load a raw data image +ILboolean iLoadDataInternal(ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp) +{ + if (iCurImage == NULL || ((Bpp != 1) && (Bpp != 3) && (Bpp != 4))) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!ilTexImage(Width, Height, Depth, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + // Tries to read the correct amount of data + if (iread(iCurImage->Data, Width * Height * Depth * Bpp, 1) != 1) + return IL_FALSE; + + if (iCurImage->Bpp == 1) + iCurImage->Format = IL_LUMINANCE; + else if (iCurImage->Bpp == 3) + iCurImage->Format = IL_RGB; + else // 4 + iCurImage->Format = IL_RGBA; + + return ilFixImage(); +} + + +//! Save the current image to FileName as raw data +ILboolean ILAPIENTRY ilSaveData(ILconst_string FileName) +{ + ILHANDLE DataFile; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + DataFile = iopenr(FileName); + if (DataFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + iwrite(iCurImage->Data, 1, iCurImage->SizeOfData); + icloser(DataFile); + + return IL_TRUE; +} + + +//#endif//IL_NO_DATA diff --git a/DevIL/src-IL/src/il_register.c b/DevIL/src-IL/src/il_register.c deleted file mode 100644 index fb095844..00000000 --- a/DevIL/src-IL/src/il_register.c +++ /dev/null @@ -1,434 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 11/07/2008 -// -// Filename: src-IL/src/il_register.c -// -// Description: Allows the caller to specify user-defined callback functions -// to open files DevIL does not support, to parse files -// differently, or anything else a person can think up. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include "il_register.h" -#include - - -// Linked lists of registered formats -iFormatL *LoadProcs = NULL; -iFormatS *SaveProcs = NULL; - - -ILboolean ILAPIENTRY ilRegisterLoad(ILconst_string Ext, IL_LOADPROC Load) { - iFormatL *TempNode, *NewNode; - - TempNode = LoadProcs; - if (TempNode != NULL) { - while (TempNode->Next != NULL) { - TempNode = TempNode->Next; - if (!iStrCmp(TempNode->Ext, Ext)) { // already registered - return IL_TRUE; - } - } - } - - NewNode = (iFormatL*)ialloc(sizeof(iFormatL)); - if (NewNode == NULL) { - return IL_FALSE; - } - - if (LoadProcs == NULL) { - LoadProcs = NewNode; - } - else { - TempNode->Next = NewNode; - } - - NewNode->Ext = ilStrDup(Ext); - NewNode->Load = Load; - NewNode->Next = NULL; - - return IL_TRUE; -} - - -ILboolean ILAPIENTRY ilRegisterSave(ILconst_string Ext, IL_SAVEPROC Save) -{ - iFormatS *TempNode, *NewNode; - - TempNode = SaveProcs; - if (TempNode != NULL) { - while (TempNode->Next != NULL) { - TempNode = TempNode->Next; - if (!iStrCmp(TempNode->Ext, Ext)) { // already registered - return IL_TRUE; - } - } - } - - NewNode = (iFormatS*)ialloc(sizeof(iFormatL)); - if (NewNode == NULL) { - return IL_FALSE; - } - - if (SaveProcs == NULL) { - SaveProcs = NewNode; - } - else { - TempNode->Next = NewNode; - } - - NewNode->Ext = ilStrDup(Ext); - NewNode->Save = Save; - NewNode->Next = NULL; - - return IL_TRUE; -} - - -//! Unregisters a load extension - doesn't have to be called. -ILboolean ILAPIENTRY ilRemoveLoad(ILconst_string Ext) -{ - iFormatL *TempNode = LoadProcs, *PrevNode = NULL; - - while (TempNode != NULL) { - if (!iStrCmp(Ext, TempNode->Ext)) { - if (PrevNode == NULL) { // first node in the list - LoadProcs = TempNode->Next; - ifree((void*)TempNode->Ext); - ifree(TempNode); - } - else { - PrevNode->Next = TempNode->Next; - ifree((void*)TempNode->Ext); - ifree(TempNode); - } - - return IL_TRUE; - } - - PrevNode = TempNode; - TempNode = TempNode->Next; - } - - return IL_FALSE; -} - - -//! Unregisters a save extension - doesn't have to be called. -ILboolean ILAPIENTRY ilRemoveSave(ILconst_string Ext) -{ - iFormatS *TempNode = SaveProcs, *PrevNode = NULL; - - while (TempNode != NULL) { - if (!iStrCmp(Ext, TempNode->Ext)) { - if (PrevNode == NULL) { // first node in the list - SaveProcs = TempNode->Next; - ifree((void*)TempNode->Ext); - ifree(TempNode); - } - else { - PrevNode->Next = TempNode->Next; - ifree((void*)TempNode->Ext); - ifree(TempNode); - } - - return IL_TRUE; - } - - PrevNode = TempNode; - TempNode = TempNode->Next; - } - - return IL_FALSE; -} - - -// Automatically removes all registered formats. -void ilRemoveRegistered() -{ - iFormatL *TempNodeL = LoadProcs; - iFormatS *TempNodeS = SaveProcs; - - while (LoadProcs != NULL) { - TempNodeL = LoadProcs->Next; - ifree((void*)LoadProcs->Ext); - ifree(LoadProcs); - LoadProcs = TempNodeL; - } - - while (SaveProcs != NULL) { - TempNodeS = SaveProcs->Next; - ifree((void*)SaveProcs->Ext); - ifree(SaveProcs); - SaveProcs = TempNodeS; - } - - return; -} - - -ILboolean iRegisterLoad(ILconst_string FileName) -{ - iFormatL *TempNode = LoadProcs; - ILstring Ext = iGetExtension(FileName); - ILenum Error; - - if (!Ext) - return IL_FALSE; - - while (TempNode != NULL) { - if (!iStrCmp(Ext, TempNode->Ext)) { - Error = TempNode->Load(FileName); - if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid. - return IL_TRUE; - } - else { - ilSetError(Error); - return IL_FALSE; - } - } - TempNode = TempNode->Next; - } - - return IL_FALSE; -} - - -ILboolean iRegisterSave(ILconst_string FileName) -{ - iFormatS *TempNode = SaveProcs; - ILstring Ext = iGetExtension(FileName); - ILenum Error; - - if (!Ext) - return IL_FALSE; - - while (TempNode != NULL) { - if (!iStrCmp(Ext, TempNode->Ext)) { - Error = TempNode->Save(FileName); - if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid. - return IL_TRUE; - } - else { - ilSetError(Error); - return IL_FALSE; - } - } - TempNode = TempNode->Next; - } - - return IL_FALSE; -} - - -// -// "Reporting" functions -// - -void ILAPIENTRY ilRegisterOrigin(ILenum Origin) -{ - switch (Origin) - { - case IL_ORIGIN_LOWER_LEFT: - case IL_ORIGIN_UPPER_LEFT: - iCurImage->Origin = Origin; - break; - default: - ilSetError(IL_INVALID_ENUM); - } - return; -} - - -void ILAPIENTRY ilRegisterFormat(ILenum Format) -{ - switch (Format) - { - case IL_COLOUR_INDEX: - case IL_RGB: - case IL_RGBA: - case IL_BGR: - case IL_BGRA: - case IL_LUMINANCE: - case IL_LUMINANCE_ALPHA: - iCurImage->Format = Format; - break; - default: - ilSetError(IL_INVALID_ENUM); - } - return; -} - - -ILboolean ILAPIENTRY ilRegisterNumFaces(ILuint Num) -{ - ILimage *Next, *Prev; - - ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. - ilCloseImage(iCurImage->Faces); // Close any current mipmaps. - - iCurImage->Faces = NULL; - if (Num == 0) // Just gets rid of all the mipmaps. - return IL_TRUE; - - iCurImage->Faces = ilNewImage(1, 1, 1, 1, 1); - if (iCurImage->Faces == NULL) - return IL_FALSE; - Next = iCurImage->Faces; - Num--; - - while (Num) { - Next->Faces = ilNewImage(1, 1, 1, 1, 1); - if (Next->Faces == NULL) { - // Clean up before we error out. - Prev = iCurImage->Faces; - while (Prev) { - Next = Prev->Faces; - ilCloseImage(Prev); - Prev = Next; - } - return IL_FALSE; - } - Next = Next->Faces; - Num--; - } - - return IL_TRUE; -} - - -ILboolean ILAPIENTRY ilRegisterMipNum(ILuint Num) -{ - ILimage *Next, *Prev; - - ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. - ilCloseImage(iCurImage->Mipmaps); // Close any current mipmaps. - - iCurImage->Mipmaps = NULL; - if (Num == 0) // Just gets rid of all the mipmaps. - return IL_TRUE; - - iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1); - if (iCurImage->Mipmaps == NULL) - return IL_FALSE; - Next = iCurImage->Mipmaps; - Num--; - - while (Num) { - Next->Next = ilNewImage(1, 1, 1, 1, 1); - if (Next->Next == NULL) { - // Clean up before we error out. - Prev = iCurImage->Mipmaps; - while (Prev) { - Next = Prev->Next; - ilCloseImage(Prev); - Prev = Next; - } - return IL_FALSE; - } - Next = Next->Next; - Num--; - } - - return IL_TRUE; -} - - -ILboolean ILAPIENTRY ilRegisterNumImages(ILuint Num) -{ - ILimage *Next, *Prev; - - ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. - ilCloseImage(iCurImage->Next); // Close any current "next" images. - - iCurImage->Next = NULL; - if (Num == 0) // Just gets rid of all the "next" images. - return IL_TRUE; - - iCurImage->Next = ilNewImage(1, 1, 1, 1, 1); - if (iCurImage->Next == NULL) - return IL_FALSE; - Next = iCurImage->Next; - Num--; - - while (Num) { - Next->Next = ilNewImage(1, 1, 1, 1, 1); - if (Next->Next == NULL) { - // Clean up before we error out. - Prev = iCurImage->Next; - while (Prev) { - Next = Prev->Next; - ilCloseImage(Prev); - Prev = Next; - } - return IL_FALSE; - } - Next = Next->Next; - Num--; - } - - return IL_TRUE; -} - - -void ILAPIENTRY ilRegisterType(ILenum Type) -{ - switch (Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - case IL_SHORT: - case IL_UNSIGNED_SHORT: - case IL_INT: - case IL_UNSIGNED_INT: - case IL_FLOAT: - case IL_DOUBLE: - iCurImage->Type = Type; - break; - default: - ilSetError(IL_INVALID_ENUM); - } - - return; -} - - -void ILAPIENTRY ilRegisterPal(void *Pal, ILuint Size, ILenum Type) -{ - if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType != IL_PAL_NONE) { - ifree(iCurImage->Pal.Palette); - } - - iCurImage->Pal.PalSize = Size; - iCurImage->Pal.PalType = Type; - iCurImage->Pal.Palette = (ILubyte*)ialloc(Size); - if (iCurImage->Pal.Palette == NULL) - return; - - if (Pal != NULL) { - memcpy(iCurImage->Pal.Palette, Pal, Size); - } - else { - ilSetError(IL_INVALID_PARAM); - } - - return; -} - - -ILboolean ILAPIENTRY ilSetDuration(ILuint Duration) -{ - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - iCurImage->Duration = Duration; - - return IL_TRUE; -} diff --git a/DevIL/src-IL/src/il_register.cpp b/DevIL/src-IL/src/il_register.cpp new file mode 100644 index 00000000..fb095844 --- /dev/null +++ b/DevIL/src-IL/src/il_register.cpp @@ -0,0 +1,434 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 11/07/2008 +// +// Filename: src-IL/src/il_register.c +// +// Description: Allows the caller to specify user-defined callback functions +// to open files DevIL does not support, to parse files +// differently, or anything else a person can think up. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include "il_register.h" +#include + + +// Linked lists of registered formats +iFormatL *LoadProcs = NULL; +iFormatS *SaveProcs = NULL; + + +ILboolean ILAPIENTRY ilRegisterLoad(ILconst_string Ext, IL_LOADPROC Load) { + iFormatL *TempNode, *NewNode; + + TempNode = LoadProcs; + if (TempNode != NULL) { + while (TempNode->Next != NULL) { + TempNode = TempNode->Next; + if (!iStrCmp(TempNode->Ext, Ext)) { // already registered + return IL_TRUE; + } + } + } + + NewNode = (iFormatL*)ialloc(sizeof(iFormatL)); + if (NewNode == NULL) { + return IL_FALSE; + } + + if (LoadProcs == NULL) { + LoadProcs = NewNode; + } + else { + TempNode->Next = NewNode; + } + + NewNode->Ext = ilStrDup(Ext); + NewNode->Load = Load; + NewNode->Next = NULL; + + return IL_TRUE; +} + + +ILboolean ILAPIENTRY ilRegisterSave(ILconst_string Ext, IL_SAVEPROC Save) +{ + iFormatS *TempNode, *NewNode; + + TempNode = SaveProcs; + if (TempNode != NULL) { + while (TempNode->Next != NULL) { + TempNode = TempNode->Next; + if (!iStrCmp(TempNode->Ext, Ext)) { // already registered + return IL_TRUE; + } + } + } + + NewNode = (iFormatS*)ialloc(sizeof(iFormatL)); + if (NewNode == NULL) { + return IL_FALSE; + } + + if (SaveProcs == NULL) { + SaveProcs = NewNode; + } + else { + TempNode->Next = NewNode; + } + + NewNode->Ext = ilStrDup(Ext); + NewNode->Save = Save; + NewNode->Next = NULL; + + return IL_TRUE; +} + + +//! Unregisters a load extension - doesn't have to be called. +ILboolean ILAPIENTRY ilRemoveLoad(ILconst_string Ext) +{ + iFormatL *TempNode = LoadProcs, *PrevNode = NULL; + + while (TempNode != NULL) { + if (!iStrCmp(Ext, TempNode->Ext)) { + if (PrevNode == NULL) { // first node in the list + LoadProcs = TempNode->Next; + ifree((void*)TempNode->Ext); + ifree(TempNode); + } + else { + PrevNode->Next = TempNode->Next; + ifree((void*)TempNode->Ext); + ifree(TempNode); + } + + return IL_TRUE; + } + + PrevNode = TempNode; + TempNode = TempNode->Next; + } + + return IL_FALSE; +} + + +//! Unregisters a save extension - doesn't have to be called. +ILboolean ILAPIENTRY ilRemoveSave(ILconst_string Ext) +{ + iFormatS *TempNode = SaveProcs, *PrevNode = NULL; + + while (TempNode != NULL) { + if (!iStrCmp(Ext, TempNode->Ext)) { + if (PrevNode == NULL) { // first node in the list + SaveProcs = TempNode->Next; + ifree((void*)TempNode->Ext); + ifree(TempNode); + } + else { + PrevNode->Next = TempNode->Next; + ifree((void*)TempNode->Ext); + ifree(TempNode); + } + + return IL_TRUE; + } + + PrevNode = TempNode; + TempNode = TempNode->Next; + } + + return IL_FALSE; +} + + +// Automatically removes all registered formats. +void ilRemoveRegistered() +{ + iFormatL *TempNodeL = LoadProcs; + iFormatS *TempNodeS = SaveProcs; + + while (LoadProcs != NULL) { + TempNodeL = LoadProcs->Next; + ifree((void*)LoadProcs->Ext); + ifree(LoadProcs); + LoadProcs = TempNodeL; + } + + while (SaveProcs != NULL) { + TempNodeS = SaveProcs->Next; + ifree((void*)SaveProcs->Ext); + ifree(SaveProcs); + SaveProcs = TempNodeS; + } + + return; +} + + +ILboolean iRegisterLoad(ILconst_string FileName) +{ + iFormatL *TempNode = LoadProcs; + ILstring Ext = iGetExtension(FileName); + ILenum Error; + + if (!Ext) + return IL_FALSE; + + while (TempNode != NULL) { + if (!iStrCmp(Ext, TempNode->Ext)) { + Error = TempNode->Load(FileName); + if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid. + return IL_TRUE; + } + else { + ilSetError(Error); + return IL_FALSE; + } + } + TempNode = TempNode->Next; + } + + return IL_FALSE; +} + + +ILboolean iRegisterSave(ILconst_string FileName) +{ + iFormatS *TempNode = SaveProcs; + ILstring Ext = iGetExtension(FileName); + ILenum Error; + + if (!Ext) + return IL_FALSE; + + while (TempNode != NULL) { + if (!iStrCmp(Ext, TempNode->Ext)) { + Error = TempNode->Save(FileName); + if (Error == IL_NO_ERROR || Error == 0) { // 0 and IL_NO_ERROR are both valid. + return IL_TRUE; + } + else { + ilSetError(Error); + return IL_FALSE; + } + } + TempNode = TempNode->Next; + } + + return IL_FALSE; +} + + +// +// "Reporting" functions +// + +void ILAPIENTRY ilRegisterOrigin(ILenum Origin) +{ + switch (Origin) + { + case IL_ORIGIN_LOWER_LEFT: + case IL_ORIGIN_UPPER_LEFT: + iCurImage->Origin = Origin; + break; + default: + ilSetError(IL_INVALID_ENUM); + } + return; +} + + +void ILAPIENTRY ilRegisterFormat(ILenum Format) +{ + switch (Format) + { + case IL_COLOUR_INDEX: + case IL_RGB: + case IL_RGBA: + case IL_BGR: + case IL_BGRA: + case IL_LUMINANCE: + case IL_LUMINANCE_ALPHA: + iCurImage->Format = Format; + break; + default: + ilSetError(IL_INVALID_ENUM); + } + return; +} + + +ILboolean ILAPIENTRY ilRegisterNumFaces(ILuint Num) +{ + ILimage *Next, *Prev; + + ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. + ilCloseImage(iCurImage->Faces); // Close any current mipmaps. + + iCurImage->Faces = NULL; + if (Num == 0) // Just gets rid of all the mipmaps. + return IL_TRUE; + + iCurImage->Faces = ilNewImage(1, 1, 1, 1, 1); + if (iCurImage->Faces == NULL) + return IL_FALSE; + Next = iCurImage->Faces; + Num--; + + while (Num) { + Next->Faces = ilNewImage(1, 1, 1, 1, 1); + if (Next->Faces == NULL) { + // Clean up before we error out. + Prev = iCurImage->Faces; + while (Prev) { + Next = Prev->Faces; + ilCloseImage(Prev); + Prev = Next; + } + return IL_FALSE; + } + Next = Next->Faces; + Num--; + } + + return IL_TRUE; +} + + +ILboolean ILAPIENTRY ilRegisterMipNum(ILuint Num) +{ + ILimage *Next, *Prev; + + ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. + ilCloseImage(iCurImage->Mipmaps); // Close any current mipmaps. + + iCurImage->Mipmaps = NULL; + if (Num == 0) // Just gets rid of all the mipmaps. + return IL_TRUE; + + iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1); + if (iCurImage->Mipmaps == NULL) + return IL_FALSE; + Next = iCurImage->Mipmaps; + Num--; + + while (Num) { + Next->Next = ilNewImage(1, 1, 1, 1, 1); + if (Next->Next == NULL) { + // Clean up before we error out. + Prev = iCurImage->Mipmaps; + while (Prev) { + Next = Prev->Next; + ilCloseImage(Prev); + Prev = Next; + } + return IL_FALSE; + } + Next = Next->Next; + Num--; + } + + return IL_TRUE; +} + + +ILboolean ILAPIENTRY ilRegisterNumImages(ILuint Num) +{ + ILimage *Next, *Prev; + + ilBindImage(ilGetCurName()); // Make sure the current image is actually bound. + ilCloseImage(iCurImage->Next); // Close any current "next" images. + + iCurImage->Next = NULL; + if (Num == 0) // Just gets rid of all the "next" images. + return IL_TRUE; + + iCurImage->Next = ilNewImage(1, 1, 1, 1, 1); + if (iCurImage->Next == NULL) + return IL_FALSE; + Next = iCurImage->Next; + Num--; + + while (Num) { + Next->Next = ilNewImage(1, 1, 1, 1, 1); + if (Next->Next == NULL) { + // Clean up before we error out. + Prev = iCurImage->Next; + while (Prev) { + Next = Prev->Next; + ilCloseImage(Prev); + Prev = Next; + } + return IL_FALSE; + } + Next = Next->Next; + Num--; + } + + return IL_TRUE; +} + + +void ILAPIENTRY ilRegisterType(ILenum Type) +{ + switch (Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + case IL_SHORT: + case IL_UNSIGNED_SHORT: + case IL_INT: + case IL_UNSIGNED_INT: + case IL_FLOAT: + case IL_DOUBLE: + iCurImage->Type = Type; + break; + default: + ilSetError(IL_INVALID_ENUM); + } + + return; +} + + +void ILAPIENTRY ilRegisterPal(void *Pal, ILuint Size, ILenum Type) +{ + if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType != IL_PAL_NONE) { + ifree(iCurImage->Pal.Palette); + } + + iCurImage->Pal.PalSize = Size; + iCurImage->Pal.PalType = Type; + iCurImage->Pal.Palette = (ILubyte*)ialloc(Size); + if (iCurImage->Pal.Palette == NULL) + return; + + if (Pal != NULL) { + memcpy(iCurImage->Pal.Palette, Pal, Size); + } + else { + ilSetError(IL_INVALID_PARAM); + } + + return; +} + + +ILboolean ILAPIENTRY ilSetDuration(ILuint Duration) +{ + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + iCurImage->Duration = Duration; + + return IL_TRUE; +} diff --git a/DevIL/src-IL/src/il_rle.c b/DevIL/src-IL/src/il_rle.c deleted file mode 100644 index 5644f8e3..00000000 --- a/DevIL/src-IL/src/il_rle.c +++ /dev/null @@ -1,153 +0,0 @@ -//----------------------------------------------------------------------------- -// Description: Functions for run-length encoding -//----------------------------------------------------------------------------- - -// RLE code from TrueVision's TGA sample code available as Tgautils.zip at -// ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version - -#define IL_RLE_C - -#include "il_internal.h" -#include "il_rle.h" - -ILboolean ilRleCompressLine(ILubyte *p, ILuint n, ILubyte bpp, - ILubyte *q, ILuint *DestWidth, ILenum CompressMode) { - - ILint DiffCount; // pixel count until two identical - ILint SameCount; // number of identical adjacent pixels - ILint RLEBufSize = 0; // count of number of bytes encoded - ILint MaxRun; - const ILint bmp_pad_to_even = 1 - ((ILint)q - *DestWidth) % 2; - - switch( CompressMode ) { - case IL_TGACOMP: - MaxRun = TGA_MAX_RUN; - break; - case IL_SGICOMP: - MaxRun = SGI_MAX_RUN; - break; - case IL_BMPCOMP: - MaxRun = BMP_MAX_RUN; - break; - default: - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - - while( n > 0 ) { - // Analyze pixels - DiffCount = CountDiffPixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n); - SameCount = CountSamePixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n); - - if( CompressMode == IL_BMPCOMP ) { - ILint remaining_data = n - DiffCount - SameCount; - if( remaining_data < 3 ) { // check if the run has gone near the end - // no absolute run can be done - // complete the line adding 0x01 + pixel, for each pixel - while( remaining_data > 0 ) { - *q++ = 0x01; - *q++ = *p++; - remaining_data--; - } - DiffCount = 0; - SameCount = 0; - n = 0; - } - } - - if( DiffCount > 0 ) { // create a raw packet (bmp absolute run) - switch(CompressMode) { - case IL_TGACOMP: - *q++ = (ILbyte)(DiffCount - 1); - break; - case IL_BMPCOMP: - *q++ = 0x00; RLEBufSize++; - *q++ = (ILbyte)DiffCount; - break; - case IL_SGICOMP: - *q++ = (ILbyte)(DiffCount | 0x80); - break; - } - n -= DiffCount; - RLEBufSize += (DiffCount * bpp) + 1; - - while( DiffCount > 0 ) { - switch(bpp) { - case 4: *q++ = *p++; - case 3: *q++ = *p++; - case 2: *q++ = *p++; - case 1: *q++ = *p++; - } - DiffCount--; - } - - if( CompressMode == IL_BMPCOMP ) { - if( (size_t)q % 2 == bmp_pad_to_even ) { - *q++ = 0x00; // insert padding - } - } - } - - if( SameCount > 1 ) { // create a RLE packet - switch(CompressMode) { - case IL_TGACOMP: - *q++ = (ILbyte)((SameCount - 1) | 0x80); - break; - case IL_SGICOMP: - case IL_BMPCOMP: - *q++ = (ILbyte)(SameCount); - break; - } - n -= SameCount; - RLEBufSize += bpp + 1; - p += (SameCount - 1) * bpp; - *q++ = *p++; - switch(bpp) { - case 4: *q++ = *p++; - case 3: *q++ = *p++; - case 2: *q++ = *p++; - case 1: *q++ = *p++; - } - } - } - - // write line termination code - switch(CompressMode) { - case IL_SGICOMP: - ++RLEBufSize; - *q++ = 0; - break; - case IL_BMPCOMP: - *q++ = 0x00; RLEBufSize++; - *q++ = 0x00; RLEBufSize++; - break; - } - *DestWidth = RLEBufSize; - - return IL_TRUE; -} - - -// Compresses an entire image using run-length encoding -ILuint ilRleCompress(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, - ILubyte *Dest, ILenum CompressMode, ILuint *ScanTable) { - ILuint DestW = 0, i, j, LineLen, Bps = Width * Bpp, SizeOfPlane = Width * Height * Bpp; - - if( ScanTable ) - imemclear(ScanTable,Depth*Height*sizeof(ILuint)); - for( j = 0; j < Depth; j++ ) { - for( i = 0; i < Height; i++ ) { - if( ScanTable ) - *ScanTable++ = DestW; - ilRleCompressLine(Data + j * SizeOfPlane + i * Bps, Width, Bpp, Dest + DestW, &LineLen, CompressMode); - DestW += LineLen; - } - } - - if( CompressMode == IL_BMPCOMP ) { // add end of image - *(Data+DestW) = 0x00; DestW++; - *(Data+DestW) = 0x01; DestW++; - } - - return DestW; -} diff --git a/DevIL/src-IL/src/il_rle.cpp b/DevIL/src-IL/src/il_rle.cpp new file mode 100644 index 00000000..5644f8e3 --- /dev/null +++ b/DevIL/src-IL/src/il_rle.cpp @@ -0,0 +1,153 @@ +//----------------------------------------------------------------------------- +// Description: Functions for run-length encoding +//----------------------------------------------------------------------------- + +// RLE code from TrueVision's TGA sample code available as Tgautils.zip at +// ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version + +#define IL_RLE_C + +#include "il_internal.h" +#include "il_rle.h" + +ILboolean ilRleCompressLine(ILubyte *p, ILuint n, ILubyte bpp, + ILubyte *q, ILuint *DestWidth, ILenum CompressMode) { + + ILint DiffCount; // pixel count until two identical + ILint SameCount; // number of identical adjacent pixels + ILint RLEBufSize = 0; // count of number of bytes encoded + ILint MaxRun; + const ILint bmp_pad_to_even = 1 - ((ILint)q - *DestWidth) % 2; + + switch( CompressMode ) { + case IL_TGACOMP: + MaxRun = TGA_MAX_RUN; + break; + case IL_SGICOMP: + MaxRun = SGI_MAX_RUN; + break; + case IL_BMPCOMP: + MaxRun = BMP_MAX_RUN; + break; + default: + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + + while( n > 0 ) { + // Analyze pixels + DiffCount = CountDiffPixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n); + SameCount = CountSamePixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n); + + if( CompressMode == IL_BMPCOMP ) { + ILint remaining_data = n - DiffCount - SameCount; + if( remaining_data < 3 ) { // check if the run has gone near the end + // no absolute run can be done + // complete the line adding 0x01 + pixel, for each pixel + while( remaining_data > 0 ) { + *q++ = 0x01; + *q++ = *p++; + remaining_data--; + } + DiffCount = 0; + SameCount = 0; + n = 0; + } + } + + if( DiffCount > 0 ) { // create a raw packet (bmp absolute run) + switch(CompressMode) { + case IL_TGACOMP: + *q++ = (ILbyte)(DiffCount - 1); + break; + case IL_BMPCOMP: + *q++ = 0x00; RLEBufSize++; + *q++ = (ILbyte)DiffCount; + break; + case IL_SGICOMP: + *q++ = (ILbyte)(DiffCount | 0x80); + break; + } + n -= DiffCount; + RLEBufSize += (DiffCount * bpp) + 1; + + while( DiffCount > 0 ) { + switch(bpp) { + case 4: *q++ = *p++; + case 3: *q++ = *p++; + case 2: *q++ = *p++; + case 1: *q++ = *p++; + } + DiffCount--; + } + + if( CompressMode == IL_BMPCOMP ) { + if( (size_t)q % 2 == bmp_pad_to_even ) { + *q++ = 0x00; // insert padding + } + } + } + + if( SameCount > 1 ) { // create a RLE packet + switch(CompressMode) { + case IL_TGACOMP: + *q++ = (ILbyte)((SameCount - 1) | 0x80); + break; + case IL_SGICOMP: + case IL_BMPCOMP: + *q++ = (ILbyte)(SameCount); + break; + } + n -= SameCount; + RLEBufSize += bpp + 1; + p += (SameCount - 1) * bpp; + *q++ = *p++; + switch(bpp) { + case 4: *q++ = *p++; + case 3: *q++ = *p++; + case 2: *q++ = *p++; + case 1: *q++ = *p++; + } + } + } + + // write line termination code + switch(CompressMode) { + case IL_SGICOMP: + ++RLEBufSize; + *q++ = 0; + break; + case IL_BMPCOMP: + *q++ = 0x00; RLEBufSize++; + *q++ = 0x00; RLEBufSize++; + break; + } + *DestWidth = RLEBufSize; + + return IL_TRUE; +} + + +// Compresses an entire image using run-length encoding +ILuint ilRleCompress(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp, + ILubyte *Dest, ILenum CompressMode, ILuint *ScanTable) { + ILuint DestW = 0, i, j, LineLen, Bps = Width * Bpp, SizeOfPlane = Width * Height * Bpp; + + if( ScanTable ) + imemclear(ScanTable,Depth*Height*sizeof(ILuint)); + for( j = 0; j < Depth; j++ ) { + for( i = 0; i < Height; i++ ) { + if( ScanTable ) + *ScanTable++ = DestW; + ilRleCompressLine(Data + j * SizeOfPlane + i * Bps, Width, Bpp, Dest + DestW, &LineLen, CompressMode); + DestW += LineLen; + } + } + + if( CompressMode == IL_BMPCOMP ) { // add end of image + *(Data+DestW) = 0x00; DestW++; + *(Data+DestW) = 0x01; DestW++; + } + + return DestW; +} diff --git a/DevIL/src-IL/src/il_rot.c b/DevIL/src-IL/src/il_rot.c deleted file mode 100644 index 38cf3067..00000000 --- a/DevIL/src-IL/src/il_rot.c +++ /dev/null @@ -1,289 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/15/2009 -// -// Filename: src-IL/src/il_rot.c -// -// Description: Reads from a Homeworld 2 - Relic Texture (.rot) file. -// -//----------------------------------------------------------------------------- - -// @TODO: -// Note: I am not certain about which is DXT3 and which is DXT5. According to -// http://forums.relicnews.com/showthread.php?t=20512, DXT3 is 1030, and DXT5 -// is 1029. However, neither way seems to work quite right for the alpha. - -#include "il_internal.h" -#ifndef IL_NO_ROT -#include "il_dds.h" - -ILboolean iLoadRotInternal(void); - -#define ROT_RGBA32 1024 -#define ROT_DXT1 1028 -#define ROT_DXT3 1029 -#define ROT_DXT5 1030 - - -//! Reads a ROT file -ILboolean ilLoadRot(ILconst_string FileName) -{ - ILHANDLE RotFile; - ILboolean bRot = IL_FALSE; - - RotFile = iopenr(FileName); - if (RotFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bRot; - } - - bRot = ilLoadRotF(RotFile); - icloser(RotFile); - - return bRot; -} - - -//! Reads an already-opened ROT file -ILboolean ilLoadRotF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadRotInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a ROT -ILboolean ilLoadRotL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadRotInternal(); -} - - -// Internal function used to load the ROT. -ILboolean iLoadRotInternal(void) -{ - ILubyte Form[4], FormName[4]; - ILuint FormLen, Width, Height, Format, Channels, CompSize; - ILuint MipSize, MipLevel, MipWidth, MipHeight; - ILenum FormatIL; - ILimage *Image; - ILboolean BaseCreated = IL_FALSE; - ILubyte *CompData = NULL; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - // The first entry in the file must be 'FORM', 0x20 in a big endian integer and then 'HEAD'. - iread(Form, 1, 4); - FormLen = GetBigUInt(); - iread(FormName, 1, 4); - if (strncmp(Form, "FORM", 4) || FormLen != 0x14 || strncmp(FormName, "HEAD", 4)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Next follows the width, height and format in the header. - Width = GetLittleUInt(); - Height = GetLittleUInt(); - Format = GetLittleUInt(); - - //@TODO: More formats. - switch (Format) - { - case ROT_RGBA32: // 32-bit RGBA format - Channels = 4; - FormatIL = IL_RGBA; - break; - - case ROT_DXT1: // DXT1 (no alpha) - Channels = 4; - FormatIL = IL_RGBA; - break; - - case ROT_DXT3: // DXT3 - case ROT_DXT5: // DXT5 - Channels = 4; - FormatIL = IL_RGBA; - // Allocates the maximum needed (the first width/height given in the file). - CompSize = ((Width + 3) / 4) * ((Height + 3) / 4) * 16; - CompData = ialloc(CompSize); - if (CompData == NULL) - return IL_FALSE; - break; - - default: - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (Width == 0 || Height == 0) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - //@TODO: Find out what this is. - GetLittleUInt(); // Skip this for the moment. This appears to be the number of channels. - - // Next comes 'FORM', a length and 'MIPS'. - iread(Form, 1, 4); - FormLen = GetBigUInt(); - iread(FormName, 1, 4); - //@TODO: Not sure if the FormLen has to be anything specific here. - if (strncmp(Form, "FORM", 4) || strncmp(FormName, "MIPS", 4)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - //@TODO: Can these mipmap levels be in any order? Some things may be easier if the answer is no. - Image = iCurImage; - do { - // Then we have 'FORM' again. - iread(Form, 1, 4); - // This is the size of the mipmap data. - MipSize = GetBigUInt(); - iread(FormName, 1, 4); - if (strncmp(Form, "FORM", 4)) { - if (!BaseCreated) { // Our file is malformed. - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - // We have reached the end of the mipmap data. - break; - } - if (strncmp(FormName, "MLVL", 4)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Next is the mipmap attributes (level number, width, height and length) - MipLevel = GetLittleUInt(); - MipWidth = GetLittleUInt(); - MipHeight = GetLittleUInt(); - MipSize = GetLittleUInt(); // This is the same as the previous size listed -20 (for attributes). - - // Lower level mipmaps cannot be larger than the main image. - if (MipWidth > Width || MipHeight > Height || MipSize > CompSize) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Just create our images here. - if (!BaseCreated) { - if (!ilTexImage(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - BaseCreated = IL_TRUE; - } - else { - Image->Mipmaps = ilNewImageFull(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL); - Image = Image->Mipmaps; - } - - switch (Format) - { - case ROT_RGBA32: // 32-bit RGBA format - if (iread(Image->Data, Image->SizeOfData, 1) != 1) - return IL_FALSE; - break; - - case ROT_DXT1: - // Allocates the size of the compressed data. - CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 8; - if (CompSize != MipSize) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - CompData = ialloc(CompSize); - if (CompData == NULL) - return IL_FALSE; - - // Read in the DXT1 data... - if (iread(CompData, CompSize, 1) != 1) - return IL_FALSE; - // ...and decompress it. - if (!DecompressDXT1(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = CompSize; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT1; - CompData = NULL; - } - break; - - case ROT_DXT3: - // Allocates the size of the compressed data. - CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; - if (CompSize != MipSize) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - CompData = ialloc(CompSize); - if (CompData == NULL) - return IL_FALSE; - - // Read in the DXT3 data... - if (iread(CompData, MipSize, 1) != 1) - return IL_FALSE; - // ...and decompress it. - if (!DecompressDXT3(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = CompSize; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT3; - CompData = NULL; - } - break; - - case ROT_DXT5: - // Allocates the size of the compressed data. - CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; - if (CompSize != MipSize) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - CompData = ialloc(CompSize); - if (CompData == NULL) - return IL_FALSE; - - // Read in the DXT5 data... - if (iread(CompData, MipSize, 1) != 1) - return IL_FALSE; - // ...and decompress it. - if (!DecompressDXT5(Image, CompData)) { - ifree(CompData); - return IL_FALSE; - } - // Keeps a copy - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = CompSize; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT5; - CompData = NULL; - } - break; - } - ifree(CompData); // Free it if it was not saved. - } while (!ieof()); //@TODO: Is there any other condition that should end this? - - return ilFixImage(); -} - -#endif//IL_NO_ROT - diff --git a/DevIL/src-IL/src/il_rot.cpp b/DevIL/src-IL/src/il_rot.cpp new file mode 100644 index 00000000..38cf3067 --- /dev/null +++ b/DevIL/src-IL/src/il_rot.cpp @@ -0,0 +1,289 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/15/2009 +// +// Filename: src-IL/src/il_rot.c +// +// Description: Reads from a Homeworld 2 - Relic Texture (.rot) file. +// +//----------------------------------------------------------------------------- + +// @TODO: +// Note: I am not certain about which is DXT3 and which is DXT5. According to +// http://forums.relicnews.com/showthread.php?t=20512, DXT3 is 1030, and DXT5 +// is 1029. However, neither way seems to work quite right for the alpha. + +#include "il_internal.h" +#ifndef IL_NO_ROT +#include "il_dds.h" + +ILboolean iLoadRotInternal(void); + +#define ROT_RGBA32 1024 +#define ROT_DXT1 1028 +#define ROT_DXT3 1029 +#define ROT_DXT5 1030 + + +//! Reads a ROT file +ILboolean ilLoadRot(ILconst_string FileName) +{ + ILHANDLE RotFile; + ILboolean bRot = IL_FALSE; + + RotFile = iopenr(FileName); + if (RotFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bRot; + } + + bRot = ilLoadRotF(RotFile); + icloser(RotFile); + + return bRot; +} + + +//! Reads an already-opened ROT file +ILboolean ilLoadRotF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadRotInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a ROT +ILboolean ilLoadRotL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadRotInternal(); +} + + +// Internal function used to load the ROT. +ILboolean iLoadRotInternal(void) +{ + ILubyte Form[4], FormName[4]; + ILuint FormLen, Width, Height, Format, Channels, CompSize; + ILuint MipSize, MipLevel, MipWidth, MipHeight; + ILenum FormatIL; + ILimage *Image; + ILboolean BaseCreated = IL_FALSE; + ILubyte *CompData = NULL; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + // The first entry in the file must be 'FORM', 0x20 in a big endian integer and then 'HEAD'. + iread(Form, 1, 4); + FormLen = GetBigUInt(); + iread(FormName, 1, 4); + if (strncmp(Form, "FORM", 4) || FormLen != 0x14 || strncmp(FormName, "HEAD", 4)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Next follows the width, height and format in the header. + Width = GetLittleUInt(); + Height = GetLittleUInt(); + Format = GetLittleUInt(); + + //@TODO: More formats. + switch (Format) + { + case ROT_RGBA32: // 32-bit RGBA format + Channels = 4; + FormatIL = IL_RGBA; + break; + + case ROT_DXT1: // DXT1 (no alpha) + Channels = 4; + FormatIL = IL_RGBA; + break; + + case ROT_DXT3: // DXT3 + case ROT_DXT5: // DXT5 + Channels = 4; + FormatIL = IL_RGBA; + // Allocates the maximum needed (the first width/height given in the file). + CompSize = ((Width + 3) / 4) * ((Height + 3) / 4) * 16; + CompData = ialloc(CompSize); + if (CompData == NULL) + return IL_FALSE; + break; + + default: + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (Width == 0 || Height == 0) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + //@TODO: Find out what this is. + GetLittleUInt(); // Skip this for the moment. This appears to be the number of channels. + + // Next comes 'FORM', a length and 'MIPS'. + iread(Form, 1, 4); + FormLen = GetBigUInt(); + iread(FormName, 1, 4); + //@TODO: Not sure if the FormLen has to be anything specific here. + if (strncmp(Form, "FORM", 4) || strncmp(FormName, "MIPS", 4)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + //@TODO: Can these mipmap levels be in any order? Some things may be easier if the answer is no. + Image = iCurImage; + do { + // Then we have 'FORM' again. + iread(Form, 1, 4); + // This is the size of the mipmap data. + MipSize = GetBigUInt(); + iread(FormName, 1, 4); + if (strncmp(Form, "FORM", 4)) { + if (!BaseCreated) { // Our file is malformed. + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + // We have reached the end of the mipmap data. + break; + } + if (strncmp(FormName, "MLVL", 4)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Next is the mipmap attributes (level number, width, height and length) + MipLevel = GetLittleUInt(); + MipWidth = GetLittleUInt(); + MipHeight = GetLittleUInt(); + MipSize = GetLittleUInt(); // This is the same as the previous size listed -20 (for attributes). + + // Lower level mipmaps cannot be larger than the main image. + if (MipWidth > Width || MipHeight > Height || MipSize > CompSize) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Just create our images here. + if (!BaseCreated) { + if (!ilTexImage(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + BaseCreated = IL_TRUE; + } + else { + Image->Mipmaps = ilNewImageFull(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL); + Image = Image->Mipmaps; + } + + switch (Format) + { + case ROT_RGBA32: // 32-bit RGBA format + if (iread(Image->Data, Image->SizeOfData, 1) != 1) + return IL_FALSE; + break; + + case ROT_DXT1: + // Allocates the size of the compressed data. + CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 8; + if (CompSize != MipSize) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + CompData = ialloc(CompSize); + if (CompData == NULL) + return IL_FALSE; + + // Read in the DXT1 data... + if (iread(CompData, CompSize, 1) != 1) + return IL_FALSE; + // ...and decompress it. + if (!DecompressDXT1(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = CompSize; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT1; + CompData = NULL; + } + break; + + case ROT_DXT3: + // Allocates the size of the compressed data. + CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; + if (CompSize != MipSize) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + CompData = ialloc(CompSize); + if (CompData == NULL) + return IL_FALSE; + + // Read in the DXT3 data... + if (iread(CompData, MipSize, 1) != 1) + return IL_FALSE; + // ...and decompress it. + if (!DecompressDXT3(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = CompSize; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT3; + CompData = NULL; + } + break; + + case ROT_DXT5: + // Allocates the size of the compressed data. + CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; + if (CompSize != MipSize) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + CompData = ialloc(CompSize); + if (CompData == NULL) + return IL_FALSE; + + // Read in the DXT5 data... + if (iread(CompData, MipSize, 1) != 1) + return IL_FALSE; + // ...and decompress it. + if (!DecompressDXT5(Image, CompData)) { + ifree(CompData); + return IL_FALSE; + } + // Keeps a copy + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = CompSize; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT5; + CompData = NULL; + } + break; + } + ifree(CompData); // Free it if it was not saved. + } while (!ieof()); //@TODO: Is there any other condition that should end this? + + return ilFixImage(); +} + +#endif//IL_NO_ROT + diff --git a/DevIL/src-IL/src/il_sgi.c b/DevIL/src-IL/src/il_sgi.c deleted file mode 100644 index 17700ed4..00000000 --- a/DevIL/src-IL/src/il_sgi.c +++ /dev/null @@ -1,762 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_sgi.c -// -// Description: Reads and writes Silicon Graphics Inc. (.sgi) files. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_SGI -#include "il_sgi.h" -#include - -static char *FName = NULL; - -/*----------------------------------------------------------------------------*/ - -/*! Checks if the file specified in FileName is a valid .sgi file. */ -ILboolean ilIsValidSgi(ILconst_string FileName) -{ - ILHANDLE SgiFile; - ILboolean bSgi = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("sgi"))) { - ilSetError(IL_INVALID_EXTENSION); - return bSgi; - } - - FName = (char*)FileName; - - SgiFile = iopenr(FileName); - if (SgiFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bSgi; - } - - bSgi = ilIsValidSgiF(SgiFile); - icloser(SgiFile); - - return bSgi; -} - -/*----------------------------------------------------------------------------*/ - -/*! Checks if the ILHANDLE contains a valid .sgi file at the current position.*/ -ILboolean ilIsValidSgiF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidSgi(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - -/*----------------------------------------------------------------------------*/ - -//! Checks if Lump is a valid .sgi lump. -ILboolean ilIsValidSgiL(const void *Lump, ILuint Size) -{ - FName = NULL; - iSetInputLump(Lump, Size); - return iIsValidSgi(); -} - -/*----------------------------------------------------------------------------*/ - -// Internal function used to get the .sgi header from the current file. -ILboolean iGetSgiHead(iSgiHeader *Header) -{ - Header->MagicNum = GetBigUShort(); - Header->Storage = (ILbyte)igetc(); - Header->Bpc = (ILbyte)igetc(); - Header->Dim = GetBigUShort(); - Header->XSize = GetBigUShort(); - Header->YSize = GetBigUShort(); - Header->ZSize = GetBigUShort(); - Header->PixMin = GetBigInt(); - Header->PixMax = GetBigInt(); - Header->Dummy1 = GetBigInt(); - iread(Header->Name, 1, 80); - Header->ColMap = GetBigInt(); - iread(Header->Dummy, 1, 404); - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -/* Internal function to get the header and check it. */ -ILboolean iIsValidSgi() -{ - iSgiHeader Head; - - if (!iGetSgiHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(iSgiHeader), IL_SEEK_CUR); // Go ahead and restore to previous state - - return iCheckSgi(&Head); -} - -/*----------------------------------------------------------------------------*/ - -/* Internal function used to check if the HEADER is a valid .sgi header. */ -ILboolean iCheckSgi(iSgiHeader *Header) -{ - if (Header->MagicNum != SGI_MAGICNUM) - return IL_FALSE; - if (Header->Storage != SGI_RLE && Header->Storage != SGI_VERBATIM) - return IL_FALSE; - if (Header->Bpc == 0 || Header->Dim == 0) - return IL_FALSE; - if (Header->XSize == 0 || Header->YSize == 0 || Header->ZSize == 0) - return IL_FALSE; - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -/*! Reads a SGI file */ -ILboolean ilLoadSgi(ILconst_string FileName) -{ - ILHANDLE SgiFile; - ILboolean bSgi = IL_FALSE; - - SgiFile = iopenr(FileName); - if (SgiFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bSgi; - } - - bSgi = ilLoadSgiF(SgiFile); - icloser(SgiFile); - - return bSgi; -} - -/*----------------------------------------------------------------------------*/ - -/*! Reads an already-opened SGI file */ -ILboolean ilLoadSgiF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadSgiInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - -/*----------------------------------------------------------------------------*/ - -/*! Reads from a memory "lump" that contains a SGI image */ -ILboolean ilLoadSgiL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadSgiInternal(); -} - -/*----------------------------------------------------------------------------*/ - -/* Internal function used to load the SGI image */ -ILboolean iLoadSgiInternal() -{ - iSgiHeader Header; - ILboolean bSgi; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetSgiHead(&Header)) - return IL_FALSE; - if (!iCheckSgi(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Bugfix for #1060946. - // The ZSize should never really be 2 by the specifications. Some - // application is outputting these, and it looks like the ZSize - // should really be 1. - if (Header.ZSize == 2) - Header.ZSize = 1; - - if (Header.Storage == SGI_RLE) { // RLE - bSgi = iReadRleSgi(&Header); - } - else { // Non-RLE //(Header.Storage == SGI_VERBATIM) - bSgi = iReadNonRleSgi(&Header); - } - - if (!bSgi) - return IL_FALSE; - return ilFixImage(); -} - -/*----------------------------------------------------------------------------*/ - -ILboolean iReadRleSgi(iSgiHeader *Head) -{ - #ifdef __LITTLE_ENDIAN__ - ILuint ixTable; - #endif - ILuint ChanInt = 0; - ILuint ixPlane, ixHeight,ixPixel, RleOff, RleLen; - ILuint *OffTable=NULL, *LenTable=NULL, TableSize, Cur; - ILubyte **TempData=NULL; - - if (!iNewSgi(Head)) - return IL_FALSE; - - TableSize = Head->YSize * Head->ZSize; - OffTable = (ILuint*)ialloc(TableSize * sizeof(ILuint)); - LenTable = (ILuint*)ialloc(TableSize * sizeof(ILuint)); - if (OffTable == NULL || LenTable == NULL) - goto cleanup_error; - if (iread(OffTable, TableSize * sizeof(ILuint), 1) != 1) - goto cleanup_error; - if (iread(LenTable, TableSize * sizeof(ILuint), 1) != 1) - goto cleanup_error; - -#ifdef __LITTLE_ENDIAN__ - // Fix the offset/len table (it's big endian format) - for (ixTable = 0; ixTable < TableSize; ixTable++) { - iSwapUInt(OffTable + ixTable); - iSwapUInt(LenTable + ixTable); - } -#endif //__LITTLE_ENDIAN__ - - // We have to create a temporary buffer for the image, because SGI - // images are plane-separated. - TempData = (ILubyte**)ialloc(Head->ZSize * sizeof(ILubyte*)); - if (TempData == NULL) - goto cleanup_error; - imemclear(TempData, Head->ZSize * sizeof(ILubyte*)); // Just in case ialloc fails then cleanup_error. - for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { - TempData[ixPlane] = (ILubyte*)ialloc(Head->XSize * Head->YSize * Head->Bpc); - if (TempData[ixPlane] == NULL) - goto cleanup_error; - } - - // Read the Planes into the temporary memory - for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { - for (ixHeight = 0, Cur = 0; ixHeight < Head->YSize; - ixHeight++, Cur += Head->XSize * Head->Bpc) { - - RleOff = OffTable[ixHeight + ixPlane * Head->YSize]; - RleLen = LenTable[ixHeight + ixPlane * Head->YSize]; - - // Seeks to the offset table position - iseek(RleOff, IL_SEEK_SET); - if (iGetScanLine((TempData[ixPlane]) + (ixHeight * Head->XSize * Head->Bpc), - Head, RleLen) != Head->XSize * Head->Bpc) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - goto cleanup_error; - } - } - } - - // DW: Removed on 05/25/2002. - /*// Check if an alphaplane exists and invert it - if (Head->ZSize == 4) { - for (ixPixel=0; (ILint)ixPixelXSize * Head->YSize; ixPixel++) { - TempData[3][ixPixel] = TempData[3][ixPixel] ^ 255; - } - }*/ - - // Assemble the image from its planes - for (ixPixel = 0; ixPixel < iCurImage->SizeOfData; - ixPixel += Head->ZSize * Head->Bpc, ChanInt += Head->Bpc) { - for (ixPlane = 0; (ILint)ixPlane < Head->ZSize * Head->Bpc; ixPlane += Head->Bpc) { - iCurImage->Data[ixPixel + ixPlane] = TempData[ixPlane][ChanInt]; - if (Head->Bpc == 2) - iCurImage->Data[ixPixel + ixPlane + 1] = TempData[ixPlane][ChanInt + 1]; - } - } - - #ifdef __LITTLE_ENDIAN__ - if (Head->Bpc == 2) - sgiSwitchData(iCurImage->Data, iCurImage->SizeOfData); - #endif - - ifree(OffTable); - ifree(LenTable); - - for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { - ifree(TempData[ixPlane]); - } - ifree(TempData); - - return IL_TRUE; - -cleanup_error: - ifree(OffTable); - ifree(LenTable); - if (TempData) { - for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { - ifree(TempData[ixPlane]); - } - ifree(TempData); - } - - return IL_FALSE; -} - -/*----------------------------------------------------------------------------*/ - -ILint iGetScanLine(ILubyte *ScanLine, iSgiHeader *Head, ILuint Length) -{ - ILushort Pixel, Count; // For current pixel - ILuint BppRead = 0, CurPos = 0, Bps = Head->XSize * Head->Bpc; - - while (BppRead < Length && CurPos < Bps) - { - Pixel = 0; - if (iread(&Pixel, Head->Bpc, 1) != 1) - return -1; - -#ifndef __LITTLE_ENDIAN__ - iSwapUShort(&Pixel); -#endif - - if (!(Count = (Pixel & 0x7f))) // If 0, line ends - return CurPos; - if (Pixel & 0x80) { // If top bit set, then it is a "run" - if (iread(ScanLine, Head->Bpc, Count) != Count) - return -1; - BppRead += Head->Bpc * Count + Head->Bpc; - ScanLine += Head->Bpc * Count; - CurPos += Head->Bpc * Count; - } - else { - if (iread(&Pixel, Head->Bpc, 1) != 1) - return -1; -#ifndef __LITTLE_ENDIAN__ - iSwapUShort(&Pixel); -#endif - if (Head->Bpc == 1) { - while (Count--) { - *ScanLine = (ILubyte)Pixel; - ScanLine++; - CurPos++; - } - } - else { - while (Count--) { - *(ILushort*)ScanLine = Pixel; - ScanLine += 2; - CurPos += 2; - } - } - BppRead += Head->Bpc + Head->Bpc; - } - } - - return CurPos; -} - - -/*----------------------------------------------------------------------------*/ - -// Much easier to read - just assemble from planes, no decompression -ILboolean iReadNonRleSgi(iSgiHeader *Head) -{ - ILuint i, c; - // ILint ChanInt = 0; Unused - ILint ChanSize; - ILboolean Cache = IL_FALSE; - - if (!iNewSgi(Head)) { - return IL_FALSE; - } - - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) { - Cache = IL_TRUE; - ChanSize = Head->XSize * Head->YSize * Head->Bpc; - iPreCache(ChanSize); - } - - for (c = 0; c < iCurImage->Bpp; c++) { - for (i = c; i < iCurImage->SizeOfData; i += iCurImage->Bpp) { - if (iread(iCurImage->Data + i, 1, 1) != 1) { - if (Cache) - iUnCache(); - return IL_FALSE; - } - } - } - - if (Cache) - iUnCache(); - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -void sgiSwitchData(ILubyte *Data, ILuint SizeOfData) -{ - ILubyte Temp; - ILuint i; - #ifdef ALTIVEC_GCC - i = 0; - union { - vector unsigned char vec; - vector unsigned int load; - }inversion_vector; - - inversion_vector.load = (vector unsigned int)\ - {0x01000302,0x05040706,0x09080B0A,0x0D0C0F0E}; - while( i <= SizeOfData-16 ) { - vector unsigned char data = vec_ld(i,Data); - vec_perm(data,data,inversion_vector.vec); - vec_st(data,i,Data); - i+=16; - } - SizeOfData -= i; - #endif - for (i = 0; i < SizeOfData; i += 2) { - Temp = Data[i]; - Data[i] = Data[i+1]; - Data[i+1] = Temp; - } - return; -} - -/*----------------------------------------------------------------------------*/ - -// Just an internal convenience function for reading SGI files -ILboolean iNewSgi(iSgiHeader *Head) -{ - if (!ilTexImage(Head->XSize, Head->YSize, Head->Bpc, (ILubyte)Head->ZSize, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - switch (Head->ZSize) - { - case 1: - iCurImage->Format = IL_LUMINANCE; - break; - /*case 2: - iCurImage->Format = IL_LUMINANCE_ALPHA; - break;*/ - case 3: - iCurImage->Format = IL_RGB; - break; - case 4: - iCurImage->Format = IL_RGBA; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - switch (Head->Bpc) - { - case 1: - if (Head->PixMin < 0) - iCurImage->Type = IL_BYTE; - else - iCurImage->Type = IL_UNSIGNED_BYTE; - break; - case 2: - if (Head->PixMin < 0) - iCurImage->Type = IL_SHORT; - else - iCurImage->Type = IL_UNSIGNED_SHORT; - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -//! Writes a SGI file -ILboolean ilSaveSgi(const ILstring FileName) -{ - ILHANDLE SgiFile; - ILuint SgiSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - SgiFile = iopenw(FileName); - if (SgiFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - SgiSize = ilSaveSgiF(SgiFile); - iclosew(SgiFile); - - if (SgiSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Sgi to an already-opened file -ILuint ilSaveSgiF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveSgiInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Sgi to a memory "lump" -ILuint ilSaveSgiL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveSgiInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -ILenum DetermineSgiType(ILenum Type) -{ - if (Type > IL_UNSIGNED_SHORT) { - if (iCurImage->Type == IL_INT) - return IL_SHORT; - return IL_UNSIGNED_SHORT; - } - return Type; -} - -/*----------------------------------------------------------------------------*/ - -// Rle does NOT work yet. - -// Internal function used to save the Sgi. -ILboolean iSaveSgiInternal() -{ - ILuint i, c; - ILboolean Compress; - ILimage *Temp = iCurImage; - ILubyte *TempData; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (iCurImage->Format != IL_LUMINANCE - //while the sgi spec doesn't directly forbid rgb files with 2 - //channels, they are quite uncommon and most apps don't support - //them. so convert lum_a images to rgba before writing. - //&& iCurImage->Format != IL_LUMINANCE_ALPHA - && iCurImage->Format != IL_RGB - && iCurImage->Format != IL_RGBA) { - if (iCurImage->Format == IL_BGRA || iCurImage->Format == IL_LUMINANCE_ALPHA) - Temp = iConvertImage(iCurImage, IL_RGBA, DetermineSgiType(iCurImage->Type)); - else - Temp = iConvertImage(iCurImage, IL_RGB, DetermineSgiType(iCurImage->Type)); - } - else if (iCurImage->Type > IL_UNSIGNED_SHORT) { - Temp = iConvertImage(iCurImage, iCurImage->Format, DetermineSgiType(iCurImage->Type)); - } - - //compression of images with 2 bytes per channel doesn't work yet - Compress = iGetInt(IL_SGI_RLE) && Temp->Bpc == 1; - - if (Temp == NULL) - return IL_FALSE; - - SaveBigUShort(SGI_MAGICNUM); // 'Magic' number - if (Compress) - iputc(1); - else - iputc(0); - - if (Temp->Type == IL_UNSIGNED_BYTE) - iputc(1); - else if (Temp->Type == IL_UNSIGNED_SHORT) - iputc(2); - // Need to error here if not one of the two... - - if (Temp->Format == IL_LUMINANCE || Temp->Format == IL_COLOUR_INDEX) - SaveBigUShort(2); - else - SaveBigUShort(3); - - SaveBigUShort((ILushort)Temp->Width); - SaveBigUShort((ILushort)Temp->Height); - SaveBigUShort((ILushort)Temp->Bpp); - - switch (Temp->Type) - { - case IL_BYTE: - SaveBigInt(SCHAR_MIN); // Minimum pixel value - SaveBigInt(SCHAR_MAX); // Maximum pixel value - break; - case IL_UNSIGNED_BYTE: - SaveBigInt(0); // Minimum pixel value - SaveBigInt(UCHAR_MAX); // Maximum pixel value - break; - case IL_SHORT: - SaveBigInt(SHRT_MIN); // Minimum pixel value - SaveBigInt(SHRT_MAX); // Maximum pixel value - break; - case IL_UNSIGNED_SHORT: - SaveBigInt(0); // Minimum pixel value - SaveBigInt(USHRT_MAX); // Maximum pixel value - break; - } - - SaveBigInt(0); // Dummy value - - if (FName) { - c = ilCharStrLen(FName); - c = c < 79 ? 79 : c; - iwrite(FName, 1, c); - c = 80 - c; - for (i = 0; i < c; i++) { - iputc(0); - } - } - else { - for (i = 0; i < 80; i++) { - iputc(0); - } - } - - SaveBigUInt(0); // Colormap - - // Padding - for (i = 0; i < 101; i++) { - SaveLittleInt(0); - } - - - if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) { - TempData = iGetFlipped(Temp); - if (TempData == NULL) { - if (Temp!= iCurImage) - ilCloseImage(Temp); - return IL_FALSE; - } - } - else { - TempData = Temp->Data; - } - - - if (!Compress) { - for (c = 0; c < Temp->Bpp; c++) { - for (i = c; i < Temp->SizeOfData; i += Temp->Bpp) { - iputc(TempData[i]); // Have to save each colour plane separately. - } - } - } - else { - iSaveRleSgi(TempData, Temp->Width, Temp->Height, Temp->Bpp, Temp->Bps); - } - - - if (TempData != Temp->Data) - ifree(TempData); - if (Temp != iCurImage) - ilCloseImage(Temp); - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -ILboolean iSaveRleSgi(ILubyte *Data, ILuint w, ILuint h, ILuint numChannels, - ILuint bps) -{ - //works only for sgi files with only 1 bpc - - ILuint c, i, y, j; - ILubyte *ScanLine = NULL, *CompLine = NULL; - ILuint *StartTable = NULL, *LenTable = NULL; - ILuint TableOff, DataOff = 0; - - ScanLine = (ILubyte*)ialloc(w); - CompLine = (ILubyte*)ialloc(w * 2 + 1); // Absolute worst case. - StartTable = (ILuint*)ialloc(h * numChannels * sizeof(ILuint)); - LenTable = (ILuint*)icalloc(h * numChannels, sizeof(ILuint)); - if (!ScanLine || !CompLine || !StartTable || !LenTable) { - ifree(ScanLine); - ifree(CompLine); - ifree(StartTable); - ifree(LenTable); - return IL_FALSE; - } - - // These just contain dummy values at this point. - TableOff = itellw(); - iwrite(StartTable, sizeof(ILuint), h * numChannels); - iwrite(LenTable, sizeof(ILuint), h * numChannels); - - DataOff = itellw(); - for (c = 0; c < numChannels; c++) { - for (y = 0; y < h; y++) { - i = y * bps + c; - for (j = 0; j < w; j++, i += numChannels) { - ScanLine[j] = Data[i]; - } - - ilRleCompressLine(ScanLine, w, 1, CompLine, LenTable + h * c + y, IL_SGICOMP); - iwrite(CompLine, 1, *(LenTable + h * c + y)); - } - } - - iseekw(TableOff, IL_SEEK_SET); - - j = h * numChannels; - for (y = 0; y < j; y++) { - StartTable[y] = DataOff; - DataOff += LenTable[y]; -#ifdef __LITTLE_ENDIAN__ - iSwapUInt(&StartTable[y]); - iSwapUInt(&LenTable[y]); -#endif - } - - iwrite(StartTable, sizeof(ILuint), h * numChannels); - iwrite(LenTable, sizeof(ILuint), h * numChannels); - - ifree(ScanLine); - ifree(CompLine); - ifree(StartTable); - ifree(LenTable); - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -#endif//IL_NO_SGI diff --git a/DevIL/src-IL/src/il_sgi.cpp b/DevIL/src-IL/src/il_sgi.cpp new file mode 100644 index 00000000..17700ed4 --- /dev/null +++ b/DevIL/src-IL/src/il_sgi.cpp @@ -0,0 +1,762 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_sgi.c +// +// Description: Reads and writes Silicon Graphics Inc. (.sgi) files. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_SGI +#include "il_sgi.h" +#include + +static char *FName = NULL; + +/*----------------------------------------------------------------------------*/ + +/*! Checks if the file specified in FileName is a valid .sgi file. */ +ILboolean ilIsValidSgi(ILconst_string FileName) +{ + ILHANDLE SgiFile; + ILboolean bSgi = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("sgi"))) { + ilSetError(IL_INVALID_EXTENSION); + return bSgi; + } + + FName = (char*)FileName; + + SgiFile = iopenr(FileName); + if (SgiFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bSgi; + } + + bSgi = ilIsValidSgiF(SgiFile); + icloser(SgiFile); + + return bSgi; +} + +/*----------------------------------------------------------------------------*/ + +/*! Checks if the ILHANDLE contains a valid .sgi file at the current position.*/ +ILboolean ilIsValidSgiF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidSgi(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ + +//! Checks if Lump is a valid .sgi lump. +ILboolean ilIsValidSgiL(const void *Lump, ILuint Size) +{ + FName = NULL; + iSetInputLump(Lump, Size); + return iIsValidSgi(); +} + +/*----------------------------------------------------------------------------*/ + +// Internal function used to get the .sgi header from the current file. +ILboolean iGetSgiHead(iSgiHeader *Header) +{ + Header->MagicNum = GetBigUShort(); + Header->Storage = (ILbyte)igetc(); + Header->Bpc = (ILbyte)igetc(); + Header->Dim = GetBigUShort(); + Header->XSize = GetBigUShort(); + Header->YSize = GetBigUShort(); + Header->ZSize = GetBigUShort(); + Header->PixMin = GetBigInt(); + Header->PixMax = GetBigInt(); + Header->Dummy1 = GetBigInt(); + iread(Header->Name, 1, 80); + Header->ColMap = GetBigInt(); + iread(Header->Dummy, 1, 404); + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +/* Internal function to get the header and check it. */ +ILboolean iIsValidSgi() +{ + iSgiHeader Head; + + if (!iGetSgiHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(iSgiHeader), IL_SEEK_CUR); // Go ahead and restore to previous state + + return iCheckSgi(&Head); +} + +/*----------------------------------------------------------------------------*/ + +/* Internal function used to check if the HEADER is a valid .sgi header. */ +ILboolean iCheckSgi(iSgiHeader *Header) +{ + if (Header->MagicNum != SGI_MAGICNUM) + return IL_FALSE; + if (Header->Storage != SGI_RLE && Header->Storage != SGI_VERBATIM) + return IL_FALSE; + if (Header->Bpc == 0 || Header->Dim == 0) + return IL_FALSE; + if (Header->XSize == 0 || Header->YSize == 0 || Header->ZSize == 0) + return IL_FALSE; + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +/*! Reads a SGI file */ +ILboolean ilLoadSgi(ILconst_string FileName) +{ + ILHANDLE SgiFile; + ILboolean bSgi = IL_FALSE; + + SgiFile = iopenr(FileName); + if (SgiFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bSgi; + } + + bSgi = ilLoadSgiF(SgiFile); + icloser(SgiFile); + + return bSgi; +} + +/*----------------------------------------------------------------------------*/ + +/*! Reads an already-opened SGI file */ +ILboolean ilLoadSgiF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadSgiInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ + +/*! Reads from a memory "lump" that contains a SGI image */ +ILboolean ilLoadSgiL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadSgiInternal(); +} + +/*----------------------------------------------------------------------------*/ + +/* Internal function used to load the SGI image */ +ILboolean iLoadSgiInternal() +{ + iSgiHeader Header; + ILboolean bSgi; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetSgiHead(&Header)) + return IL_FALSE; + if (!iCheckSgi(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Bugfix for #1060946. + // The ZSize should never really be 2 by the specifications. Some + // application is outputting these, and it looks like the ZSize + // should really be 1. + if (Header.ZSize == 2) + Header.ZSize = 1; + + if (Header.Storage == SGI_RLE) { // RLE + bSgi = iReadRleSgi(&Header); + } + else { // Non-RLE //(Header.Storage == SGI_VERBATIM) + bSgi = iReadNonRleSgi(&Header); + } + + if (!bSgi) + return IL_FALSE; + return ilFixImage(); +} + +/*----------------------------------------------------------------------------*/ + +ILboolean iReadRleSgi(iSgiHeader *Head) +{ + #ifdef __LITTLE_ENDIAN__ + ILuint ixTable; + #endif + ILuint ChanInt = 0; + ILuint ixPlane, ixHeight,ixPixel, RleOff, RleLen; + ILuint *OffTable=NULL, *LenTable=NULL, TableSize, Cur; + ILubyte **TempData=NULL; + + if (!iNewSgi(Head)) + return IL_FALSE; + + TableSize = Head->YSize * Head->ZSize; + OffTable = (ILuint*)ialloc(TableSize * sizeof(ILuint)); + LenTable = (ILuint*)ialloc(TableSize * sizeof(ILuint)); + if (OffTable == NULL || LenTable == NULL) + goto cleanup_error; + if (iread(OffTable, TableSize * sizeof(ILuint), 1) != 1) + goto cleanup_error; + if (iread(LenTable, TableSize * sizeof(ILuint), 1) != 1) + goto cleanup_error; + +#ifdef __LITTLE_ENDIAN__ + // Fix the offset/len table (it's big endian format) + for (ixTable = 0; ixTable < TableSize; ixTable++) { + iSwapUInt(OffTable + ixTable); + iSwapUInt(LenTable + ixTable); + } +#endif //__LITTLE_ENDIAN__ + + // We have to create a temporary buffer for the image, because SGI + // images are plane-separated. + TempData = (ILubyte**)ialloc(Head->ZSize * sizeof(ILubyte*)); + if (TempData == NULL) + goto cleanup_error; + imemclear(TempData, Head->ZSize * sizeof(ILubyte*)); // Just in case ialloc fails then cleanup_error. + for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { + TempData[ixPlane] = (ILubyte*)ialloc(Head->XSize * Head->YSize * Head->Bpc); + if (TempData[ixPlane] == NULL) + goto cleanup_error; + } + + // Read the Planes into the temporary memory + for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { + for (ixHeight = 0, Cur = 0; ixHeight < Head->YSize; + ixHeight++, Cur += Head->XSize * Head->Bpc) { + + RleOff = OffTable[ixHeight + ixPlane * Head->YSize]; + RleLen = LenTable[ixHeight + ixPlane * Head->YSize]; + + // Seeks to the offset table position + iseek(RleOff, IL_SEEK_SET); + if (iGetScanLine((TempData[ixPlane]) + (ixHeight * Head->XSize * Head->Bpc), + Head, RleLen) != Head->XSize * Head->Bpc) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + goto cleanup_error; + } + } + } + + // DW: Removed on 05/25/2002. + /*// Check if an alphaplane exists and invert it + if (Head->ZSize == 4) { + for (ixPixel=0; (ILint)ixPixelXSize * Head->YSize; ixPixel++) { + TempData[3][ixPixel] = TempData[3][ixPixel] ^ 255; + } + }*/ + + // Assemble the image from its planes + for (ixPixel = 0; ixPixel < iCurImage->SizeOfData; + ixPixel += Head->ZSize * Head->Bpc, ChanInt += Head->Bpc) { + for (ixPlane = 0; (ILint)ixPlane < Head->ZSize * Head->Bpc; ixPlane += Head->Bpc) { + iCurImage->Data[ixPixel + ixPlane] = TempData[ixPlane][ChanInt]; + if (Head->Bpc == 2) + iCurImage->Data[ixPixel + ixPlane + 1] = TempData[ixPlane][ChanInt + 1]; + } + } + + #ifdef __LITTLE_ENDIAN__ + if (Head->Bpc == 2) + sgiSwitchData(iCurImage->Data, iCurImage->SizeOfData); + #endif + + ifree(OffTable); + ifree(LenTable); + + for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { + ifree(TempData[ixPlane]); + } + ifree(TempData); + + return IL_TRUE; + +cleanup_error: + ifree(OffTable); + ifree(LenTable); + if (TempData) { + for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { + ifree(TempData[ixPlane]); + } + ifree(TempData); + } + + return IL_FALSE; +} + +/*----------------------------------------------------------------------------*/ + +ILint iGetScanLine(ILubyte *ScanLine, iSgiHeader *Head, ILuint Length) +{ + ILushort Pixel, Count; // For current pixel + ILuint BppRead = 0, CurPos = 0, Bps = Head->XSize * Head->Bpc; + + while (BppRead < Length && CurPos < Bps) + { + Pixel = 0; + if (iread(&Pixel, Head->Bpc, 1) != 1) + return -1; + +#ifndef __LITTLE_ENDIAN__ + iSwapUShort(&Pixel); +#endif + + if (!(Count = (Pixel & 0x7f))) // If 0, line ends + return CurPos; + if (Pixel & 0x80) { // If top bit set, then it is a "run" + if (iread(ScanLine, Head->Bpc, Count) != Count) + return -1; + BppRead += Head->Bpc * Count + Head->Bpc; + ScanLine += Head->Bpc * Count; + CurPos += Head->Bpc * Count; + } + else { + if (iread(&Pixel, Head->Bpc, 1) != 1) + return -1; +#ifndef __LITTLE_ENDIAN__ + iSwapUShort(&Pixel); +#endif + if (Head->Bpc == 1) { + while (Count--) { + *ScanLine = (ILubyte)Pixel; + ScanLine++; + CurPos++; + } + } + else { + while (Count--) { + *(ILushort*)ScanLine = Pixel; + ScanLine += 2; + CurPos += 2; + } + } + BppRead += Head->Bpc + Head->Bpc; + } + } + + return CurPos; +} + + +/*----------------------------------------------------------------------------*/ + +// Much easier to read - just assemble from planes, no decompression +ILboolean iReadNonRleSgi(iSgiHeader *Head) +{ + ILuint i, c; + // ILint ChanInt = 0; Unused + ILint ChanSize; + ILboolean Cache = IL_FALSE; + + if (!iNewSgi(Head)) { + return IL_FALSE; + } + + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) { + Cache = IL_TRUE; + ChanSize = Head->XSize * Head->YSize * Head->Bpc; + iPreCache(ChanSize); + } + + for (c = 0; c < iCurImage->Bpp; c++) { + for (i = c; i < iCurImage->SizeOfData; i += iCurImage->Bpp) { + if (iread(iCurImage->Data + i, 1, 1) != 1) { + if (Cache) + iUnCache(); + return IL_FALSE; + } + } + } + + if (Cache) + iUnCache(); + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +void sgiSwitchData(ILubyte *Data, ILuint SizeOfData) +{ + ILubyte Temp; + ILuint i; + #ifdef ALTIVEC_GCC + i = 0; + union { + vector unsigned char vec; + vector unsigned int load; + }inversion_vector; + + inversion_vector.load = (vector unsigned int)\ + {0x01000302,0x05040706,0x09080B0A,0x0D0C0F0E}; + while( i <= SizeOfData-16 ) { + vector unsigned char data = vec_ld(i,Data); + vec_perm(data,data,inversion_vector.vec); + vec_st(data,i,Data); + i+=16; + } + SizeOfData -= i; + #endif + for (i = 0; i < SizeOfData; i += 2) { + Temp = Data[i]; + Data[i] = Data[i+1]; + Data[i+1] = Temp; + } + return; +} + +/*----------------------------------------------------------------------------*/ + +// Just an internal convenience function for reading SGI files +ILboolean iNewSgi(iSgiHeader *Head) +{ + if (!ilTexImage(Head->XSize, Head->YSize, Head->Bpc, (ILubyte)Head->ZSize, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + switch (Head->ZSize) + { + case 1: + iCurImage->Format = IL_LUMINANCE; + break; + /*case 2: + iCurImage->Format = IL_LUMINANCE_ALPHA; + break;*/ + case 3: + iCurImage->Format = IL_RGB; + break; + case 4: + iCurImage->Format = IL_RGBA; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + switch (Head->Bpc) + { + case 1: + if (Head->PixMin < 0) + iCurImage->Type = IL_BYTE; + else + iCurImage->Type = IL_UNSIGNED_BYTE; + break; + case 2: + if (Head->PixMin < 0) + iCurImage->Type = IL_SHORT; + else + iCurImage->Type = IL_UNSIGNED_SHORT; + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +//! Writes a SGI file +ILboolean ilSaveSgi(const ILstring FileName) +{ + ILHANDLE SgiFile; + ILuint SgiSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + SgiFile = iopenw(FileName); + if (SgiFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + SgiSize = ilSaveSgiF(SgiFile); + iclosew(SgiFile); + + if (SgiSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Sgi to an already-opened file +ILuint ilSaveSgiF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveSgiInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Sgi to a memory "lump" +ILuint ilSaveSgiL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveSgiInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +ILenum DetermineSgiType(ILenum Type) +{ + if (Type > IL_UNSIGNED_SHORT) { + if (iCurImage->Type == IL_INT) + return IL_SHORT; + return IL_UNSIGNED_SHORT; + } + return Type; +} + +/*----------------------------------------------------------------------------*/ + +// Rle does NOT work yet. + +// Internal function used to save the Sgi. +ILboolean iSaveSgiInternal() +{ + ILuint i, c; + ILboolean Compress; + ILimage *Temp = iCurImage; + ILubyte *TempData; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (iCurImage->Format != IL_LUMINANCE + //while the sgi spec doesn't directly forbid rgb files with 2 + //channels, they are quite uncommon and most apps don't support + //them. so convert lum_a images to rgba before writing. + //&& iCurImage->Format != IL_LUMINANCE_ALPHA + && iCurImage->Format != IL_RGB + && iCurImage->Format != IL_RGBA) { + if (iCurImage->Format == IL_BGRA || iCurImage->Format == IL_LUMINANCE_ALPHA) + Temp = iConvertImage(iCurImage, IL_RGBA, DetermineSgiType(iCurImage->Type)); + else + Temp = iConvertImage(iCurImage, IL_RGB, DetermineSgiType(iCurImage->Type)); + } + else if (iCurImage->Type > IL_UNSIGNED_SHORT) { + Temp = iConvertImage(iCurImage, iCurImage->Format, DetermineSgiType(iCurImage->Type)); + } + + //compression of images with 2 bytes per channel doesn't work yet + Compress = iGetInt(IL_SGI_RLE) && Temp->Bpc == 1; + + if (Temp == NULL) + return IL_FALSE; + + SaveBigUShort(SGI_MAGICNUM); // 'Magic' number + if (Compress) + iputc(1); + else + iputc(0); + + if (Temp->Type == IL_UNSIGNED_BYTE) + iputc(1); + else if (Temp->Type == IL_UNSIGNED_SHORT) + iputc(2); + // Need to error here if not one of the two... + + if (Temp->Format == IL_LUMINANCE || Temp->Format == IL_COLOUR_INDEX) + SaveBigUShort(2); + else + SaveBigUShort(3); + + SaveBigUShort((ILushort)Temp->Width); + SaveBigUShort((ILushort)Temp->Height); + SaveBigUShort((ILushort)Temp->Bpp); + + switch (Temp->Type) + { + case IL_BYTE: + SaveBigInt(SCHAR_MIN); // Minimum pixel value + SaveBigInt(SCHAR_MAX); // Maximum pixel value + break; + case IL_UNSIGNED_BYTE: + SaveBigInt(0); // Minimum pixel value + SaveBigInt(UCHAR_MAX); // Maximum pixel value + break; + case IL_SHORT: + SaveBigInt(SHRT_MIN); // Minimum pixel value + SaveBigInt(SHRT_MAX); // Maximum pixel value + break; + case IL_UNSIGNED_SHORT: + SaveBigInt(0); // Minimum pixel value + SaveBigInt(USHRT_MAX); // Maximum pixel value + break; + } + + SaveBigInt(0); // Dummy value + + if (FName) { + c = ilCharStrLen(FName); + c = c < 79 ? 79 : c; + iwrite(FName, 1, c); + c = 80 - c; + for (i = 0; i < c; i++) { + iputc(0); + } + } + else { + for (i = 0; i < 80; i++) { + iputc(0); + } + } + + SaveBigUInt(0); // Colormap + + // Padding + for (i = 0; i < 101; i++) { + SaveLittleInt(0); + } + + + if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) { + TempData = iGetFlipped(Temp); + if (TempData == NULL) { + if (Temp!= iCurImage) + ilCloseImage(Temp); + return IL_FALSE; + } + } + else { + TempData = Temp->Data; + } + + + if (!Compress) { + for (c = 0; c < Temp->Bpp; c++) { + for (i = c; i < Temp->SizeOfData; i += Temp->Bpp) { + iputc(TempData[i]); // Have to save each colour plane separately. + } + } + } + else { + iSaveRleSgi(TempData, Temp->Width, Temp->Height, Temp->Bpp, Temp->Bps); + } + + + if (TempData != Temp->Data) + ifree(TempData); + if (Temp != iCurImage) + ilCloseImage(Temp); + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +ILboolean iSaveRleSgi(ILubyte *Data, ILuint w, ILuint h, ILuint numChannels, + ILuint bps) +{ + //works only for sgi files with only 1 bpc + + ILuint c, i, y, j; + ILubyte *ScanLine = NULL, *CompLine = NULL; + ILuint *StartTable = NULL, *LenTable = NULL; + ILuint TableOff, DataOff = 0; + + ScanLine = (ILubyte*)ialloc(w); + CompLine = (ILubyte*)ialloc(w * 2 + 1); // Absolute worst case. + StartTable = (ILuint*)ialloc(h * numChannels * sizeof(ILuint)); + LenTable = (ILuint*)icalloc(h * numChannels, sizeof(ILuint)); + if (!ScanLine || !CompLine || !StartTable || !LenTable) { + ifree(ScanLine); + ifree(CompLine); + ifree(StartTable); + ifree(LenTable); + return IL_FALSE; + } + + // These just contain dummy values at this point. + TableOff = itellw(); + iwrite(StartTable, sizeof(ILuint), h * numChannels); + iwrite(LenTable, sizeof(ILuint), h * numChannels); + + DataOff = itellw(); + for (c = 0; c < numChannels; c++) { + for (y = 0; y < h; y++) { + i = y * bps + c; + for (j = 0; j < w; j++, i += numChannels) { + ScanLine[j] = Data[i]; + } + + ilRleCompressLine(ScanLine, w, 1, CompLine, LenTable + h * c + y, IL_SGICOMP); + iwrite(CompLine, 1, *(LenTable + h * c + y)); + } + } + + iseekw(TableOff, IL_SEEK_SET); + + j = h * numChannels; + for (y = 0; y < j; y++) { + StartTable[y] = DataOff; + DataOff += LenTable[y]; +#ifdef __LITTLE_ENDIAN__ + iSwapUInt(&StartTable[y]); + iSwapUInt(&LenTable[y]); +#endif + } + + iwrite(StartTable, sizeof(ILuint), h * numChannels); + iwrite(LenTable, sizeof(ILuint), h * numChannels); + + ifree(ScanLine); + ifree(CompLine); + ifree(StartTable); + ifree(LenTable); + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +#endif//IL_NO_SGI diff --git a/DevIL/src-IL/src/il_size.c b/DevIL/src-IL/src/il_size.c deleted file mode 100755 index 52553173..00000000 --- a/DevIL/src-IL/src/il_size.c +++ /dev/null @@ -1,185 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 01/30/2009 -// -// Filename: src-IL/src/il_size.c -// -// Description: Determines the size of output files for lump writing. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" - - -ILuint iTargaSize(void); - - -ILuint CurPos; // Fake "file" pointer. -ILuint MaxPos; - - -//! Fake seek function -ILint ILAPIENTRY iSizeSeek(ILint Offset, ILuint Mode) -{ - switch (Mode) - { - case IL_SEEK_SET: - CurPos = Offset; - if (CurPos > MaxPos) - MaxPos = CurPos; - break; - - case IL_SEEK_CUR: - CurPos = CurPos + Offset; - break; - - case IL_SEEK_END: - CurPos = MaxPos + Offset; // Offset should be negative in this case. - break; - - default: - ilSetError(IL_INTERNAL_ERROR); // Should never happen! - return -1; // Error code - } - - if (CurPos > MaxPos) - MaxPos = CurPos; - - return 0; // Code for success -} - -ILuint ILAPIENTRY iSizeTell(void) -{ - return CurPos; -} - -ILint ILAPIENTRY iSizePutc(ILubyte Char) -{ - CurPos++; - if (CurPos > MaxPos) - MaxPos = CurPos; - return Char; -} - -ILint ILAPIENTRY iSizeWrite(const void *Buffer, ILuint Size, ILuint Number) -{ - CurPos += Size * Number; - if (CurPos > MaxPos) - MaxPos = CurPos; - return Number; -} - - -//@TODO: Do computations for uncompressed formats without going through the -// whole writing process. - -//! Returns the size of the memory buffer needed to save the current image into this Type. -// A return value of 0 is an error. -ILuint ilDetermineSize(ILenum Type) -{ - MaxPos = CurPos = 0; - iSetOutputFake(); // Sets iputc, iwrite, etc. to functions above. - - switch (Type) - { - #ifndef IL_NO_BMP - case IL_BMP: - ilSaveBmpL(NULL, 0); - break; - #endif//IL_NO_BMP - - #ifndef IL_NO_DDS - case IL_DDS: - ilSaveDdsL(NULL, 0); - break; - #endif//IL_NO_DDS - - #ifndef IL_NO_EXR - case IL_EXR: - ilSaveExrL(NULL, 0); - break; - #endif//IL_NO_EXR - - #ifndef IL_NO_HDR - case IL_HDR: - ilSaveHdrL(NULL, 0); - break; - #endif//IL_NO_HDR - - #ifndef IL_NO_JP2 - case IL_JP2: - ilSaveJp2L(NULL, 0); - break; - #endif//IL_NO_JP2 - - #ifndef IL_NO_JPG - case IL_JPG: - ilSaveJpegL(NULL, 0); - break; - #endif//IL_NO_JPG - - #ifndef IL_NO_PCX - case IL_PCX: - ilSavePcxL(NULL, 0); - break; - #endif//IL_NO_PCX - - #ifndef IL_NO_PNG - case IL_PNG: - ilSavePngL(NULL, 0); - break; - #endif//IL_NO_PNG - - #ifndef IL_NO_PNM - case IL_PNM: - ilSavePnmL(NULL, 0); - break; - #endif//IL_NO_PNM - - #ifndef IL_NO_PSD - case IL_PSD: - ilSavePsdL(NULL, 0); - break; - #endif//IL_NO_PSD - - #ifndef IL_NO_RAW - case IL_RAW: - ilSaveRawL(NULL, 0); - break; - #endif//IL_NO_RAW - - #ifndef IL_NO_SGI - case IL_SGI: - ilSaveSgiL(NULL, 0); - break; - #endif//IL_NO_SGI - - #ifndef IL_NO_TGA - case IL_TGA: - //ilSaveTargaL(NULL, 0); - return iTargaSize(); - break; - #endif//IL_NO_TGA - - #ifndef IL_NO_TIF - case IL_TIF: - ilSaveTiffL(NULL, 0); - break; - #endif//IL_NO_TIF - - #ifndef IL_NO_WBMP - case IL_WBMP: - ilSaveWbmpL(NULL, 0); - break; - #endif//IL_NO_WBMP - - default: - // 0 is an error for this. - ilSetError(IL_INVALID_ENUM); - return 0; - } - - return MaxPos; -} diff --git a/DevIL/src-IL/src/il_size.cpp b/DevIL/src-IL/src/il_size.cpp new file mode 100755 index 00000000..52553173 --- /dev/null +++ b/DevIL/src-IL/src/il_size.cpp @@ -0,0 +1,185 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 01/30/2009 +// +// Filename: src-IL/src/il_size.c +// +// Description: Determines the size of output files for lump writing. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" + + +ILuint iTargaSize(void); + + +ILuint CurPos; // Fake "file" pointer. +ILuint MaxPos; + + +//! Fake seek function +ILint ILAPIENTRY iSizeSeek(ILint Offset, ILuint Mode) +{ + switch (Mode) + { + case IL_SEEK_SET: + CurPos = Offset; + if (CurPos > MaxPos) + MaxPos = CurPos; + break; + + case IL_SEEK_CUR: + CurPos = CurPos + Offset; + break; + + case IL_SEEK_END: + CurPos = MaxPos + Offset; // Offset should be negative in this case. + break; + + default: + ilSetError(IL_INTERNAL_ERROR); // Should never happen! + return -1; // Error code + } + + if (CurPos > MaxPos) + MaxPos = CurPos; + + return 0; // Code for success +} + +ILuint ILAPIENTRY iSizeTell(void) +{ + return CurPos; +} + +ILint ILAPIENTRY iSizePutc(ILubyte Char) +{ + CurPos++; + if (CurPos > MaxPos) + MaxPos = CurPos; + return Char; +} + +ILint ILAPIENTRY iSizeWrite(const void *Buffer, ILuint Size, ILuint Number) +{ + CurPos += Size * Number; + if (CurPos > MaxPos) + MaxPos = CurPos; + return Number; +} + + +//@TODO: Do computations for uncompressed formats without going through the +// whole writing process. + +//! Returns the size of the memory buffer needed to save the current image into this Type. +// A return value of 0 is an error. +ILuint ilDetermineSize(ILenum Type) +{ + MaxPos = CurPos = 0; + iSetOutputFake(); // Sets iputc, iwrite, etc. to functions above. + + switch (Type) + { + #ifndef IL_NO_BMP + case IL_BMP: + ilSaveBmpL(NULL, 0); + break; + #endif//IL_NO_BMP + + #ifndef IL_NO_DDS + case IL_DDS: + ilSaveDdsL(NULL, 0); + break; + #endif//IL_NO_DDS + + #ifndef IL_NO_EXR + case IL_EXR: + ilSaveExrL(NULL, 0); + break; + #endif//IL_NO_EXR + + #ifndef IL_NO_HDR + case IL_HDR: + ilSaveHdrL(NULL, 0); + break; + #endif//IL_NO_HDR + + #ifndef IL_NO_JP2 + case IL_JP2: + ilSaveJp2L(NULL, 0); + break; + #endif//IL_NO_JP2 + + #ifndef IL_NO_JPG + case IL_JPG: + ilSaveJpegL(NULL, 0); + break; + #endif//IL_NO_JPG + + #ifndef IL_NO_PCX + case IL_PCX: + ilSavePcxL(NULL, 0); + break; + #endif//IL_NO_PCX + + #ifndef IL_NO_PNG + case IL_PNG: + ilSavePngL(NULL, 0); + break; + #endif//IL_NO_PNG + + #ifndef IL_NO_PNM + case IL_PNM: + ilSavePnmL(NULL, 0); + break; + #endif//IL_NO_PNM + + #ifndef IL_NO_PSD + case IL_PSD: + ilSavePsdL(NULL, 0); + break; + #endif//IL_NO_PSD + + #ifndef IL_NO_RAW + case IL_RAW: + ilSaveRawL(NULL, 0); + break; + #endif//IL_NO_RAW + + #ifndef IL_NO_SGI + case IL_SGI: + ilSaveSgiL(NULL, 0); + break; + #endif//IL_NO_SGI + + #ifndef IL_NO_TGA + case IL_TGA: + //ilSaveTargaL(NULL, 0); + return iTargaSize(); + break; + #endif//IL_NO_TGA + + #ifndef IL_NO_TIF + case IL_TIF: + ilSaveTiffL(NULL, 0); + break; + #endif//IL_NO_TIF + + #ifndef IL_NO_WBMP + case IL_WBMP: + ilSaveWbmpL(NULL, 0); + break; + #endif//IL_NO_WBMP + + default: + // 0 is an error for this. + ilSetError(IL_INVALID_ENUM); + return 0; + } + + return MaxPos; +} diff --git a/DevIL/src-IL/src/il_stack.c b/DevIL/src-IL/src/il_stack.c deleted file mode 100644 index 3d36c81e..00000000 --- a/DevIL/src-IL/src/il_stack.c +++ /dev/null @@ -1,669 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2008 by Denton Woods -// Last modified: 12/17/2008 -// -// Filename: src-IL/src/il_stack.c -// -// Description: The main image stack -// -//----------------------------------------------------------------------------- - -// Credit goes to John Villar (johnny@reliaschev.com) for making the suggestion -// of not letting the user use ILimage structs but instead binding images -// like OpenGL. - -#include "il_internal.h" -#include "il_stack.h" - -//! Creates Num images and puts their index in Images - similar to glGenTextures(). -void ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images) -{ - ILsizei Index = 0; - iFree *TempFree = FreeNames; - - if (Num < 1 || Images == NULL) { - ilSetError(IL_INVALID_VALUE); - return; - } - - // No images have been generated yet, so create the image stack. - if (ImageStack == NULL) - if (!iEnlargeStack()) - return; - - do { - if (FreeNames != NULL) { // If any have been deleted, then reuse their image names. - TempFree = (iFree*)FreeNames->Next; - Images[Index] = FreeNames->Name; - ImageStack[FreeNames->Name] = ilNewImage(1, 1, 1, 1, 1); - ifree(FreeNames); - FreeNames = TempFree; - } else { - if (LastUsed >= StackSize) - if (!iEnlargeStack()) - return; - Images[Index] = LastUsed; - // Must be all 1's instead of 0's, because some functions would divide by 0. - ImageStack[LastUsed] = ilNewImage(1, 1, 1, 1, 1); - LastUsed++; - } - } while (++Index < Num); - - return; -} - -ILuint ILAPIENTRY ilGenImage() -{ - ILuint i; - ilGenImages(1,&i); - return i; -} - -//! Makes Image the current active image - similar to glBindTexture(). -void ILAPIENTRY ilBindImage(ILuint Image) -{ - if (ImageStack == NULL || StackSize == 0) { - if (!iEnlargeStack()) { - return; - } - } - - // If the user requests a high image name. - while (Image >= StackSize) { - if (!iEnlargeStack()) { - return; - } - } - - if (ImageStack[Image] == NULL) { - ImageStack[Image] = ilNewImage(1, 1, 1, 1, 1); - if (Image >= LastUsed) // >= ? - LastUsed = Image + 1; - } - - iCurImage = ImageStack[Image]; - CurName = Image; - - ParentImage = IL_TRUE; - - return; -} - - -//! Deletes Num images from the image stack - similar to glDeleteTextures(). -void ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images) -{ - iFree *Temp = FreeNames; - ILuint Index = 0; - - if (Num < 1) { - //ilSetError(IL_INVALID_VALUE); - return; - } - if (StackSize == 0) - return; - - do { - if (Images[Index] > 0 && Images[Index] < LastUsed) { // <= ? - /*if (FreeNames != NULL) { // Terribly inefficient - Temp = FreeNames; - do { - if (Temp->Name == Images[Index]) { - continue; // Sufficient? - } - } while ((Temp = Temp->Next)); - }*/ - - // Already has been deleted or was never used. - if (ImageStack[Images[Index]] == NULL) - continue; - - // Find out if current image - if so, set to default image zero. - if (Images[Index] == CurName || Images[Index] == 0) { - iCurImage = ImageStack[0]; - CurName = 0; - } - - // Should *NOT* be NULL here! - ilCloseImage(ImageStack[Images[Index]]); - ImageStack[Images[Index]] = NULL; - - // Add to head of list - works for empty and non-empty lists - Temp = (iFree*)ialloc(sizeof(iFree)); - if (!Temp) { - return; - } - Temp->Name = Images[Index]; - Temp->Next = FreeNames; - FreeNames = Temp; - } - /*else { // Shouldn't set an error...just continue onward. - ilSetError(IL_ILLEGAL_OPERATION); - }*/ - } while (++Index < (ILuint)Num); -} - - -void ILAPIENTRY ilDeleteImage(const ILuint Num) { - ilDeleteImages(1,&Num); -} - -//! Checks if Image is a valid ilGenImages-generated image (like glIsTexture()). -ILboolean ILAPIENTRY ilIsImage(ILuint Image) -{ - //iFree *Temp = FreeNames; - - if (ImageStack == NULL) - return IL_FALSE; - if (Image >= LastUsed || Image == 0) - return IL_FALSE; - - /*do { - if (Temp->Name == Image) - return IL_FALSE; - } while ((Temp = Temp->Next));*/ - - if (ImageStack[Image] == NULL) // Easier check. - return IL_FALSE; - - return IL_TRUE; -} - - -//! Closes Image and frees all memory associated with it. -ILAPI void ILAPIENTRY ilCloseImage(ILimage *Image) -{ - if (Image == NULL) - return; - - if (Image->Data != NULL) { - ifree(Image->Data); - Image->Data = NULL; - } - - if (Image->Pal.Palette != NULL && Image->Pal.PalSize > 0 && Image->Pal.PalType != IL_PAL_NONE) { - ifree(Image->Pal.Palette); - Image->Pal.Palette = NULL; - } - - if (Image->Next != NULL) { - ilCloseImage(Image->Next); - Image->Next = NULL; - } - - if (Image->Faces != NULL) { - ilCloseImage(Image->Faces); - Image->Mipmaps = NULL; - } - - if (Image->Mipmaps != NULL) { - ilCloseImage(Image->Mipmaps); - Image->Mipmaps = NULL; - } - - if (Image->Layers != NULL) { - ilCloseImage(Image->Layers); - Image->Layers = NULL; - } - - if (Image->AnimList != NULL && Image->AnimSize != 0) { - ifree(Image->AnimList); - Image->AnimList = NULL; - } - - if (Image->Profile != NULL && Image->ProfileSize != 0) { - ifree(Image->Profile); - Image->Profile = NULL; - Image->ProfileSize = 0; - } - - if (Image->DxtcData != NULL && Image->DxtcFormat != IL_DXT_NO_COMP) { - ifree(Image->DxtcData); - Image->DxtcData = NULL; - Image->DxtcFormat = IL_DXT_NO_COMP; - Image->DxtcSize = 0; - } - - ifree(Image); - Image = NULL; - - return; -} - - -ILAPI ILboolean ILAPIENTRY ilIsValidPal(ILpal *Palette) -{ - if (Palette == NULL) - return IL_FALSE; - if (Palette->PalSize == 0 || Palette->Palette == NULL) - return IL_FALSE; - switch (Palette->PalType) - { - case IL_PAL_RGB24: - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - case IL_PAL_BGR24: - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - return IL_TRUE; - } - return IL_FALSE; -} - - -//! Closes Palette and frees all memory associated with it. -ILAPI void ILAPIENTRY ilClosePal(ILpal *Palette) -{ - if (Palette == NULL) - return; - if (!ilIsValidPal(Palette)) - return; - ifree(Palette->Palette); - ifree(Palette); - return; -} - - -ILimage *iGetBaseImage() -{ - return ImageStack[ilGetCurName()]; -} - - -//! Sets the current mipmap level -ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number) -{ - ILuint Current; - ILimage *iTempImage; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (Number == 0) { - return IL_TRUE; - } - - iTempImage = iCurImage; - iCurImage = iCurImage->Mipmaps; - if (iCurImage == NULL) { - iCurImage = iTempImage; - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - for (Current = 1; Current < Number; Current++) { - iCurImage = iCurImage->Mipmaps; - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - iCurImage = iTempImage; - return IL_FALSE; - } - } - - ParentImage = IL_FALSE; - - return IL_TRUE; -} - - -//! Used for setting the current image if it is an animation. -ILboolean ILAPIENTRY ilActiveImage(ILuint Number) -{ - ILuint Current; - ILimage *iTempImage; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (Number == 0) { - return IL_TRUE; - } - - iTempImage = iCurImage; - iCurImage = iCurImage->Next; - if (iCurImage == NULL) { - iCurImage = iTempImage; - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - Number--; // Skip 0 (parent image) - for (Current = 0; Current < Number; Current++) { - iCurImage = iCurImage->Next; - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - iCurImage = iTempImage; - return IL_FALSE; - } - } - - ParentImage = IL_FALSE; - - return IL_TRUE; -} - - -//! Used for setting the current face if it is a cubemap. -ILboolean ILAPIENTRY ilActiveFace(ILuint Number) -{ - ILuint Current; - ILimage *iTempImage; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (Number == 0) { - return IL_TRUE; - } - - iTempImage = iCurImage; - iCurImage = iCurImage->Faces; - if (iCurImage == NULL) { - iCurImage = iTempImage; - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - //Number--; // Skip 0 (parent image) - for (Current = 1; Current < Number; Current++) { - iCurImage = iCurImage->Faces; - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - iCurImage = iTempImage; - return IL_FALSE; - } - } - - ParentImage = IL_FALSE; - - return IL_TRUE; -} - - - -//! Used for setting the current layer if layers exist. -ILboolean ILAPIENTRY ilActiveLayer(ILuint Number) -{ - ILuint Current; - ILimage *iTempImage; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (Number == 0) { - return IL_TRUE; - } - - iTempImage = iCurImage; - iCurImage = iCurImage->Layers; - if (iCurImage == NULL) { - iCurImage = iTempImage; - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - //Number--; // Skip 0 (parent image) - for (Current = 1; Current < Number; Current++) { - iCurImage = iCurImage->Layers; - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - iCurImage = iTempImage; - return IL_FALSE; - } - } - - ParentImage = IL_FALSE; - - return IL_TRUE; -} - - -ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num) -{ - ILimage *SubImage; - ILuint Count ; // Create one before we go in the loop. - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return 0; - } - if (Num == 0) { - return 0; - } - - switch (Type) - { - case IL_SUB_NEXT: - if (iCurImage->Next) - ilCloseImage(iCurImage->Next); - iCurImage->Next = ilNewImage(1, 1, 1, 1, 1); - SubImage = iCurImage->Next; - break; - - case IL_SUB_MIPMAP: - if (iCurImage->Mipmaps) - ilCloseImage(iCurImage->Mipmaps); - iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1); - SubImage = iCurImage->Mipmaps; - break; - - case IL_SUB_LAYER: - if (iCurImage->Layers) - ilCloseImage(iCurImage->Layers); - iCurImage->Layers = ilNewImage(1, 1, 1, 1, 1); - SubImage = iCurImage->Layers; - break; - - default: - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; - } - - if (SubImage == NULL) { - return 0; - } - - for (Count = 1; Count < Num; Count++) { - SubImage->Next = ilNewImage(1, 1, 1, 1, 1); - SubImage = SubImage->Next; - if (SubImage == NULL) - return Count; - } - - return Count; -} - - -// Returns the current index. -ILAPI ILuint ILAPIENTRY ilGetCurName() -{ - if (iCurImage == NULL || ImageStack == NULL || StackSize == 0) - return 0; - return CurName; -} - - -// Returns the current image. -ILAPI ILimage* ILAPIENTRY ilGetCurImage() -{ - return iCurImage; -} - - -// To be only used when the original image is going to be set back almost immediately. -ILAPI void ILAPIENTRY ilSetCurImage(ILimage *Image) -{ - iCurImage = Image; - return; -} - - -// Completely replaces the current image and the version in the image stack. -ILAPI void ILAPIENTRY ilReplaceCurImage(ILimage *Image) -{ - if (iCurImage) { - ilActiveImage(0); - ilCloseImage(iCurImage); - } - ImageStack[ilGetCurName()] = Image; - iCurImage = Image; - ParentImage = IL_TRUE; - return; -} - - -// Like realloc but sets new memory to 0. -void* ILAPIENTRY ilRecalloc(void *Ptr, ILuint OldSize, ILuint NewSize) -{ - void *Temp = ialloc(NewSize); - ILuint CopySize = (OldSize < NewSize) ? OldSize : NewSize; - - if (Temp != NULL) { - if (Ptr != NULL) { - memcpy(Temp, Ptr, CopySize); - ifree(Ptr); - } - - Ptr = Temp; - - if (OldSize < NewSize) - imemclear((ILubyte*)Temp + OldSize, NewSize - OldSize); - } - - return Temp; -} - - -// Internal function to enlarge the image stack by I_STACK_INCREMENT members. -ILboolean iEnlargeStack() -{ - // 02-05-2001: Moved from ilGenImages(). - // Puts the cleanup function on the exit handler once. - if (!OnExit) { - #ifdef _MEM_DEBUG - AddToAtexit(); // So iFreeMem doesn't get called after unfreed information. - #endif//_MEM_DEBUG -#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB)) - atexit((void*)ilShutDown); -#endif - OnExit = IL_TRUE; - } - - if (!(ImageStack = (ILimage**)ilRecalloc(ImageStack, StackSize * sizeof(ILimage*), (StackSize + I_STACK_INCREMENT) * sizeof(ILimage*)))) { - return IL_FALSE; - } - StackSize += I_STACK_INCREMENT; - return IL_TRUE; -} - - -static ILboolean IsInit = IL_FALSE; - -// ONLY call at startup. -void ILAPIENTRY ilInit() -{ - // if it is already initialized skip initialization - if (IsInit == IL_TRUE ) - return; - - //ilSetMemory(NULL, NULL); Now useless 3/4/2006 (due to modification in il_alloc.c) - ilSetError(IL_NO_ERROR); - ilDefaultStates(); // Set states to their defaults. - // Sets default file-reading callbacks. - ilResetRead(); - ilResetWrite(); -#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB)) - atexit((void*)ilRemoveRegistered); -#endif - //_WIN32_WCE - //ilShutDown(); - iSetImage0(); // Beware! Clears all existing textures! - iBindImageTemp(); // Go ahead and create the temporary image. - IsInit = IL_TRUE; - return; -} - - -// Frees any extra memory in the stack. -// - Called on exit -void ILAPIENTRY ilShutDown() -{ - // if it is not initialized do not shutdown - iFree* TempFree = (iFree*)FreeNames; - ILuint i; - - if (!IsInit) - return; - - if (!IsInit) { // Prevent from being called when not initialized. - ilSetError(IL_ILLEGAL_OPERATION); - return; - } - - while (TempFree != NULL) { - FreeNames = (iFree*)TempFree->Next; - ifree(TempFree); - TempFree = FreeNames; - } - - //for (i = 0; i < LastUsed; i++) { - for (i = 0; i < StackSize; i++) { - if (ImageStack[i] != NULL) - ilCloseImage(ImageStack[i]); - } - - if (ImageStack) - ifree(ImageStack); - ImageStack = NULL; - LastUsed = 0; - StackSize = 0; - IsInit = IL_FALSE; - return; -} - - -// Initializes the image stack's first entry (default image) -- ONLY CALL ONCE! -void iSetImage0() -{ - if (ImageStack == NULL) - if (!iEnlargeStack()) - return; - - LastUsed = 1; - CurName = 0; - ParentImage = IL_TRUE; - if (!ImageStack[0]) - ImageStack[0] = ilNewImage(1, 1, 1, 1, 1); - iCurImage = ImageStack[0]; - ilDefaultImage(); - - return; -} - - -ILAPI void ILAPIENTRY iBindImageTemp() -{ - if (ImageStack == NULL || StackSize <= 1) - if (!iEnlargeStack()) - return; - - if (LastUsed < 2) - LastUsed = 2; - CurName = 1; - ParentImage = IL_TRUE; - if (!ImageStack[1]) - ImageStack[1] = ilNewImage(1, 1, 1, 1, 1); - iCurImage = ImageStack[1]; - - return; -} diff --git a/DevIL/src-IL/src/il_stack.cpp b/DevIL/src-IL/src/il_stack.cpp new file mode 100644 index 00000000..3d36c81e --- /dev/null +++ b/DevIL/src-IL/src/il_stack.cpp @@ -0,0 +1,669 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2008 by Denton Woods +// Last modified: 12/17/2008 +// +// Filename: src-IL/src/il_stack.c +// +// Description: The main image stack +// +//----------------------------------------------------------------------------- + +// Credit goes to John Villar (johnny@reliaschev.com) for making the suggestion +// of not letting the user use ILimage structs but instead binding images +// like OpenGL. + +#include "il_internal.h" +#include "il_stack.h" + +//! Creates Num images and puts their index in Images - similar to glGenTextures(). +void ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images) +{ + ILsizei Index = 0; + iFree *TempFree = FreeNames; + + if (Num < 1 || Images == NULL) { + ilSetError(IL_INVALID_VALUE); + return; + } + + // No images have been generated yet, so create the image stack. + if (ImageStack == NULL) + if (!iEnlargeStack()) + return; + + do { + if (FreeNames != NULL) { // If any have been deleted, then reuse their image names. + TempFree = (iFree*)FreeNames->Next; + Images[Index] = FreeNames->Name; + ImageStack[FreeNames->Name] = ilNewImage(1, 1, 1, 1, 1); + ifree(FreeNames); + FreeNames = TempFree; + } else { + if (LastUsed >= StackSize) + if (!iEnlargeStack()) + return; + Images[Index] = LastUsed; + // Must be all 1's instead of 0's, because some functions would divide by 0. + ImageStack[LastUsed] = ilNewImage(1, 1, 1, 1, 1); + LastUsed++; + } + } while (++Index < Num); + + return; +} + +ILuint ILAPIENTRY ilGenImage() +{ + ILuint i; + ilGenImages(1,&i); + return i; +} + +//! Makes Image the current active image - similar to glBindTexture(). +void ILAPIENTRY ilBindImage(ILuint Image) +{ + if (ImageStack == NULL || StackSize == 0) { + if (!iEnlargeStack()) { + return; + } + } + + // If the user requests a high image name. + while (Image >= StackSize) { + if (!iEnlargeStack()) { + return; + } + } + + if (ImageStack[Image] == NULL) { + ImageStack[Image] = ilNewImage(1, 1, 1, 1, 1); + if (Image >= LastUsed) // >= ? + LastUsed = Image + 1; + } + + iCurImage = ImageStack[Image]; + CurName = Image; + + ParentImage = IL_TRUE; + + return; +} + + +//! Deletes Num images from the image stack - similar to glDeleteTextures(). +void ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images) +{ + iFree *Temp = FreeNames; + ILuint Index = 0; + + if (Num < 1) { + //ilSetError(IL_INVALID_VALUE); + return; + } + if (StackSize == 0) + return; + + do { + if (Images[Index] > 0 && Images[Index] < LastUsed) { // <= ? + /*if (FreeNames != NULL) { // Terribly inefficient + Temp = FreeNames; + do { + if (Temp->Name == Images[Index]) { + continue; // Sufficient? + } + } while ((Temp = Temp->Next)); + }*/ + + // Already has been deleted or was never used. + if (ImageStack[Images[Index]] == NULL) + continue; + + // Find out if current image - if so, set to default image zero. + if (Images[Index] == CurName || Images[Index] == 0) { + iCurImage = ImageStack[0]; + CurName = 0; + } + + // Should *NOT* be NULL here! + ilCloseImage(ImageStack[Images[Index]]); + ImageStack[Images[Index]] = NULL; + + // Add to head of list - works for empty and non-empty lists + Temp = (iFree*)ialloc(sizeof(iFree)); + if (!Temp) { + return; + } + Temp->Name = Images[Index]; + Temp->Next = FreeNames; + FreeNames = Temp; + } + /*else { // Shouldn't set an error...just continue onward. + ilSetError(IL_ILLEGAL_OPERATION); + }*/ + } while (++Index < (ILuint)Num); +} + + +void ILAPIENTRY ilDeleteImage(const ILuint Num) { + ilDeleteImages(1,&Num); +} + +//! Checks if Image is a valid ilGenImages-generated image (like glIsTexture()). +ILboolean ILAPIENTRY ilIsImage(ILuint Image) +{ + //iFree *Temp = FreeNames; + + if (ImageStack == NULL) + return IL_FALSE; + if (Image >= LastUsed || Image == 0) + return IL_FALSE; + + /*do { + if (Temp->Name == Image) + return IL_FALSE; + } while ((Temp = Temp->Next));*/ + + if (ImageStack[Image] == NULL) // Easier check. + return IL_FALSE; + + return IL_TRUE; +} + + +//! Closes Image and frees all memory associated with it. +ILAPI void ILAPIENTRY ilCloseImage(ILimage *Image) +{ + if (Image == NULL) + return; + + if (Image->Data != NULL) { + ifree(Image->Data); + Image->Data = NULL; + } + + if (Image->Pal.Palette != NULL && Image->Pal.PalSize > 0 && Image->Pal.PalType != IL_PAL_NONE) { + ifree(Image->Pal.Palette); + Image->Pal.Palette = NULL; + } + + if (Image->Next != NULL) { + ilCloseImage(Image->Next); + Image->Next = NULL; + } + + if (Image->Faces != NULL) { + ilCloseImage(Image->Faces); + Image->Mipmaps = NULL; + } + + if (Image->Mipmaps != NULL) { + ilCloseImage(Image->Mipmaps); + Image->Mipmaps = NULL; + } + + if (Image->Layers != NULL) { + ilCloseImage(Image->Layers); + Image->Layers = NULL; + } + + if (Image->AnimList != NULL && Image->AnimSize != 0) { + ifree(Image->AnimList); + Image->AnimList = NULL; + } + + if (Image->Profile != NULL && Image->ProfileSize != 0) { + ifree(Image->Profile); + Image->Profile = NULL; + Image->ProfileSize = 0; + } + + if (Image->DxtcData != NULL && Image->DxtcFormat != IL_DXT_NO_COMP) { + ifree(Image->DxtcData); + Image->DxtcData = NULL; + Image->DxtcFormat = IL_DXT_NO_COMP; + Image->DxtcSize = 0; + } + + ifree(Image); + Image = NULL; + + return; +} + + +ILAPI ILboolean ILAPIENTRY ilIsValidPal(ILpal *Palette) +{ + if (Palette == NULL) + return IL_FALSE; + if (Palette->PalSize == 0 || Palette->Palette == NULL) + return IL_FALSE; + switch (Palette->PalType) + { + case IL_PAL_RGB24: + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + case IL_PAL_BGR24: + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + return IL_TRUE; + } + return IL_FALSE; +} + + +//! Closes Palette and frees all memory associated with it. +ILAPI void ILAPIENTRY ilClosePal(ILpal *Palette) +{ + if (Palette == NULL) + return; + if (!ilIsValidPal(Palette)) + return; + ifree(Palette->Palette); + ifree(Palette); + return; +} + + +ILimage *iGetBaseImage() +{ + return ImageStack[ilGetCurName()]; +} + + +//! Sets the current mipmap level +ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number) +{ + ILuint Current; + ILimage *iTempImage; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (Number == 0) { + return IL_TRUE; + } + + iTempImage = iCurImage; + iCurImage = iCurImage->Mipmaps; + if (iCurImage == NULL) { + iCurImage = iTempImage; + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + for (Current = 1; Current < Number; Current++) { + iCurImage = iCurImage->Mipmaps; + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + iCurImage = iTempImage; + return IL_FALSE; + } + } + + ParentImage = IL_FALSE; + + return IL_TRUE; +} + + +//! Used for setting the current image if it is an animation. +ILboolean ILAPIENTRY ilActiveImage(ILuint Number) +{ + ILuint Current; + ILimage *iTempImage; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (Number == 0) { + return IL_TRUE; + } + + iTempImage = iCurImage; + iCurImage = iCurImage->Next; + if (iCurImage == NULL) { + iCurImage = iTempImage; + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + Number--; // Skip 0 (parent image) + for (Current = 0; Current < Number; Current++) { + iCurImage = iCurImage->Next; + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + iCurImage = iTempImage; + return IL_FALSE; + } + } + + ParentImage = IL_FALSE; + + return IL_TRUE; +} + + +//! Used for setting the current face if it is a cubemap. +ILboolean ILAPIENTRY ilActiveFace(ILuint Number) +{ + ILuint Current; + ILimage *iTempImage; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (Number == 0) { + return IL_TRUE; + } + + iTempImage = iCurImage; + iCurImage = iCurImage->Faces; + if (iCurImage == NULL) { + iCurImage = iTempImage; + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + //Number--; // Skip 0 (parent image) + for (Current = 1; Current < Number; Current++) { + iCurImage = iCurImage->Faces; + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + iCurImage = iTempImage; + return IL_FALSE; + } + } + + ParentImage = IL_FALSE; + + return IL_TRUE; +} + + + +//! Used for setting the current layer if layers exist. +ILboolean ILAPIENTRY ilActiveLayer(ILuint Number) +{ + ILuint Current; + ILimage *iTempImage; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (Number == 0) { + return IL_TRUE; + } + + iTempImage = iCurImage; + iCurImage = iCurImage->Layers; + if (iCurImage == NULL) { + iCurImage = iTempImage; + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + //Number--; // Skip 0 (parent image) + for (Current = 1; Current < Number; Current++) { + iCurImage = iCurImage->Layers; + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + iCurImage = iTempImage; + return IL_FALSE; + } + } + + ParentImage = IL_FALSE; + + return IL_TRUE; +} + + +ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num) +{ + ILimage *SubImage; + ILuint Count ; // Create one before we go in the loop. + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return 0; + } + if (Num == 0) { + return 0; + } + + switch (Type) + { + case IL_SUB_NEXT: + if (iCurImage->Next) + ilCloseImage(iCurImage->Next); + iCurImage->Next = ilNewImage(1, 1, 1, 1, 1); + SubImage = iCurImage->Next; + break; + + case IL_SUB_MIPMAP: + if (iCurImage->Mipmaps) + ilCloseImage(iCurImage->Mipmaps); + iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1); + SubImage = iCurImage->Mipmaps; + break; + + case IL_SUB_LAYER: + if (iCurImage->Layers) + ilCloseImage(iCurImage->Layers); + iCurImage->Layers = ilNewImage(1, 1, 1, 1, 1); + SubImage = iCurImage->Layers; + break; + + default: + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; + } + + if (SubImage == NULL) { + return 0; + } + + for (Count = 1; Count < Num; Count++) { + SubImage->Next = ilNewImage(1, 1, 1, 1, 1); + SubImage = SubImage->Next; + if (SubImage == NULL) + return Count; + } + + return Count; +} + + +// Returns the current index. +ILAPI ILuint ILAPIENTRY ilGetCurName() +{ + if (iCurImage == NULL || ImageStack == NULL || StackSize == 0) + return 0; + return CurName; +} + + +// Returns the current image. +ILAPI ILimage* ILAPIENTRY ilGetCurImage() +{ + return iCurImage; +} + + +// To be only used when the original image is going to be set back almost immediately. +ILAPI void ILAPIENTRY ilSetCurImage(ILimage *Image) +{ + iCurImage = Image; + return; +} + + +// Completely replaces the current image and the version in the image stack. +ILAPI void ILAPIENTRY ilReplaceCurImage(ILimage *Image) +{ + if (iCurImage) { + ilActiveImage(0); + ilCloseImage(iCurImage); + } + ImageStack[ilGetCurName()] = Image; + iCurImage = Image; + ParentImage = IL_TRUE; + return; +} + + +// Like realloc but sets new memory to 0. +void* ILAPIENTRY ilRecalloc(void *Ptr, ILuint OldSize, ILuint NewSize) +{ + void *Temp = ialloc(NewSize); + ILuint CopySize = (OldSize < NewSize) ? OldSize : NewSize; + + if (Temp != NULL) { + if (Ptr != NULL) { + memcpy(Temp, Ptr, CopySize); + ifree(Ptr); + } + + Ptr = Temp; + + if (OldSize < NewSize) + imemclear((ILubyte*)Temp + OldSize, NewSize - OldSize); + } + + return Temp; +} + + +// Internal function to enlarge the image stack by I_STACK_INCREMENT members. +ILboolean iEnlargeStack() +{ + // 02-05-2001: Moved from ilGenImages(). + // Puts the cleanup function on the exit handler once. + if (!OnExit) { + #ifdef _MEM_DEBUG + AddToAtexit(); // So iFreeMem doesn't get called after unfreed information. + #endif//_MEM_DEBUG +#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB)) + atexit((void*)ilShutDown); +#endif + OnExit = IL_TRUE; + } + + if (!(ImageStack = (ILimage**)ilRecalloc(ImageStack, StackSize * sizeof(ILimage*), (StackSize + I_STACK_INCREMENT) * sizeof(ILimage*)))) { + return IL_FALSE; + } + StackSize += I_STACK_INCREMENT; + return IL_TRUE; +} + + +static ILboolean IsInit = IL_FALSE; + +// ONLY call at startup. +void ILAPIENTRY ilInit() +{ + // if it is already initialized skip initialization + if (IsInit == IL_TRUE ) + return; + + //ilSetMemory(NULL, NULL); Now useless 3/4/2006 (due to modification in il_alloc.c) + ilSetError(IL_NO_ERROR); + ilDefaultStates(); // Set states to their defaults. + // Sets default file-reading callbacks. + ilResetRead(); + ilResetWrite(); +#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB)) + atexit((void*)ilRemoveRegistered); +#endif + //_WIN32_WCE + //ilShutDown(); + iSetImage0(); // Beware! Clears all existing textures! + iBindImageTemp(); // Go ahead and create the temporary image. + IsInit = IL_TRUE; + return; +} + + +// Frees any extra memory in the stack. +// - Called on exit +void ILAPIENTRY ilShutDown() +{ + // if it is not initialized do not shutdown + iFree* TempFree = (iFree*)FreeNames; + ILuint i; + + if (!IsInit) + return; + + if (!IsInit) { // Prevent from being called when not initialized. + ilSetError(IL_ILLEGAL_OPERATION); + return; + } + + while (TempFree != NULL) { + FreeNames = (iFree*)TempFree->Next; + ifree(TempFree); + TempFree = FreeNames; + } + + //for (i = 0; i < LastUsed; i++) { + for (i = 0; i < StackSize; i++) { + if (ImageStack[i] != NULL) + ilCloseImage(ImageStack[i]); + } + + if (ImageStack) + ifree(ImageStack); + ImageStack = NULL; + LastUsed = 0; + StackSize = 0; + IsInit = IL_FALSE; + return; +} + + +// Initializes the image stack's first entry (default image) -- ONLY CALL ONCE! +void iSetImage0() +{ + if (ImageStack == NULL) + if (!iEnlargeStack()) + return; + + LastUsed = 1; + CurName = 0; + ParentImage = IL_TRUE; + if (!ImageStack[0]) + ImageStack[0] = ilNewImage(1, 1, 1, 1, 1); + iCurImage = ImageStack[0]; + ilDefaultImage(); + + return; +} + + +ILAPI void ILAPIENTRY iBindImageTemp() +{ + if (ImageStack == NULL || StackSize <= 1) + if (!iEnlargeStack()) + return; + + if (LastUsed < 2) + LastUsed = 2; + CurName = 1; + ParentImage = IL_TRUE; + if (!ImageStack[1]) + ImageStack[1] = ilNewImage(1, 1, 1, 1, 1); + iCurImage = ImageStack[1]; + + return; +} diff --git a/DevIL/src-IL/src/il_states.c b/DevIL/src-IL/src/il_states.c deleted file mode 100644 index 96291887..00000000 --- a/DevIL/src-IL/src/il_states.c +++ /dev/null @@ -1,1192 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_states.c -// -// Description: State machine -// -// -// 20040223 XIX : now has a ilPngAlphaIndex member, so we can spit out png files with a transparent index, set to -1 for none -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#include "il_states.h" -//#include -#include - -ILconst_string _ilVendor = IL_TEXT("Abysmal Software"); -ILconst_string _ilVersion = IL_TEXT("Developer's Image Library (DevIL) 1.7.8"); - - -char* _ilLoadExt = "" IL_BLP_EXT IL_BMP_EXT IL_CUT_EXT IL_DCX_EXT IL_DDS_EXT - IL_DCM_EXT IL_DPX_EXT IL_EXR_EXT IL_FITS_EXT IL_FTX_EXT - IL_GIF_EXT IL_HDR_EXT IL_ICNS_EXT IL_ICO_EXT IL_IFF_EXT - IL_IWI_EXT IL_JPG_EXT IL_JP2_EXT IL_LIF_EXT IL_MDL_EXT - IL_MNG_EXT IL_MP3_EXT IL_PCD_EXT IL_PCX_EXT IL_PIC_EXT - IL_PIX_EXT IL_PNG_EXT IL_PNM_EXT IL_PSD_EXT IL_PSP_EXT - IL_PXR_EXT IL_RAW_EXT IL_ROT_EXT IL_SGI_EXT IL_SUN_EXT - IL_TEX_EXT IL_TGA_EXT IL_TIF_EXT IL_TPL_EXT IL_UTX_EXT - IL_VTF_EXT IL_WAL_EXT IL_WDP_EXT IL_XPM_EXT; - -char* _ilSaveExt = "" IL_BMP_EXT IL_CHEAD_EXT IL_DDS_EXT IL_EXR_EXT - IL_HDR_EXT IL_JP2_EXT IL_JPG_EXT IL_PCX_EXT - IL_PNG_EXT IL_PNM_EXT IL_PSD_EXT IL_RAW_EXT - IL_SGI_EXT IL_TGA_EXT IL_TIF_EXT IL_VTF_EXT - IL_WBMP_EXT; - - -//! Set all states to their defaults. -void ilDefaultStates() -{ - ilStates[ilCurrentPos].ilOriginSet = IL_FALSE; - ilStates[ilCurrentPos].ilOriginMode = IL_ORIGIN_LOWER_LEFT; - ilStates[ilCurrentPos].ilFormatSet = IL_FALSE; - ilStates[ilCurrentPos].ilFormatMode = IL_BGRA; - ilStates[ilCurrentPos].ilTypeSet = IL_FALSE; - ilStates[ilCurrentPos].ilTypeMode = IL_UNSIGNED_BYTE; - ilStates[ilCurrentPos].ilOverWriteFiles = IL_FALSE; - ilStates[ilCurrentPos].ilAutoConvPal = IL_FALSE; - ilStates[ilCurrentPos].ilDefaultOnFail = IL_FALSE; - ilStates[ilCurrentPos].ilUseKeyColour = IL_FALSE; - ilStates[ilCurrentPos].ilBlitBlend = IL_TRUE; - ilStates[ilCurrentPos].ilCompression = IL_COMPRESS_ZLIB; - ilStates[ilCurrentPos].ilInterlace = IL_FALSE; - - ilStates[ilCurrentPos].ilTgaCreateStamp = IL_FALSE; - ilStates[ilCurrentPos].ilJpgQuality = 99; - ilStates[ilCurrentPos].ilPngInterlace = IL_FALSE; - ilStates[ilCurrentPos].ilTgaRle = IL_FALSE; - ilStates[ilCurrentPos].ilBmpRle = IL_FALSE; - ilStates[ilCurrentPos].ilSgiRle = IL_FALSE; - ilStates[ilCurrentPos].ilJpgFormat = IL_JFIF; - ilStates[ilCurrentPos].ilJpgProgressive = IL_FALSE; - ilStates[ilCurrentPos].ilDxtcFormat = IL_DXT1; - ilStates[ilCurrentPos].ilPcdPicNum = 2; - ilStates[ilCurrentPos].ilPngAlphaIndex = -1; - ilStates[ilCurrentPos].ilVtfCompression = IL_DXT_NO_COMP; - - ilStates[ilCurrentPos].ilTgaId = NULL; - ilStates[ilCurrentPos].ilTgaAuthName = NULL; - ilStates[ilCurrentPos].ilTgaAuthComment = NULL; - ilStates[ilCurrentPos].ilPngAuthName = NULL; - ilStates[ilCurrentPos].ilPngTitle = NULL; - ilStates[ilCurrentPos].ilPngDescription = NULL; - - //2003-09-01: added tiff strings - ilStates[ilCurrentPos].ilTifDescription = NULL; - ilStates[ilCurrentPos].ilTifHostComputer = NULL; - ilStates[ilCurrentPos].ilTifDocumentName = NULL; - ilStates[ilCurrentPos].ilTifAuthName = NULL; - ilStates[ilCurrentPos].ilCHeader = NULL; - - ilStates[ilCurrentPos].ilQuantMode = IL_WU_QUANT; - ilStates[ilCurrentPos].ilNeuSample = 15; - ilStates[ilCurrentPos].ilQuantMaxIndexs = 256; - - ilStates[ilCurrentPos].ilKeepDxtcData = IL_FALSE; - ilStates[ilCurrentPos].ilUseNVidiaDXT = IL_FALSE; - ilStates[ilCurrentPos].ilUseSquishDXT = IL_FALSE; - - - - - ilHints.MemVsSpeedHint = IL_FASTEST; - ilHints.CompressHint = IL_USE_COMPRESSION; - - while (ilGetError() != IL_NO_ERROR); - - return; -} - - -//! Returns a constant string detailing aspects about this library. -ILconst_string ILAPIENTRY ilGetString(ILenum StringName) -{ - switch (StringName) - { - case IL_VENDOR: - return (ILconst_string)_ilVendor; - case IL_VERSION_NUM: //changed 2003-08-30: IL_VERSION changes //switch define ;-) - return (ILconst_string)_ilVersion; - case IL_LOAD_EXT: - return (ILconst_string)_ilLoadExt; - case IL_SAVE_EXT: - return (ILconst_string)_ilSaveExt; - case IL_TGA_ID_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTgaId; - case IL_TGA_AUTHNAME_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTgaAuthName; - case IL_TGA_AUTHCOMMENT_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTgaAuthComment; - case IL_PNG_AUTHNAME_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilPngAuthName; - case IL_PNG_TITLE_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilPngTitle; - case IL_PNG_DESCRIPTION_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilPngDescription; - //2003-08-31: added tif strings - case IL_TIF_DESCRIPTION_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTifDescription; - case IL_TIF_HOSTCOMPUTER_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTifHostComputer; - case IL_TIF_DOCUMENTNAME_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTifDocumentName; - case IL_TIF_AUTHNAME_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilTifAuthName; - case IL_CHEAD_HEADER_STRING: - return (ILconst_string)ilStates[ilCurrentPos].ilCHeader; - default: - ilSetError(IL_INVALID_ENUM); - break; - } - return NULL; -} - - -// Clips a string to a certain length and returns a new string. -char *iClipString(char *String, ILuint MaxLen) -{ - char *Clipped; - ILuint Length; - - if (String == NULL) - return NULL; - - Length = ilCharStrLen(String); //ilStrLen(String); - - Clipped = (char*)ialloc((MaxLen + 1) * sizeof(char) /*sizeof(ILchar)*/); // Terminating NULL makes it +1. - if (Clipped == NULL) { - return NULL; - } - - memcpy(Clipped, String, MaxLen * sizeof(char) /*sizeof(ILchar)*/); - Clipped[Length] = 0; - - return Clipped; -} - - -// Returns format-specific strings, truncated to MaxLen (not counting the terminating NULL). -char *iGetString(ILenum StringName) -{ - switch (StringName) - { - case IL_TGA_ID_STRING: - return iClipString(ilStates[ilCurrentPos].ilTgaId, 254); - case IL_TGA_AUTHNAME_STRING: - return iClipString(ilStates[ilCurrentPos].ilTgaAuthName, 40); - case IL_TGA_AUTHCOMMENT_STRING: - return iClipString(ilStates[ilCurrentPos].ilTgaAuthComment, 80); - case IL_PNG_AUTHNAME_STRING: - return iClipString(ilStates[ilCurrentPos].ilPngAuthName, 255); - case IL_PNG_TITLE_STRING: - return iClipString(ilStates[ilCurrentPos].ilPngTitle, 255); - case IL_PNG_DESCRIPTION_STRING: - return iClipString(ilStates[ilCurrentPos].ilPngDescription, 255); - - //changed 2003-08-31...here was a serious copy and paste bug ;-) - case IL_TIF_DESCRIPTION_STRING: - return iClipString(ilStates[ilCurrentPos].ilTifDescription, 255); - case IL_TIF_HOSTCOMPUTER_STRING: - return iClipString(ilStates[ilCurrentPos].ilTifHostComputer, 255); - case IL_TIF_DOCUMENTNAME_STRING: - return iClipString(ilStates[ilCurrentPos].ilTifDocumentName, 255); - case IL_TIF_AUTHNAME_STRING: - return iClipString(ilStates[ilCurrentPos].ilTifAuthName, 255); - case IL_CHEAD_HEADER_STRING: - return iClipString(ilStates[ilCurrentPos].ilCHeader, 32); - default: - ilSetError(IL_INVALID_ENUM); - } - return NULL; -} - - -//! Enables a mode -ILboolean ILAPIENTRY ilEnable(ILenum Mode) -{ - return ilAble(Mode, IL_TRUE); -} - - -//! Disables a mode -ILboolean ILAPIENTRY ilDisable(ILenum Mode) -{ - return ilAble(Mode, IL_FALSE); -} - - -// Internal function that sets the Mode equal to Flag -ILboolean ilAble(ILenum Mode, ILboolean Flag) -{ - switch (Mode) - { - case IL_ORIGIN_SET: - ilStates[ilCurrentPos].ilOriginSet = Flag; - break; - case IL_FORMAT_SET: - ilStates[ilCurrentPos].ilFormatSet = Flag; - break; - case IL_TYPE_SET: - ilStates[ilCurrentPos].ilTypeSet = Flag; - break; - case IL_FILE_OVERWRITE: - ilStates[ilCurrentPos].ilOverWriteFiles = Flag; - break; - case IL_CONV_PAL: - ilStates[ilCurrentPos].ilAutoConvPal = Flag; - break; - case IL_DEFAULT_ON_FAIL: - ilStates[ilCurrentPos].ilDefaultOnFail = Flag; - break; - case IL_USE_KEY_COLOUR: - ilStates[ilCurrentPos].ilUseKeyColour = Flag; - break; - case IL_BLIT_BLEND: - ilStates[ilCurrentPos].ilBlitBlend = Flag; - break; - case IL_SAVE_INTERLACED: - ilStates[ilCurrentPos].ilInterlace = Flag; - break; - case IL_JPG_PROGRESSIVE: - ilStates[ilCurrentPos].ilJpgProgressive = Flag; - break; - case IL_NVIDIA_COMPRESS: - ilStates[ilCurrentPos].ilUseNVidiaDXT = Flag; - break; - case IL_SQUISH_COMPRESS: - ilStates[ilCurrentPos].ilUseSquishDXT = Flag; - break; - - default: - ilSetError(IL_INVALID_ENUM); - return IL_FALSE; - } - - return IL_TRUE; -} - - -//! Checks whether the mode is enabled. -ILboolean ILAPIENTRY ilIsEnabled(ILenum Mode) -{ - switch (Mode) - { - case IL_ORIGIN_SET: - return ilStates[ilCurrentPos].ilOriginSet; - case IL_FORMAT_SET: - return ilStates[ilCurrentPos].ilFormatSet; - case IL_TYPE_SET: - return ilStates[ilCurrentPos].ilTypeSet; - case IL_FILE_OVERWRITE: - return ilStates[ilCurrentPos].ilOverWriteFiles; - case IL_CONV_PAL: - return ilStates[ilCurrentPos].ilAutoConvPal; - case IL_DEFAULT_ON_FAIL: - return ilStates[ilCurrentPos].ilDefaultOnFail; - case IL_USE_KEY_COLOUR: - return ilStates[ilCurrentPos].ilUseKeyColour; - case IL_BLIT_BLEND: - return ilStates[ilCurrentPos].ilBlitBlend; - case IL_SAVE_INTERLACED: - return ilStates[ilCurrentPos].ilInterlace; - case IL_JPG_PROGRESSIVE: - return ilStates[ilCurrentPos].ilJpgProgressive; - case IL_NVIDIA_COMPRESS: - return ilStates[ilCurrentPos].ilUseNVidiaDXT; - case IL_SQUISH_COMPRESS: - return ilStates[ilCurrentPos].ilUseSquishDXT; - - default: - ilSetError(IL_INVALID_ENUM); - } - - return IL_FALSE; -} - - -//! Checks whether the mode is disabled. -ILboolean ILAPIENTRY ilIsDisabled(ILenum Mode) -{ - return !ilIsEnabled(Mode); -} - - -//! Sets Param equal to the current value of the Mode -void ILAPIENTRY ilGetBooleanv(ILenum Mode, ILboolean *Param) -{ - if (Param == NULL) { - ilSetError(IL_INVALID_PARAM); - return; - } - - *Param = ilGetInteger(Mode); - - return; -} - - -//! Returns the current value of the Mode -ILboolean ILAPIENTRY ilGetBoolean(ILenum Mode) -{ - ILboolean Temp; - Temp = IL_FALSE; - ilGetBooleanv(Mode, &Temp); - return Temp; -} - - -ILimage *iGetBaseImage(void); - -//! Internal function to figure out where we are in an image chain. -//@TODO: This may get much more complex with mipmaps under faces, etc. -ILuint iGetActiveNum(ILenum Type) -{ - ILimage *BaseImage; - ILuint Num = 0; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return 0; - } - - BaseImage = iGetBaseImage(); - if (BaseImage == iCurImage) - return 0; - - switch (Type) - { - case IL_ACTIVE_IMAGE: - BaseImage = BaseImage->Next; - do { - if (BaseImage == NULL) - return 0; - Num++; - if (BaseImage == iCurImage) - return Num; - } while ((BaseImage = BaseImage->Next)); - break; - case IL_ACTIVE_MIPMAP: - BaseImage = BaseImage->Mipmaps; - do { - if (BaseImage == NULL) - return 0; - Num++; - if (BaseImage == iCurImage) - return Num; - } while ((BaseImage = BaseImage->Mipmaps)); - break; - case IL_ACTIVE_LAYER: - BaseImage = BaseImage->Layers; - do { - if (BaseImage == NULL) - return 0; - Num++; - if (BaseImage == iCurImage) - return Num; - } while ((BaseImage = BaseImage->Layers)); - break; - case IL_ACTIVE_FACE: - BaseImage = BaseImage->Faces; - do { - if (BaseImage == NULL) - return 0; - Num++; - if (BaseImage == iCurImage) - return Num; - } while ((BaseImage = BaseImage->Faces)); - break; - } - - //@TODO: Any error needed here? - - return 0; -} - - -//! Sets Param equal to the current value of the Mode -void ILAPIENTRY ilGetIntegerv(ILenum Mode, ILint *Param) -{ - if (Param == NULL) { - ilSetError(IL_INVALID_PARAM); - return; - } - - *Param = 0; - - switch (Mode) { - // Integer values - case IL_COMPRESS_MODE: - *Param = ilStates[ilCurrentPos].ilCompression; - break; - case IL_CUR_IMAGE: - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - break; - } - *Param = ilGetCurName(); - break; - case IL_FORMAT_MODE: - *Param = ilStates[ilCurrentPos].ilFormatMode; - break; - case IL_INTERLACE_MODE: - *Param = ilStates[ilCurrentPos].ilInterlace; - break; - case IL_KEEP_DXTC_DATA: - *Param = ilStates[ilCurrentPos].ilKeepDxtcData; - break; - case IL_ORIGIN_MODE: - *Param = ilStates[ilCurrentPos].ilOriginMode; - break; - case IL_MAX_QUANT_INDICES: - *Param = ilStates[ilCurrentPos].ilQuantMaxIndexs; - break; - case IL_NEU_QUANT_SAMPLE: - *Param = ilStates[ilCurrentPos].ilNeuSample; - break; - case IL_QUANTIZATION_MODE: - *Param = ilStates[ilCurrentPos].ilQuantMode; - break; - case IL_TYPE_MODE: - *Param = ilStates[ilCurrentPos].ilTypeMode; - break; - case IL_VERSION_NUM: - *Param = IL_VERSION; - break; - - // Image specific values - case IL_ACTIVE_IMAGE: - case IL_ACTIVE_MIPMAP: - case IL_ACTIVE_LAYER: - *Param = iGetActiveNum(Mode); - break; - - // Format-specific values - case IL_BMP_RLE: - *Param = ilStates[ilCurrentPos].ilBmpRle; - break; - case IL_DXTC_FORMAT: - *Param = ilStates[ilCurrentPos].ilDxtcFormat; - break; - case IL_JPG_QUALITY: - *Param = ilStates[ilCurrentPos].ilJpgQuality; - break; - case IL_JPG_SAVE_FORMAT: - *Param = ilStates[ilCurrentPos].ilJpgFormat; - break; - case IL_PCD_PICNUM: - *Param = ilStates[ilCurrentPos].ilPcdPicNum; - break; - case IL_PNG_ALPHA_INDEX: - *Param = ilStates[ilCurrentPos].ilPngAlphaIndex; - break; - case IL_PNG_INTERLACE: - *Param = ilStates[ilCurrentPos].ilPngInterlace; - break; - case IL_SGI_RLE: - *Param = ilStates[ilCurrentPos].ilSgiRle; - break; - case IL_TGA_CREATE_STAMP: - *Param = ilStates[ilCurrentPos].ilTgaCreateStamp; - break; - case IL_TGA_RLE: - *Param = ilStates[ilCurrentPos].ilTgaRle; - break; - case IL_VTF_COMP: - *Param = ilStates[ilCurrentPos].ilVtfCompression; - break; - - // Boolean values - case IL_CONV_PAL: - *Param = ilStates[ilCurrentPos].ilAutoConvPal; - break; - case IL_DEFAULT_ON_FAIL: - *Param = ilStates[ilCurrentPos].ilDefaultOnFail; - break; - case IL_FILE_MODE: - *Param = ilStates[ilCurrentPos].ilOverWriteFiles; - break; - case IL_FORMAT_SET: - *Param = ilStates[ilCurrentPos].ilFormatSet; - break; - case IL_ORIGIN_SET: - *Param = ilStates[ilCurrentPos].ilOriginSet; - break; - case IL_TYPE_SET: - *Param = ilStates[ilCurrentPos].ilTypeSet; - break; - case IL_USE_KEY_COLOUR: - *Param = ilStates[ilCurrentPos].ilUseKeyColour; - break; - case IL_BLIT_BLEND: - *Param = ilStates[ilCurrentPos].ilBlitBlend; - break; - case IL_JPG_PROGRESSIVE: - *Param = ilStates[ilCurrentPos].ilJpgProgressive; - break; - case IL_NVIDIA_COMPRESS: - *Param = ilStates[ilCurrentPos].ilUseNVidiaDXT; - break; - case IL_SQUISH_COMPRESS: - *Param = ilStates[ilCurrentPos].ilUseSquishDXT; - break; - - default: - iGetIntegervImage(iCurImage, Mode, Param); - } - - return; -} - -//@TODO rename to ilGetImageIntegerv for 1.6.9 and make it public -//! Sets Param equal to the current value of the Mode -void ILAPIENTRY iGetIntegervImage(ILimage *Image, ILenum Mode, ILint *Param) -{ - ILimage *SubImage; - if (Image == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return; - } - if (Param == NULL) { - ilSetError(IL_INVALID_PARAM); - return; - } - *Param = 0; - - switch (Mode) - { - case IL_DXTC_DATA_FORMAT: - if (Image->DxtcData == NULL || Image->DxtcSize == 0) { - *Param = IL_DXT_NO_COMP; - break; - } - *Param = Image->DxtcFormat; - break; - //// - case IL_IMAGE_BITS_PER_PIXEL: - //changed 20040610 to channel count (Bpp) times Bytes per channel - *Param = (Image->Bpp << 3)*Image->Bpc; - break; - case IL_IMAGE_BYTES_PER_PIXEL: - //changed 20040610 to channel count (Bpp) times Bytes per channel - *Param = Image->Bpp*Image->Bpc; - break; - case IL_IMAGE_BPC: - *Param = Image->Bpc; - break; - case IL_IMAGE_CHANNELS: - *Param = Image->Bpp; - break; - case IL_IMAGE_CUBEFLAGS: - *Param = Image->CubeFlags; - break; - case IL_IMAGE_DEPTH: - *Param = Image->Depth; - break; - case IL_IMAGE_DURATION: - *Param = Image->Duration; - break; - case IL_IMAGE_FORMAT: - *Param = Image->Format; - break; - case IL_IMAGE_HEIGHT: - *Param = Image->Height; - break; - case IL_IMAGE_SIZE_OF_DATA: - *Param = Image->SizeOfData; - - break; - case IL_IMAGE_OFFX: - *Param = Image->OffX; - break; - case IL_IMAGE_OFFY: - *Param = Image->OffY; - break; - case IL_IMAGE_ORIGIN: - *Param = Image->Origin; - break; - case IL_IMAGE_PLANESIZE: - *Param = Image->SizeOfPlane; - break; - case IL_IMAGE_TYPE: - *Param = Image->Type; - break; - case IL_IMAGE_WIDTH: - *Param = Image->Width; - break; - case IL_NUM_FACES: - for (SubImage = Image->Faces; SubImage; SubImage = SubImage->Faces) - (*Param)++; - break; - case IL_NUM_IMAGES: - for (SubImage = Image->Next; SubImage; SubImage = SubImage->Next) - (*Param)++; - break; - case IL_NUM_LAYERS: - for (SubImage = Image->Layers; SubImage; SubImage = SubImage->Layers) - (*Param)++; - break; - case IL_NUM_MIPMAPS: - for (SubImage = Image->Mipmaps; SubImage; SubImage = SubImage->Mipmaps) - (*Param)++; - break; - - case IL_PALETTE_TYPE: - *Param = Image->Pal.PalType; - break; - case IL_PALETTE_BPP: - *Param = ilGetBppPal(Image->Pal.PalType); - break; - case IL_PALETTE_NUM_COLS: - if (!Image->Pal.Palette || !Image->Pal.PalSize || Image->Pal.PalType == IL_PAL_NONE) - *Param = 0; - else - *Param = Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType); - break; - case IL_PALETTE_BASE_TYPE: - switch (Image->Pal.PalType) - { - case IL_PAL_RGB24: - *Param = IL_RGB; - case IL_PAL_RGB32: - *Param = IL_RGBA; // Not sure - case IL_PAL_RGBA32: - *Param = IL_RGBA; - case IL_PAL_BGR24: - *Param = IL_BGR; - case IL_PAL_BGR32: - *Param = IL_BGRA; // Not sure - case IL_PAL_BGRA32: - *Param = IL_BGRA; - } - break; - default: - ilSetError(IL_INVALID_ENUM); - } -} - - - -//! Returns the current value of the Mode -ILint ILAPIENTRY ilGetInteger(ILenum Mode) -{ - ILint Temp; - Temp = 0; - ilGetIntegerv(Mode, &Temp); - return Temp; -} - - -//! Sets the default origin to be used. -ILboolean ILAPIENTRY ilOriginFunc(ILenum Mode) -{ - switch (Mode) - { - case IL_ORIGIN_LOWER_LEFT: - case IL_ORIGIN_UPPER_LEFT: - ilStates[ilCurrentPos].ilOriginMode = Mode; - break; - default: - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - return IL_TRUE; -} - - -//! Sets the default format to be used. -ILboolean ILAPIENTRY ilFormatFunc(ILenum Mode) -{ - switch (Mode) - { - //case IL_COLOUR_INDEX: - case IL_RGB: - case IL_RGBA: - case IL_BGR: - case IL_BGRA: - case IL_LUMINANCE: - case IL_LUMINANCE_ALPHA: - ilStates[ilCurrentPos].ilFormatMode = Mode; - break; - default: - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - return IL_TRUE; -} - - -//! Sets the default type to be used. -ILboolean ILAPIENTRY ilTypeFunc(ILenum Mode) -{ - switch (Mode) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - case IL_SHORT: - case IL_UNSIGNED_SHORT: - case IL_INT: - case IL_UNSIGNED_INT: - case IL_FLOAT: - case IL_DOUBLE: - ilStates[ilCurrentPos].ilTypeMode = Mode; - break; - default: - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - return IL_TRUE; -} - - -ILboolean ILAPIENTRY ilCompressFunc(ILenum Mode) -{ - switch (Mode) - { - case IL_COMPRESS_NONE: - case IL_COMPRESS_RLE: - //case IL_COMPRESS_LZO: - case IL_COMPRESS_ZLIB: - ilStates[ilCurrentPos].ilCompression = Mode; - break; - default: - ilSetError(IL_INVALID_PARAM); - return IL_FALSE; - } - return IL_TRUE; -} - - -//! Pushes the states indicated by Bits onto the state stack -void ILAPIENTRY ilPushAttrib(ILuint Bits) -{ - // Should we check here to see if ilCurrentPos is negative? - - if (ilCurrentPos >= IL_ATTRIB_STACK_MAX - 1) { - ilCurrentPos = IL_ATTRIB_STACK_MAX - 1; - ilSetError(IL_STACK_OVERFLOW); - return; - } - - ilCurrentPos++; - - // memcpy(&ilStates[ilCurrentPos], &ilStates[ilCurrentPos - 1], sizeof(IL_STATES)); - - ilDefaultStates(); - - if (Bits & IL_ORIGIN_BIT) { - ilStates[ilCurrentPos].ilOriginMode = ilStates[ilCurrentPos-1].ilOriginMode; - ilStates[ilCurrentPos].ilOriginSet = ilStates[ilCurrentPos-1].ilOriginSet; - } - if (Bits & IL_FORMAT_BIT) { - ilStates[ilCurrentPos].ilFormatMode = ilStates[ilCurrentPos-1].ilFormatMode; - ilStates[ilCurrentPos].ilFormatSet = ilStates[ilCurrentPos-1].ilFormatSet; - } - if (Bits & IL_TYPE_BIT) { - ilStates[ilCurrentPos].ilTypeMode = ilStates[ilCurrentPos-1].ilTypeMode; - ilStates[ilCurrentPos].ilTypeSet = ilStates[ilCurrentPos-1].ilTypeSet; - } - if (Bits & IL_FILE_BIT) { - ilStates[ilCurrentPos].ilOverWriteFiles = ilStates[ilCurrentPos-1].ilOverWriteFiles; - } - if (Bits & IL_PAL_BIT) { - ilStates[ilCurrentPos].ilAutoConvPal = ilStates[ilCurrentPos-1].ilAutoConvPal; - } - if (Bits & IL_LOADFAIL_BIT) { - ilStates[ilCurrentPos].ilDefaultOnFail = ilStates[ilCurrentPos-1].ilDefaultOnFail; - } - if (Bits & IL_COMPRESS_BIT) { - ilStates[ilCurrentPos].ilCompression = ilStates[ilCurrentPos-1].ilCompression; - } - if (Bits & IL_FORMAT_SPECIFIC_BIT) { - ilStates[ilCurrentPos].ilTgaCreateStamp = ilStates[ilCurrentPos-1].ilTgaCreateStamp; - ilStates[ilCurrentPos].ilJpgQuality = ilStates[ilCurrentPos-1].ilJpgQuality; - ilStates[ilCurrentPos].ilPngInterlace = ilStates[ilCurrentPos-1].ilPngInterlace; - ilStates[ilCurrentPos].ilTgaRle = ilStates[ilCurrentPos-1].ilTgaRle; - ilStates[ilCurrentPos].ilBmpRle = ilStates[ilCurrentPos-1].ilBmpRle; - ilStates[ilCurrentPos].ilSgiRle = ilStates[ilCurrentPos-1].ilSgiRle; - ilStates[ilCurrentPos].ilJpgFormat = ilStates[ilCurrentPos-1].ilJpgFormat; - ilStates[ilCurrentPos].ilDxtcFormat = ilStates[ilCurrentPos-1].ilDxtcFormat; - ilStates[ilCurrentPos].ilPcdPicNum = ilStates[ilCurrentPos-1].ilPcdPicNum; - - ilStates[ilCurrentPos].ilPngAlphaIndex = ilStates[ilCurrentPos-1].ilPngAlphaIndex; - - // Strings - if (ilStates[ilCurrentPos].ilTgaId) - ifree(ilStates[ilCurrentPos].ilTgaId); - if (ilStates[ilCurrentPos].ilTgaAuthName) - ifree(ilStates[ilCurrentPos].ilTgaAuthName); - if (ilStates[ilCurrentPos].ilTgaAuthComment) - ifree(ilStates[ilCurrentPos].ilTgaAuthComment); - if (ilStates[ilCurrentPos].ilPngAuthName) - ifree(ilStates[ilCurrentPos].ilPngAuthName); - if (ilStates[ilCurrentPos].ilPngTitle) - ifree(ilStates[ilCurrentPos].ilPngTitle); - if (ilStates[ilCurrentPos].ilPngDescription) - ifree(ilStates[ilCurrentPos].ilPngDescription); - - //2003-09-01: added tif strings - if (ilStates[ilCurrentPos].ilTifDescription) - ifree(ilStates[ilCurrentPos].ilTifDescription); - if (ilStates[ilCurrentPos].ilTifHostComputer) - ifree(ilStates[ilCurrentPos].ilTifHostComputer); - if (ilStates[ilCurrentPos].ilTifDocumentName) - ifree(ilStates[ilCurrentPos].ilTifDocumentName); - if (ilStates[ilCurrentPos].ilTifAuthName) - ifree(ilStates[ilCurrentPos].ilTifAuthName); - - if (ilStates[ilCurrentPos].ilCHeader) - ifree(ilStates[ilCurrentPos].ilCHeader); - - ilStates[ilCurrentPos].ilTgaId = strdup(ilStates[ilCurrentPos-1].ilTgaId); - ilStates[ilCurrentPos].ilTgaAuthName = strdup(ilStates[ilCurrentPos-1].ilTgaAuthName); - ilStates[ilCurrentPos].ilTgaAuthComment = strdup(ilStates[ilCurrentPos-1].ilTgaAuthComment); - ilStates[ilCurrentPos].ilPngAuthName = strdup(ilStates[ilCurrentPos-1].ilPngAuthName); - ilStates[ilCurrentPos].ilPngTitle = strdup(ilStates[ilCurrentPos-1].ilPngTitle); - ilStates[ilCurrentPos].ilPngDescription = strdup(ilStates[ilCurrentPos-1].ilPngDescription); - - //2003-09-01: added tif strings - ilStates[ilCurrentPos].ilTifDescription = strdup(ilStates[ilCurrentPos-1].ilTifDescription); - ilStates[ilCurrentPos].ilTifHostComputer = strdup(ilStates[ilCurrentPos-1].ilTifHostComputer); - ilStates[ilCurrentPos].ilTifDocumentName = strdup(ilStates[ilCurrentPos-1].ilTifDocumentName); - ilStates[ilCurrentPos].ilTifAuthName = strdup(ilStates[ilCurrentPos-1].ilTifAuthName); - - ilStates[ilCurrentPos].ilCHeader = strdup(ilStates[ilCurrentPos-1].ilCHeader); - } - - return; -} - - -// @TODO: Find out how this affects strings!!! - -//! Pops the last entry off the state stack into the current states -void ILAPIENTRY ilPopAttrib() -{ - if (ilCurrentPos <= 0) { - ilCurrentPos = 0; - ilSetError(IL_STACK_UNDERFLOW); - return; - } - - // Should we check here to see if ilCurrentPos is too large? - ilCurrentPos--; - - return; -} - - -//! Specifies implementation-dependent performance hints -void ILAPIENTRY ilHint(ILenum Target, ILenum Mode) -{ - switch (Target) - { - case IL_MEM_SPEED_HINT: - switch (Mode) - { - case IL_FASTEST: - ilHints.MemVsSpeedHint = Mode; - break; - case IL_LESS_MEM: - ilHints.MemVsSpeedHint = Mode; - break; - case IL_DONT_CARE: - ilHints.MemVsSpeedHint = IL_FASTEST; - break; - default: - ilSetError(IL_INVALID_ENUM); - return; - } - break; - - case IL_COMPRESSION_HINT: - switch (Mode) - { - case IL_USE_COMPRESSION: - ilHints.CompressHint = Mode; - break; - case IL_NO_COMPRESSION: - ilHints.CompressHint = Mode; - break; - case IL_DONT_CARE: - ilHints.CompressHint = IL_NO_COMPRESSION; - break; - default: - ilSetError(IL_INVALID_ENUM); - return; - } - break; - - - default: - ilSetError(IL_INVALID_ENUM); - return; - } - - return; -} - - -ILenum iGetHint(ILenum Target) -{ - switch (Target) - { - case IL_MEM_SPEED_HINT: - return ilHints.MemVsSpeedHint; - case IL_COMPRESSION_HINT: - return ilHints.CompressHint; - default: - ilSetError(IL_INTERNAL_ERROR); - return 0; - } -} - - -void ILAPIENTRY ilSetString(ILenum Mode, const char *String) -{ - if (String == NULL) { - ilSetError(IL_INVALID_PARAM); - return; - } - - switch (Mode) - { - case IL_TGA_ID_STRING: - if (ilStates[ilCurrentPos].ilTgaId) - ifree(ilStates[ilCurrentPos].ilTgaId); - ilStates[ilCurrentPos].ilTgaId = strdup(String); - break; - case IL_TGA_AUTHNAME_STRING: - if (ilStates[ilCurrentPos].ilTgaAuthName) - ifree(ilStates[ilCurrentPos].ilTgaAuthName); - ilStates[ilCurrentPos].ilTgaAuthName = strdup(String); - break; - case IL_TGA_AUTHCOMMENT_STRING: - if (ilStates[ilCurrentPos].ilTgaAuthComment) - ifree(ilStates[ilCurrentPos].ilTgaAuthComment); - ilStates[ilCurrentPos].ilTgaAuthComment = strdup(String); - break; - case IL_PNG_AUTHNAME_STRING: - if (ilStates[ilCurrentPos].ilPngAuthName) - ifree(ilStates[ilCurrentPos].ilPngAuthName); - ilStates[ilCurrentPos].ilPngAuthName = strdup(String); - break; - case IL_PNG_TITLE_STRING: - if (ilStates[ilCurrentPos].ilPngTitle) - ifree(ilStates[ilCurrentPos].ilPngTitle); - ilStates[ilCurrentPos].ilPngTitle = strdup(String); - break; - case IL_PNG_DESCRIPTION_STRING: - if (ilStates[ilCurrentPos].ilPngDescription) - ifree(ilStates[ilCurrentPos].ilPngDescription); - ilStates[ilCurrentPos].ilPngDescription = strdup(String); - break; - - //2003-09-01: added tif strings - case IL_TIF_DESCRIPTION_STRING: - if (ilStates[ilCurrentPos].ilTifDescription) - ifree(ilStates[ilCurrentPos].ilTifDescription); - ilStates[ilCurrentPos].ilTifDescription = strdup(String); - break; - case IL_TIF_HOSTCOMPUTER_STRING: - if (ilStates[ilCurrentPos].ilTifHostComputer) - ifree(ilStates[ilCurrentPos].ilTifHostComputer); - ilStates[ilCurrentPos].ilTifHostComputer = strdup(String); - break; - case IL_TIF_DOCUMENTNAME_STRING: - if (ilStates[ilCurrentPos].ilTifDocumentName) - ifree(ilStates[ilCurrentPos].ilTifDocumentName); - ilStates[ilCurrentPos].ilTifDocumentName = strdup(String); - break; - case IL_TIF_AUTHNAME_STRING: - if (ilStates[ilCurrentPos].ilTifAuthName) - ifree(ilStates[ilCurrentPos].ilTifAuthName); - ilStates[ilCurrentPos].ilTifAuthName = strdup(String); - break; - - case IL_CHEAD_HEADER_STRING: - if (ilStates[ilCurrentPos].ilCHeader) - ifree(ilStates[ilCurrentPos].ilCHeader); - ilStates[ilCurrentPos].ilCHeader = strdup(String); - break; - - default: - ilSetError(IL_INVALID_ENUM); - } - - return; -} - - -void ILAPIENTRY ilSetInteger(ILenum Mode, ILint Param) -{ - switch (Mode) - { - // Integer values - case IL_FORMAT_MODE: - ilFormatFunc(Param); - return; - case IL_KEEP_DXTC_DATA: - if (Param == IL_FALSE || Param == IL_TRUE) { - ilStates[ilCurrentPos].ilKeepDxtcData = Param; - return; - } - break; - case IL_MAX_QUANT_INDICES: - if (Param >= 2 && Param <= 256) { - ilStates[ilCurrentPos].ilQuantMaxIndexs = Param; - return; - } - break; - case IL_NEU_QUANT_SAMPLE: - if (Param >= 1 && Param <= 30) { - ilStates[ilCurrentPos].ilNeuSample = Param; - return; - } - break; - case IL_ORIGIN_MODE: - ilOriginFunc(Param); - return; - case IL_QUANTIZATION_MODE: - if (Param == IL_WU_QUANT || Param == IL_NEU_QUANT) { - ilStates[ilCurrentPos].ilQuantMode = Param; - return; - } - break; - case IL_TYPE_MODE: - ilTypeFunc(Param); - return; - - // Image specific values - case IL_IMAGE_DURATION: - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - break; - } - iCurImage->Duration = Param; - return; - case IL_IMAGE_OFFX: - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - break; - } - iCurImage->OffX = Param; - return; - case IL_IMAGE_OFFY: - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - break; - } - iCurImage->OffY = Param; - return; - case IL_IMAGE_CUBEFLAGS: - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - break; - } - iCurImage->CubeFlags = Param; - break; - - // Format specific values - case IL_BMP_RLE: - if (Param == IL_FALSE || Param == IL_TRUE) { - ilStates[ilCurrentPos].ilBmpRle = Param; - return; - } - break; - case IL_DXTC_FORMAT: - if (Param >= IL_DXT1 || Param <= IL_DXT5 || Param == IL_DXT1A) { - ilStates[ilCurrentPos].ilDxtcFormat = Param; - return; - } - break; - case IL_JPG_SAVE_FORMAT: - if (Param == IL_JFIF || Param == IL_EXIF) { - ilStates[ilCurrentPos].ilJpgFormat = Param; - return; - } - break; - case IL_JPG_QUALITY: - if (Param >= 0 && Param <= 99) { - ilStates[ilCurrentPos].ilJpgQuality = Param; - return; - } - break; - case IL_PNG_INTERLACE: - if (Param == IL_FALSE || Param == IL_TRUE) { - ilStates[ilCurrentPos].ilPngInterlace = Param; - return; - } - break; - case IL_PCD_PICNUM: - if (Param >= 0 || Param <= 2) { - ilStates[ilCurrentPos].ilPcdPicNum = Param; - return; - } - break; - case IL_PNG_ALPHA_INDEX: - if (Param >= -1 || Param <= 255) { - ilStates[ilCurrentPos].ilPngAlphaIndex=Param; - return; - } - break; - case IL_SGI_RLE: - if (Param == IL_FALSE || Param == IL_TRUE) { - ilStates[ilCurrentPos].ilSgiRle = Param; - return; - } - break; - case IL_TGA_CREATE_STAMP: - if (Param == IL_FALSE || Param == IL_TRUE) { - ilStates[ilCurrentPos].ilTgaCreateStamp = Param; - return; - } - break; - case IL_TGA_RLE: - if (Param == IL_FALSE || Param == IL_TRUE) { - ilStates[ilCurrentPos].ilTgaRle = Param; - return; - } - break; - case IL_VTF_COMP: - if (Param == IL_DXT1 || Param == IL_DXT5 || Param == IL_DXT3 || Param == IL_DXT1A || Param == IL_DXT_NO_COMP) { - ilStates[ilCurrentPos].ilVtfCompression = Param; - return; - } - break; - - default: - ilSetError(IL_INVALID_ENUM); - return; - } - - ilSetError(IL_INVALID_PARAM); // Parameter not in valid bounds. - return; -} - - - -ILint iGetInt(ILenum Mode) -{ - //like ilGetInteger(), but sets another error on failure - - //call ilGetIntegerv() for more robust code - ILenum err; - ILint r = -1; - - ilGetIntegerv(Mode, &r); - - //check if an error occured, set another error - err = ilGetError(); - if (r == -1 && err == IL_INVALID_ENUM) - ilSetError(IL_INTERNAL_ERROR); - else - ilSetError(err); //restore error - - return r; -} diff --git a/DevIL/src-IL/src/il_states.cpp b/DevIL/src-IL/src/il_states.cpp new file mode 100644 index 00000000..96291887 --- /dev/null +++ b/DevIL/src-IL/src/il_states.cpp @@ -0,0 +1,1192 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_states.c +// +// Description: State machine +// +// +// 20040223 XIX : now has a ilPngAlphaIndex member, so we can spit out png files with a transparent index, set to -1 for none +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#include "il_states.h" +//#include +#include + +ILconst_string _ilVendor = IL_TEXT("Abysmal Software"); +ILconst_string _ilVersion = IL_TEXT("Developer's Image Library (DevIL) 1.7.8"); + + +char* _ilLoadExt = "" IL_BLP_EXT IL_BMP_EXT IL_CUT_EXT IL_DCX_EXT IL_DDS_EXT + IL_DCM_EXT IL_DPX_EXT IL_EXR_EXT IL_FITS_EXT IL_FTX_EXT + IL_GIF_EXT IL_HDR_EXT IL_ICNS_EXT IL_ICO_EXT IL_IFF_EXT + IL_IWI_EXT IL_JPG_EXT IL_JP2_EXT IL_LIF_EXT IL_MDL_EXT + IL_MNG_EXT IL_MP3_EXT IL_PCD_EXT IL_PCX_EXT IL_PIC_EXT + IL_PIX_EXT IL_PNG_EXT IL_PNM_EXT IL_PSD_EXT IL_PSP_EXT + IL_PXR_EXT IL_RAW_EXT IL_ROT_EXT IL_SGI_EXT IL_SUN_EXT + IL_TEX_EXT IL_TGA_EXT IL_TIF_EXT IL_TPL_EXT IL_UTX_EXT + IL_VTF_EXT IL_WAL_EXT IL_WDP_EXT IL_XPM_EXT; + +char* _ilSaveExt = "" IL_BMP_EXT IL_CHEAD_EXT IL_DDS_EXT IL_EXR_EXT + IL_HDR_EXT IL_JP2_EXT IL_JPG_EXT IL_PCX_EXT + IL_PNG_EXT IL_PNM_EXT IL_PSD_EXT IL_RAW_EXT + IL_SGI_EXT IL_TGA_EXT IL_TIF_EXT IL_VTF_EXT + IL_WBMP_EXT; + + +//! Set all states to their defaults. +void ilDefaultStates() +{ + ilStates[ilCurrentPos].ilOriginSet = IL_FALSE; + ilStates[ilCurrentPos].ilOriginMode = IL_ORIGIN_LOWER_LEFT; + ilStates[ilCurrentPos].ilFormatSet = IL_FALSE; + ilStates[ilCurrentPos].ilFormatMode = IL_BGRA; + ilStates[ilCurrentPos].ilTypeSet = IL_FALSE; + ilStates[ilCurrentPos].ilTypeMode = IL_UNSIGNED_BYTE; + ilStates[ilCurrentPos].ilOverWriteFiles = IL_FALSE; + ilStates[ilCurrentPos].ilAutoConvPal = IL_FALSE; + ilStates[ilCurrentPos].ilDefaultOnFail = IL_FALSE; + ilStates[ilCurrentPos].ilUseKeyColour = IL_FALSE; + ilStates[ilCurrentPos].ilBlitBlend = IL_TRUE; + ilStates[ilCurrentPos].ilCompression = IL_COMPRESS_ZLIB; + ilStates[ilCurrentPos].ilInterlace = IL_FALSE; + + ilStates[ilCurrentPos].ilTgaCreateStamp = IL_FALSE; + ilStates[ilCurrentPos].ilJpgQuality = 99; + ilStates[ilCurrentPos].ilPngInterlace = IL_FALSE; + ilStates[ilCurrentPos].ilTgaRle = IL_FALSE; + ilStates[ilCurrentPos].ilBmpRle = IL_FALSE; + ilStates[ilCurrentPos].ilSgiRle = IL_FALSE; + ilStates[ilCurrentPos].ilJpgFormat = IL_JFIF; + ilStates[ilCurrentPos].ilJpgProgressive = IL_FALSE; + ilStates[ilCurrentPos].ilDxtcFormat = IL_DXT1; + ilStates[ilCurrentPos].ilPcdPicNum = 2; + ilStates[ilCurrentPos].ilPngAlphaIndex = -1; + ilStates[ilCurrentPos].ilVtfCompression = IL_DXT_NO_COMP; + + ilStates[ilCurrentPos].ilTgaId = NULL; + ilStates[ilCurrentPos].ilTgaAuthName = NULL; + ilStates[ilCurrentPos].ilTgaAuthComment = NULL; + ilStates[ilCurrentPos].ilPngAuthName = NULL; + ilStates[ilCurrentPos].ilPngTitle = NULL; + ilStates[ilCurrentPos].ilPngDescription = NULL; + + //2003-09-01: added tiff strings + ilStates[ilCurrentPos].ilTifDescription = NULL; + ilStates[ilCurrentPos].ilTifHostComputer = NULL; + ilStates[ilCurrentPos].ilTifDocumentName = NULL; + ilStates[ilCurrentPos].ilTifAuthName = NULL; + ilStates[ilCurrentPos].ilCHeader = NULL; + + ilStates[ilCurrentPos].ilQuantMode = IL_WU_QUANT; + ilStates[ilCurrentPos].ilNeuSample = 15; + ilStates[ilCurrentPos].ilQuantMaxIndexs = 256; + + ilStates[ilCurrentPos].ilKeepDxtcData = IL_FALSE; + ilStates[ilCurrentPos].ilUseNVidiaDXT = IL_FALSE; + ilStates[ilCurrentPos].ilUseSquishDXT = IL_FALSE; + + + + + ilHints.MemVsSpeedHint = IL_FASTEST; + ilHints.CompressHint = IL_USE_COMPRESSION; + + while (ilGetError() != IL_NO_ERROR); + + return; +} + + +//! Returns a constant string detailing aspects about this library. +ILconst_string ILAPIENTRY ilGetString(ILenum StringName) +{ + switch (StringName) + { + case IL_VENDOR: + return (ILconst_string)_ilVendor; + case IL_VERSION_NUM: //changed 2003-08-30: IL_VERSION changes //switch define ;-) + return (ILconst_string)_ilVersion; + case IL_LOAD_EXT: + return (ILconst_string)_ilLoadExt; + case IL_SAVE_EXT: + return (ILconst_string)_ilSaveExt; + case IL_TGA_ID_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTgaId; + case IL_TGA_AUTHNAME_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTgaAuthName; + case IL_TGA_AUTHCOMMENT_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTgaAuthComment; + case IL_PNG_AUTHNAME_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilPngAuthName; + case IL_PNG_TITLE_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilPngTitle; + case IL_PNG_DESCRIPTION_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilPngDescription; + //2003-08-31: added tif strings + case IL_TIF_DESCRIPTION_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTifDescription; + case IL_TIF_HOSTCOMPUTER_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTifHostComputer; + case IL_TIF_DOCUMENTNAME_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTifDocumentName; + case IL_TIF_AUTHNAME_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilTifAuthName; + case IL_CHEAD_HEADER_STRING: + return (ILconst_string)ilStates[ilCurrentPos].ilCHeader; + default: + ilSetError(IL_INVALID_ENUM); + break; + } + return NULL; +} + + +// Clips a string to a certain length and returns a new string. +char *iClipString(char *String, ILuint MaxLen) +{ + char *Clipped; + ILuint Length; + + if (String == NULL) + return NULL; + + Length = ilCharStrLen(String); //ilStrLen(String); + + Clipped = (char*)ialloc((MaxLen + 1) * sizeof(char) /*sizeof(ILchar)*/); // Terminating NULL makes it +1. + if (Clipped == NULL) { + return NULL; + } + + memcpy(Clipped, String, MaxLen * sizeof(char) /*sizeof(ILchar)*/); + Clipped[Length] = 0; + + return Clipped; +} + + +// Returns format-specific strings, truncated to MaxLen (not counting the terminating NULL). +char *iGetString(ILenum StringName) +{ + switch (StringName) + { + case IL_TGA_ID_STRING: + return iClipString(ilStates[ilCurrentPos].ilTgaId, 254); + case IL_TGA_AUTHNAME_STRING: + return iClipString(ilStates[ilCurrentPos].ilTgaAuthName, 40); + case IL_TGA_AUTHCOMMENT_STRING: + return iClipString(ilStates[ilCurrentPos].ilTgaAuthComment, 80); + case IL_PNG_AUTHNAME_STRING: + return iClipString(ilStates[ilCurrentPos].ilPngAuthName, 255); + case IL_PNG_TITLE_STRING: + return iClipString(ilStates[ilCurrentPos].ilPngTitle, 255); + case IL_PNG_DESCRIPTION_STRING: + return iClipString(ilStates[ilCurrentPos].ilPngDescription, 255); + + //changed 2003-08-31...here was a serious copy and paste bug ;-) + case IL_TIF_DESCRIPTION_STRING: + return iClipString(ilStates[ilCurrentPos].ilTifDescription, 255); + case IL_TIF_HOSTCOMPUTER_STRING: + return iClipString(ilStates[ilCurrentPos].ilTifHostComputer, 255); + case IL_TIF_DOCUMENTNAME_STRING: + return iClipString(ilStates[ilCurrentPos].ilTifDocumentName, 255); + case IL_TIF_AUTHNAME_STRING: + return iClipString(ilStates[ilCurrentPos].ilTifAuthName, 255); + case IL_CHEAD_HEADER_STRING: + return iClipString(ilStates[ilCurrentPos].ilCHeader, 32); + default: + ilSetError(IL_INVALID_ENUM); + } + return NULL; +} + + +//! Enables a mode +ILboolean ILAPIENTRY ilEnable(ILenum Mode) +{ + return ilAble(Mode, IL_TRUE); +} + + +//! Disables a mode +ILboolean ILAPIENTRY ilDisable(ILenum Mode) +{ + return ilAble(Mode, IL_FALSE); +} + + +// Internal function that sets the Mode equal to Flag +ILboolean ilAble(ILenum Mode, ILboolean Flag) +{ + switch (Mode) + { + case IL_ORIGIN_SET: + ilStates[ilCurrentPos].ilOriginSet = Flag; + break; + case IL_FORMAT_SET: + ilStates[ilCurrentPos].ilFormatSet = Flag; + break; + case IL_TYPE_SET: + ilStates[ilCurrentPos].ilTypeSet = Flag; + break; + case IL_FILE_OVERWRITE: + ilStates[ilCurrentPos].ilOverWriteFiles = Flag; + break; + case IL_CONV_PAL: + ilStates[ilCurrentPos].ilAutoConvPal = Flag; + break; + case IL_DEFAULT_ON_FAIL: + ilStates[ilCurrentPos].ilDefaultOnFail = Flag; + break; + case IL_USE_KEY_COLOUR: + ilStates[ilCurrentPos].ilUseKeyColour = Flag; + break; + case IL_BLIT_BLEND: + ilStates[ilCurrentPos].ilBlitBlend = Flag; + break; + case IL_SAVE_INTERLACED: + ilStates[ilCurrentPos].ilInterlace = Flag; + break; + case IL_JPG_PROGRESSIVE: + ilStates[ilCurrentPos].ilJpgProgressive = Flag; + break; + case IL_NVIDIA_COMPRESS: + ilStates[ilCurrentPos].ilUseNVidiaDXT = Flag; + break; + case IL_SQUISH_COMPRESS: + ilStates[ilCurrentPos].ilUseSquishDXT = Flag; + break; + + default: + ilSetError(IL_INVALID_ENUM); + return IL_FALSE; + } + + return IL_TRUE; +} + + +//! Checks whether the mode is enabled. +ILboolean ILAPIENTRY ilIsEnabled(ILenum Mode) +{ + switch (Mode) + { + case IL_ORIGIN_SET: + return ilStates[ilCurrentPos].ilOriginSet; + case IL_FORMAT_SET: + return ilStates[ilCurrentPos].ilFormatSet; + case IL_TYPE_SET: + return ilStates[ilCurrentPos].ilTypeSet; + case IL_FILE_OVERWRITE: + return ilStates[ilCurrentPos].ilOverWriteFiles; + case IL_CONV_PAL: + return ilStates[ilCurrentPos].ilAutoConvPal; + case IL_DEFAULT_ON_FAIL: + return ilStates[ilCurrentPos].ilDefaultOnFail; + case IL_USE_KEY_COLOUR: + return ilStates[ilCurrentPos].ilUseKeyColour; + case IL_BLIT_BLEND: + return ilStates[ilCurrentPos].ilBlitBlend; + case IL_SAVE_INTERLACED: + return ilStates[ilCurrentPos].ilInterlace; + case IL_JPG_PROGRESSIVE: + return ilStates[ilCurrentPos].ilJpgProgressive; + case IL_NVIDIA_COMPRESS: + return ilStates[ilCurrentPos].ilUseNVidiaDXT; + case IL_SQUISH_COMPRESS: + return ilStates[ilCurrentPos].ilUseSquishDXT; + + default: + ilSetError(IL_INVALID_ENUM); + } + + return IL_FALSE; +} + + +//! Checks whether the mode is disabled. +ILboolean ILAPIENTRY ilIsDisabled(ILenum Mode) +{ + return !ilIsEnabled(Mode); +} + + +//! Sets Param equal to the current value of the Mode +void ILAPIENTRY ilGetBooleanv(ILenum Mode, ILboolean *Param) +{ + if (Param == NULL) { + ilSetError(IL_INVALID_PARAM); + return; + } + + *Param = ilGetInteger(Mode); + + return; +} + + +//! Returns the current value of the Mode +ILboolean ILAPIENTRY ilGetBoolean(ILenum Mode) +{ + ILboolean Temp; + Temp = IL_FALSE; + ilGetBooleanv(Mode, &Temp); + return Temp; +} + + +ILimage *iGetBaseImage(void); + +//! Internal function to figure out where we are in an image chain. +//@TODO: This may get much more complex with mipmaps under faces, etc. +ILuint iGetActiveNum(ILenum Type) +{ + ILimage *BaseImage; + ILuint Num = 0; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return 0; + } + + BaseImage = iGetBaseImage(); + if (BaseImage == iCurImage) + return 0; + + switch (Type) + { + case IL_ACTIVE_IMAGE: + BaseImage = BaseImage->Next; + do { + if (BaseImage == NULL) + return 0; + Num++; + if (BaseImage == iCurImage) + return Num; + } while ((BaseImage = BaseImage->Next)); + break; + case IL_ACTIVE_MIPMAP: + BaseImage = BaseImage->Mipmaps; + do { + if (BaseImage == NULL) + return 0; + Num++; + if (BaseImage == iCurImage) + return Num; + } while ((BaseImage = BaseImage->Mipmaps)); + break; + case IL_ACTIVE_LAYER: + BaseImage = BaseImage->Layers; + do { + if (BaseImage == NULL) + return 0; + Num++; + if (BaseImage == iCurImage) + return Num; + } while ((BaseImage = BaseImage->Layers)); + break; + case IL_ACTIVE_FACE: + BaseImage = BaseImage->Faces; + do { + if (BaseImage == NULL) + return 0; + Num++; + if (BaseImage == iCurImage) + return Num; + } while ((BaseImage = BaseImage->Faces)); + break; + } + + //@TODO: Any error needed here? + + return 0; +} + + +//! Sets Param equal to the current value of the Mode +void ILAPIENTRY ilGetIntegerv(ILenum Mode, ILint *Param) +{ + if (Param == NULL) { + ilSetError(IL_INVALID_PARAM); + return; + } + + *Param = 0; + + switch (Mode) { + // Integer values + case IL_COMPRESS_MODE: + *Param = ilStates[ilCurrentPos].ilCompression; + break; + case IL_CUR_IMAGE: + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + break; + } + *Param = ilGetCurName(); + break; + case IL_FORMAT_MODE: + *Param = ilStates[ilCurrentPos].ilFormatMode; + break; + case IL_INTERLACE_MODE: + *Param = ilStates[ilCurrentPos].ilInterlace; + break; + case IL_KEEP_DXTC_DATA: + *Param = ilStates[ilCurrentPos].ilKeepDxtcData; + break; + case IL_ORIGIN_MODE: + *Param = ilStates[ilCurrentPos].ilOriginMode; + break; + case IL_MAX_QUANT_INDICES: + *Param = ilStates[ilCurrentPos].ilQuantMaxIndexs; + break; + case IL_NEU_QUANT_SAMPLE: + *Param = ilStates[ilCurrentPos].ilNeuSample; + break; + case IL_QUANTIZATION_MODE: + *Param = ilStates[ilCurrentPos].ilQuantMode; + break; + case IL_TYPE_MODE: + *Param = ilStates[ilCurrentPos].ilTypeMode; + break; + case IL_VERSION_NUM: + *Param = IL_VERSION; + break; + + // Image specific values + case IL_ACTIVE_IMAGE: + case IL_ACTIVE_MIPMAP: + case IL_ACTIVE_LAYER: + *Param = iGetActiveNum(Mode); + break; + + // Format-specific values + case IL_BMP_RLE: + *Param = ilStates[ilCurrentPos].ilBmpRle; + break; + case IL_DXTC_FORMAT: + *Param = ilStates[ilCurrentPos].ilDxtcFormat; + break; + case IL_JPG_QUALITY: + *Param = ilStates[ilCurrentPos].ilJpgQuality; + break; + case IL_JPG_SAVE_FORMAT: + *Param = ilStates[ilCurrentPos].ilJpgFormat; + break; + case IL_PCD_PICNUM: + *Param = ilStates[ilCurrentPos].ilPcdPicNum; + break; + case IL_PNG_ALPHA_INDEX: + *Param = ilStates[ilCurrentPos].ilPngAlphaIndex; + break; + case IL_PNG_INTERLACE: + *Param = ilStates[ilCurrentPos].ilPngInterlace; + break; + case IL_SGI_RLE: + *Param = ilStates[ilCurrentPos].ilSgiRle; + break; + case IL_TGA_CREATE_STAMP: + *Param = ilStates[ilCurrentPos].ilTgaCreateStamp; + break; + case IL_TGA_RLE: + *Param = ilStates[ilCurrentPos].ilTgaRle; + break; + case IL_VTF_COMP: + *Param = ilStates[ilCurrentPos].ilVtfCompression; + break; + + // Boolean values + case IL_CONV_PAL: + *Param = ilStates[ilCurrentPos].ilAutoConvPal; + break; + case IL_DEFAULT_ON_FAIL: + *Param = ilStates[ilCurrentPos].ilDefaultOnFail; + break; + case IL_FILE_MODE: + *Param = ilStates[ilCurrentPos].ilOverWriteFiles; + break; + case IL_FORMAT_SET: + *Param = ilStates[ilCurrentPos].ilFormatSet; + break; + case IL_ORIGIN_SET: + *Param = ilStates[ilCurrentPos].ilOriginSet; + break; + case IL_TYPE_SET: + *Param = ilStates[ilCurrentPos].ilTypeSet; + break; + case IL_USE_KEY_COLOUR: + *Param = ilStates[ilCurrentPos].ilUseKeyColour; + break; + case IL_BLIT_BLEND: + *Param = ilStates[ilCurrentPos].ilBlitBlend; + break; + case IL_JPG_PROGRESSIVE: + *Param = ilStates[ilCurrentPos].ilJpgProgressive; + break; + case IL_NVIDIA_COMPRESS: + *Param = ilStates[ilCurrentPos].ilUseNVidiaDXT; + break; + case IL_SQUISH_COMPRESS: + *Param = ilStates[ilCurrentPos].ilUseSquishDXT; + break; + + default: + iGetIntegervImage(iCurImage, Mode, Param); + } + + return; +} + +//@TODO rename to ilGetImageIntegerv for 1.6.9 and make it public +//! Sets Param equal to the current value of the Mode +void ILAPIENTRY iGetIntegervImage(ILimage *Image, ILenum Mode, ILint *Param) +{ + ILimage *SubImage; + if (Image == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return; + } + if (Param == NULL) { + ilSetError(IL_INVALID_PARAM); + return; + } + *Param = 0; + + switch (Mode) + { + case IL_DXTC_DATA_FORMAT: + if (Image->DxtcData == NULL || Image->DxtcSize == 0) { + *Param = IL_DXT_NO_COMP; + break; + } + *Param = Image->DxtcFormat; + break; + //// + case IL_IMAGE_BITS_PER_PIXEL: + //changed 20040610 to channel count (Bpp) times Bytes per channel + *Param = (Image->Bpp << 3)*Image->Bpc; + break; + case IL_IMAGE_BYTES_PER_PIXEL: + //changed 20040610 to channel count (Bpp) times Bytes per channel + *Param = Image->Bpp*Image->Bpc; + break; + case IL_IMAGE_BPC: + *Param = Image->Bpc; + break; + case IL_IMAGE_CHANNELS: + *Param = Image->Bpp; + break; + case IL_IMAGE_CUBEFLAGS: + *Param = Image->CubeFlags; + break; + case IL_IMAGE_DEPTH: + *Param = Image->Depth; + break; + case IL_IMAGE_DURATION: + *Param = Image->Duration; + break; + case IL_IMAGE_FORMAT: + *Param = Image->Format; + break; + case IL_IMAGE_HEIGHT: + *Param = Image->Height; + break; + case IL_IMAGE_SIZE_OF_DATA: + *Param = Image->SizeOfData; + + break; + case IL_IMAGE_OFFX: + *Param = Image->OffX; + break; + case IL_IMAGE_OFFY: + *Param = Image->OffY; + break; + case IL_IMAGE_ORIGIN: + *Param = Image->Origin; + break; + case IL_IMAGE_PLANESIZE: + *Param = Image->SizeOfPlane; + break; + case IL_IMAGE_TYPE: + *Param = Image->Type; + break; + case IL_IMAGE_WIDTH: + *Param = Image->Width; + break; + case IL_NUM_FACES: + for (SubImage = Image->Faces; SubImage; SubImage = SubImage->Faces) + (*Param)++; + break; + case IL_NUM_IMAGES: + for (SubImage = Image->Next; SubImage; SubImage = SubImage->Next) + (*Param)++; + break; + case IL_NUM_LAYERS: + for (SubImage = Image->Layers; SubImage; SubImage = SubImage->Layers) + (*Param)++; + break; + case IL_NUM_MIPMAPS: + for (SubImage = Image->Mipmaps; SubImage; SubImage = SubImage->Mipmaps) + (*Param)++; + break; + + case IL_PALETTE_TYPE: + *Param = Image->Pal.PalType; + break; + case IL_PALETTE_BPP: + *Param = ilGetBppPal(Image->Pal.PalType); + break; + case IL_PALETTE_NUM_COLS: + if (!Image->Pal.Palette || !Image->Pal.PalSize || Image->Pal.PalType == IL_PAL_NONE) + *Param = 0; + else + *Param = Image->Pal.PalSize / ilGetBppPal(Image->Pal.PalType); + break; + case IL_PALETTE_BASE_TYPE: + switch (Image->Pal.PalType) + { + case IL_PAL_RGB24: + *Param = IL_RGB; + case IL_PAL_RGB32: + *Param = IL_RGBA; // Not sure + case IL_PAL_RGBA32: + *Param = IL_RGBA; + case IL_PAL_BGR24: + *Param = IL_BGR; + case IL_PAL_BGR32: + *Param = IL_BGRA; // Not sure + case IL_PAL_BGRA32: + *Param = IL_BGRA; + } + break; + default: + ilSetError(IL_INVALID_ENUM); + } +} + + + +//! Returns the current value of the Mode +ILint ILAPIENTRY ilGetInteger(ILenum Mode) +{ + ILint Temp; + Temp = 0; + ilGetIntegerv(Mode, &Temp); + return Temp; +} + + +//! Sets the default origin to be used. +ILboolean ILAPIENTRY ilOriginFunc(ILenum Mode) +{ + switch (Mode) + { + case IL_ORIGIN_LOWER_LEFT: + case IL_ORIGIN_UPPER_LEFT: + ilStates[ilCurrentPos].ilOriginMode = Mode; + break; + default: + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + return IL_TRUE; +} + + +//! Sets the default format to be used. +ILboolean ILAPIENTRY ilFormatFunc(ILenum Mode) +{ + switch (Mode) + { + //case IL_COLOUR_INDEX: + case IL_RGB: + case IL_RGBA: + case IL_BGR: + case IL_BGRA: + case IL_LUMINANCE: + case IL_LUMINANCE_ALPHA: + ilStates[ilCurrentPos].ilFormatMode = Mode; + break; + default: + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + return IL_TRUE; +} + + +//! Sets the default type to be used. +ILboolean ILAPIENTRY ilTypeFunc(ILenum Mode) +{ + switch (Mode) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + case IL_SHORT: + case IL_UNSIGNED_SHORT: + case IL_INT: + case IL_UNSIGNED_INT: + case IL_FLOAT: + case IL_DOUBLE: + ilStates[ilCurrentPos].ilTypeMode = Mode; + break; + default: + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + return IL_TRUE; +} + + +ILboolean ILAPIENTRY ilCompressFunc(ILenum Mode) +{ + switch (Mode) + { + case IL_COMPRESS_NONE: + case IL_COMPRESS_RLE: + //case IL_COMPRESS_LZO: + case IL_COMPRESS_ZLIB: + ilStates[ilCurrentPos].ilCompression = Mode; + break; + default: + ilSetError(IL_INVALID_PARAM); + return IL_FALSE; + } + return IL_TRUE; +} + + +//! Pushes the states indicated by Bits onto the state stack +void ILAPIENTRY ilPushAttrib(ILuint Bits) +{ + // Should we check here to see if ilCurrentPos is negative? + + if (ilCurrentPos >= IL_ATTRIB_STACK_MAX - 1) { + ilCurrentPos = IL_ATTRIB_STACK_MAX - 1; + ilSetError(IL_STACK_OVERFLOW); + return; + } + + ilCurrentPos++; + + // memcpy(&ilStates[ilCurrentPos], &ilStates[ilCurrentPos - 1], sizeof(IL_STATES)); + + ilDefaultStates(); + + if (Bits & IL_ORIGIN_BIT) { + ilStates[ilCurrentPos].ilOriginMode = ilStates[ilCurrentPos-1].ilOriginMode; + ilStates[ilCurrentPos].ilOriginSet = ilStates[ilCurrentPos-1].ilOriginSet; + } + if (Bits & IL_FORMAT_BIT) { + ilStates[ilCurrentPos].ilFormatMode = ilStates[ilCurrentPos-1].ilFormatMode; + ilStates[ilCurrentPos].ilFormatSet = ilStates[ilCurrentPos-1].ilFormatSet; + } + if (Bits & IL_TYPE_BIT) { + ilStates[ilCurrentPos].ilTypeMode = ilStates[ilCurrentPos-1].ilTypeMode; + ilStates[ilCurrentPos].ilTypeSet = ilStates[ilCurrentPos-1].ilTypeSet; + } + if (Bits & IL_FILE_BIT) { + ilStates[ilCurrentPos].ilOverWriteFiles = ilStates[ilCurrentPos-1].ilOverWriteFiles; + } + if (Bits & IL_PAL_BIT) { + ilStates[ilCurrentPos].ilAutoConvPal = ilStates[ilCurrentPos-1].ilAutoConvPal; + } + if (Bits & IL_LOADFAIL_BIT) { + ilStates[ilCurrentPos].ilDefaultOnFail = ilStates[ilCurrentPos-1].ilDefaultOnFail; + } + if (Bits & IL_COMPRESS_BIT) { + ilStates[ilCurrentPos].ilCompression = ilStates[ilCurrentPos-1].ilCompression; + } + if (Bits & IL_FORMAT_SPECIFIC_BIT) { + ilStates[ilCurrentPos].ilTgaCreateStamp = ilStates[ilCurrentPos-1].ilTgaCreateStamp; + ilStates[ilCurrentPos].ilJpgQuality = ilStates[ilCurrentPos-1].ilJpgQuality; + ilStates[ilCurrentPos].ilPngInterlace = ilStates[ilCurrentPos-1].ilPngInterlace; + ilStates[ilCurrentPos].ilTgaRle = ilStates[ilCurrentPos-1].ilTgaRle; + ilStates[ilCurrentPos].ilBmpRle = ilStates[ilCurrentPos-1].ilBmpRle; + ilStates[ilCurrentPos].ilSgiRle = ilStates[ilCurrentPos-1].ilSgiRle; + ilStates[ilCurrentPos].ilJpgFormat = ilStates[ilCurrentPos-1].ilJpgFormat; + ilStates[ilCurrentPos].ilDxtcFormat = ilStates[ilCurrentPos-1].ilDxtcFormat; + ilStates[ilCurrentPos].ilPcdPicNum = ilStates[ilCurrentPos-1].ilPcdPicNum; + + ilStates[ilCurrentPos].ilPngAlphaIndex = ilStates[ilCurrentPos-1].ilPngAlphaIndex; + + // Strings + if (ilStates[ilCurrentPos].ilTgaId) + ifree(ilStates[ilCurrentPos].ilTgaId); + if (ilStates[ilCurrentPos].ilTgaAuthName) + ifree(ilStates[ilCurrentPos].ilTgaAuthName); + if (ilStates[ilCurrentPos].ilTgaAuthComment) + ifree(ilStates[ilCurrentPos].ilTgaAuthComment); + if (ilStates[ilCurrentPos].ilPngAuthName) + ifree(ilStates[ilCurrentPos].ilPngAuthName); + if (ilStates[ilCurrentPos].ilPngTitle) + ifree(ilStates[ilCurrentPos].ilPngTitle); + if (ilStates[ilCurrentPos].ilPngDescription) + ifree(ilStates[ilCurrentPos].ilPngDescription); + + //2003-09-01: added tif strings + if (ilStates[ilCurrentPos].ilTifDescription) + ifree(ilStates[ilCurrentPos].ilTifDescription); + if (ilStates[ilCurrentPos].ilTifHostComputer) + ifree(ilStates[ilCurrentPos].ilTifHostComputer); + if (ilStates[ilCurrentPos].ilTifDocumentName) + ifree(ilStates[ilCurrentPos].ilTifDocumentName); + if (ilStates[ilCurrentPos].ilTifAuthName) + ifree(ilStates[ilCurrentPos].ilTifAuthName); + + if (ilStates[ilCurrentPos].ilCHeader) + ifree(ilStates[ilCurrentPos].ilCHeader); + + ilStates[ilCurrentPos].ilTgaId = strdup(ilStates[ilCurrentPos-1].ilTgaId); + ilStates[ilCurrentPos].ilTgaAuthName = strdup(ilStates[ilCurrentPos-1].ilTgaAuthName); + ilStates[ilCurrentPos].ilTgaAuthComment = strdup(ilStates[ilCurrentPos-1].ilTgaAuthComment); + ilStates[ilCurrentPos].ilPngAuthName = strdup(ilStates[ilCurrentPos-1].ilPngAuthName); + ilStates[ilCurrentPos].ilPngTitle = strdup(ilStates[ilCurrentPos-1].ilPngTitle); + ilStates[ilCurrentPos].ilPngDescription = strdup(ilStates[ilCurrentPos-1].ilPngDescription); + + //2003-09-01: added tif strings + ilStates[ilCurrentPos].ilTifDescription = strdup(ilStates[ilCurrentPos-1].ilTifDescription); + ilStates[ilCurrentPos].ilTifHostComputer = strdup(ilStates[ilCurrentPos-1].ilTifHostComputer); + ilStates[ilCurrentPos].ilTifDocumentName = strdup(ilStates[ilCurrentPos-1].ilTifDocumentName); + ilStates[ilCurrentPos].ilTifAuthName = strdup(ilStates[ilCurrentPos-1].ilTifAuthName); + + ilStates[ilCurrentPos].ilCHeader = strdup(ilStates[ilCurrentPos-1].ilCHeader); + } + + return; +} + + +// @TODO: Find out how this affects strings!!! + +//! Pops the last entry off the state stack into the current states +void ILAPIENTRY ilPopAttrib() +{ + if (ilCurrentPos <= 0) { + ilCurrentPos = 0; + ilSetError(IL_STACK_UNDERFLOW); + return; + } + + // Should we check here to see if ilCurrentPos is too large? + ilCurrentPos--; + + return; +} + + +//! Specifies implementation-dependent performance hints +void ILAPIENTRY ilHint(ILenum Target, ILenum Mode) +{ + switch (Target) + { + case IL_MEM_SPEED_HINT: + switch (Mode) + { + case IL_FASTEST: + ilHints.MemVsSpeedHint = Mode; + break; + case IL_LESS_MEM: + ilHints.MemVsSpeedHint = Mode; + break; + case IL_DONT_CARE: + ilHints.MemVsSpeedHint = IL_FASTEST; + break; + default: + ilSetError(IL_INVALID_ENUM); + return; + } + break; + + case IL_COMPRESSION_HINT: + switch (Mode) + { + case IL_USE_COMPRESSION: + ilHints.CompressHint = Mode; + break; + case IL_NO_COMPRESSION: + ilHints.CompressHint = Mode; + break; + case IL_DONT_CARE: + ilHints.CompressHint = IL_NO_COMPRESSION; + break; + default: + ilSetError(IL_INVALID_ENUM); + return; + } + break; + + + default: + ilSetError(IL_INVALID_ENUM); + return; + } + + return; +} + + +ILenum iGetHint(ILenum Target) +{ + switch (Target) + { + case IL_MEM_SPEED_HINT: + return ilHints.MemVsSpeedHint; + case IL_COMPRESSION_HINT: + return ilHints.CompressHint; + default: + ilSetError(IL_INTERNAL_ERROR); + return 0; + } +} + + +void ILAPIENTRY ilSetString(ILenum Mode, const char *String) +{ + if (String == NULL) { + ilSetError(IL_INVALID_PARAM); + return; + } + + switch (Mode) + { + case IL_TGA_ID_STRING: + if (ilStates[ilCurrentPos].ilTgaId) + ifree(ilStates[ilCurrentPos].ilTgaId); + ilStates[ilCurrentPos].ilTgaId = strdup(String); + break; + case IL_TGA_AUTHNAME_STRING: + if (ilStates[ilCurrentPos].ilTgaAuthName) + ifree(ilStates[ilCurrentPos].ilTgaAuthName); + ilStates[ilCurrentPos].ilTgaAuthName = strdup(String); + break; + case IL_TGA_AUTHCOMMENT_STRING: + if (ilStates[ilCurrentPos].ilTgaAuthComment) + ifree(ilStates[ilCurrentPos].ilTgaAuthComment); + ilStates[ilCurrentPos].ilTgaAuthComment = strdup(String); + break; + case IL_PNG_AUTHNAME_STRING: + if (ilStates[ilCurrentPos].ilPngAuthName) + ifree(ilStates[ilCurrentPos].ilPngAuthName); + ilStates[ilCurrentPos].ilPngAuthName = strdup(String); + break; + case IL_PNG_TITLE_STRING: + if (ilStates[ilCurrentPos].ilPngTitle) + ifree(ilStates[ilCurrentPos].ilPngTitle); + ilStates[ilCurrentPos].ilPngTitle = strdup(String); + break; + case IL_PNG_DESCRIPTION_STRING: + if (ilStates[ilCurrentPos].ilPngDescription) + ifree(ilStates[ilCurrentPos].ilPngDescription); + ilStates[ilCurrentPos].ilPngDescription = strdup(String); + break; + + //2003-09-01: added tif strings + case IL_TIF_DESCRIPTION_STRING: + if (ilStates[ilCurrentPos].ilTifDescription) + ifree(ilStates[ilCurrentPos].ilTifDescription); + ilStates[ilCurrentPos].ilTifDescription = strdup(String); + break; + case IL_TIF_HOSTCOMPUTER_STRING: + if (ilStates[ilCurrentPos].ilTifHostComputer) + ifree(ilStates[ilCurrentPos].ilTifHostComputer); + ilStates[ilCurrentPos].ilTifHostComputer = strdup(String); + break; + case IL_TIF_DOCUMENTNAME_STRING: + if (ilStates[ilCurrentPos].ilTifDocumentName) + ifree(ilStates[ilCurrentPos].ilTifDocumentName); + ilStates[ilCurrentPos].ilTifDocumentName = strdup(String); + break; + case IL_TIF_AUTHNAME_STRING: + if (ilStates[ilCurrentPos].ilTifAuthName) + ifree(ilStates[ilCurrentPos].ilTifAuthName); + ilStates[ilCurrentPos].ilTifAuthName = strdup(String); + break; + + case IL_CHEAD_HEADER_STRING: + if (ilStates[ilCurrentPos].ilCHeader) + ifree(ilStates[ilCurrentPos].ilCHeader); + ilStates[ilCurrentPos].ilCHeader = strdup(String); + break; + + default: + ilSetError(IL_INVALID_ENUM); + } + + return; +} + + +void ILAPIENTRY ilSetInteger(ILenum Mode, ILint Param) +{ + switch (Mode) + { + // Integer values + case IL_FORMAT_MODE: + ilFormatFunc(Param); + return; + case IL_KEEP_DXTC_DATA: + if (Param == IL_FALSE || Param == IL_TRUE) { + ilStates[ilCurrentPos].ilKeepDxtcData = Param; + return; + } + break; + case IL_MAX_QUANT_INDICES: + if (Param >= 2 && Param <= 256) { + ilStates[ilCurrentPos].ilQuantMaxIndexs = Param; + return; + } + break; + case IL_NEU_QUANT_SAMPLE: + if (Param >= 1 && Param <= 30) { + ilStates[ilCurrentPos].ilNeuSample = Param; + return; + } + break; + case IL_ORIGIN_MODE: + ilOriginFunc(Param); + return; + case IL_QUANTIZATION_MODE: + if (Param == IL_WU_QUANT || Param == IL_NEU_QUANT) { + ilStates[ilCurrentPos].ilQuantMode = Param; + return; + } + break; + case IL_TYPE_MODE: + ilTypeFunc(Param); + return; + + // Image specific values + case IL_IMAGE_DURATION: + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + break; + } + iCurImage->Duration = Param; + return; + case IL_IMAGE_OFFX: + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + break; + } + iCurImage->OffX = Param; + return; + case IL_IMAGE_OFFY: + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + break; + } + iCurImage->OffY = Param; + return; + case IL_IMAGE_CUBEFLAGS: + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + break; + } + iCurImage->CubeFlags = Param; + break; + + // Format specific values + case IL_BMP_RLE: + if (Param == IL_FALSE || Param == IL_TRUE) { + ilStates[ilCurrentPos].ilBmpRle = Param; + return; + } + break; + case IL_DXTC_FORMAT: + if (Param >= IL_DXT1 || Param <= IL_DXT5 || Param == IL_DXT1A) { + ilStates[ilCurrentPos].ilDxtcFormat = Param; + return; + } + break; + case IL_JPG_SAVE_FORMAT: + if (Param == IL_JFIF || Param == IL_EXIF) { + ilStates[ilCurrentPos].ilJpgFormat = Param; + return; + } + break; + case IL_JPG_QUALITY: + if (Param >= 0 && Param <= 99) { + ilStates[ilCurrentPos].ilJpgQuality = Param; + return; + } + break; + case IL_PNG_INTERLACE: + if (Param == IL_FALSE || Param == IL_TRUE) { + ilStates[ilCurrentPos].ilPngInterlace = Param; + return; + } + break; + case IL_PCD_PICNUM: + if (Param >= 0 || Param <= 2) { + ilStates[ilCurrentPos].ilPcdPicNum = Param; + return; + } + break; + case IL_PNG_ALPHA_INDEX: + if (Param >= -1 || Param <= 255) { + ilStates[ilCurrentPos].ilPngAlphaIndex=Param; + return; + } + break; + case IL_SGI_RLE: + if (Param == IL_FALSE || Param == IL_TRUE) { + ilStates[ilCurrentPos].ilSgiRle = Param; + return; + } + break; + case IL_TGA_CREATE_STAMP: + if (Param == IL_FALSE || Param == IL_TRUE) { + ilStates[ilCurrentPos].ilTgaCreateStamp = Param; + return; + } + break; + case IL_TGA_RLE: + if (Param == IL_FALSE || Param == IL_TRUE) { + ilStates[ilCurrentPos].ilTgaRle = Param; + return; + } + break; + case IL_VTF_COMP: + if (Param == IL_DXT1 || Param == IL_DXT5 || Param == IL_DXT3 || Param == IL_DXT1A || Param == IL_DXT_NO_COMP) { + ilStates[ilCurrentPos].ilVtfCompression = Param; + return; + } + break; + + default: + ilSetError(IL_INVALID_ENUM); + return; + } + + ilSetError(IL_INVALID_PARAM); // Parameter not in valid bounds. + return; +} + + + +ILint iGetInt(ILenum Mode) +{ + //like ilGetInteger(), but sets another error on failure + + //call ilGetIntegerv() for more robust code + ILenum err; + ILint r = -1; + + ilGetIntegerv(Mode, &r); + + //check if an error occured, set another error + err = ilGetError(); + if (r == -1 && err == IL_INVALID_ENUM) + ilSetError(IL_INTERNAL_ERROR); + else + ilSetError(err); //restore error + + return r; +} diff --git a/DevIL/src-IL/src/il_sun.c b/DevIL/src-IL/src/il_sun.c deleted file mode 100644 index 62009034..00000000 --- a/DevIL/src-IL/src/il_sun.c +++ /dev/null @@ -1,398 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 01/06/2009 -// -// Filename: src-IL/src/il_sun.c -// -// Description: Reads from a Sun RAS file. Specifications available from -// http://www.fileformat.info/format/sunraster/egff.htm. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_SUN -#include "il_bits.h" - -ILboolean iLoadSunInternal(void); -ILboolean iIsValidSun(void); -ILuint iSunGetRle(ILubyte *Data, ILuint Length); - -typedef struct SUNHEAD -{ - ILuint MagicNumber; // Magic (identification) number - ILuint Width; // Width of image in pixels - ILuint Height; // Height of image in pixels - ILuint Depth; // Number of bits per pixel - ILuint Length; // Size of image data in bytes - ILuint Type; // Type of raster file - ILuint ColorMapType; // Type of color map - ILuint ColorMapLength; // Size of the color map in bytes -} SUNHEAD; - -// Data storage types -#define IL_SUN_OLD 0x00 -#define IL_SUN_STANDARD 0x01 -#define IL_SUN_BYTE_ENC 0x02 -#define IL_SUN_RGB 0x03 -#define IL_SUN_TIFF 0x04 -#define IL_SUN_IFF 0x05 -#define IL_SUN_EXPER 0xFFFF // Experimental, not supported. - -// Colormap types -#define IL_SUN_NO_MAP 0x00 -#define IL_SUN_RGB_MAP 0x01 -#define IL_SUN_RAW_MAP 0x02 - - -//! Checks if the file specified in FileName is a valid Sun file. -ILboolean ilIsValidSun(ILconst_string FileName) -{ - ILHANDLE SunFile; - ILboolean bSun = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("sun")) && !iCheckExtension(FileName, IL_TEXT("ras")) && - !iCheckExtension(FileName, IL_TEXT("im1")) && !iCheckExtension(FileName, IL_TEXT("im8")) && - !iCheckExtension(FileName, IL_TEXT("im24")) && !iCheckExtension(FileName, IL_TEXT("im32")) && - !iCheckExtension(FileName, IL_TEXT("rs"))) { // Lots of names possible... - ilSetError(IL_INVALID_EXTENSION); - return bSun; - } - - SunFile = iopenr(FileName); - if (SunFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bSun; - } - - bSun = ilIsValidSunF(SunFile); - icloser(SunFile); - - return bSun; -} - - -//! Checks if the ILHANDLE contains a valid Sun file at the current position. -ILboolean ilIsValidSunF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidSun(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid Sun lump. -ILboolean ilIsValidSunL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidSun(); -} - - -// Internal function used to get the Sun header from the current file. -ILboolean iGetSunHead(SUNHEAD *Header) -{ - Header->MagicNumber = GetBigUInt(); - Header->Width = GetBigUInt(); - Header->Height = GetBigUInt(); - Header->Depth = GetBigUInt(); - Header->Length = GetBigUInt(); - Header->Type = GetBigUInt(); - Header->ColorMapType = GetBigUInt(); - Header->ColorMapLength = GetBigUInt(); - - return IL_TRUE; -} - - -// Internal function used to check if the HEADER is a valid SUN header. -ILboolean iCheckSun(SUNHEAD *Header) -{ - if (Header->MagicNumber != 0x59A66A95) // Magic number is always 0x59A66A95. - return IL_FALSE; - if (Header->Width == 0 || Header->Height == 0) // 0 dimensions are meaningless. - return IL_FALSE; - // These are the only valid depths that I know of. - if (Header->Depth != 1 && Header->Depth != 8 && Header->Depth != 24 && Header->Depth != 32) - return IL_FALSE; - if (Header->Type > IL_SUN_RGB) //@TODO: Support further types. - return IL_FALSE; - if (Header->ColorMapType > IL_SUN_RGB_MAP) //@TODO: Find out more about raw map. - return IL_FALSE; - // Color map cannot be 0 if there is a map indicated. - if (Header->ColorMapType > IL_SUN_NO_MAP && Header->ColorMapLength == 0) - return IL_FALSE; - //@TODO: These wouldn't make sense. Are they valid somehow? Find out... - if ((Header->Depth == 1 || Header->Depth == 32) && Header->Type == IL_SUN_BYTE_ENC) - return IL_FALSE; - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidSun() -{ - SUNHEAD Head; - - if (!iGetSunHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(SUNHEAD), IL_SEEK_CUR); - - return iCheckSun(&Head); -} - - -// Reads a Sun file -ILboolean ilLoadSun(ILconst_string FileName) -{ - ILHANDLE SunFile; - ILboolean bSun = IL_FALSE; - - SunFile = iopenr(FileName); - if (SunFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bSun; - } - - iSetInputFile(SunFile); - - bSun = ilLoadSunF(SunFile); - - icloser(SunFile); - - return bSun; -} - - -//! Reads an already-opened Sun file -ILboolean ilLoadSunF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadSunInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Sun -ILboolean ilLoadSunL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadSunInternal(); -} - - -ILboolean iLoadSunInternal(void) -{ - SUNHEAD Header; - BITFILE *File; - ILuint i, j, Padding, Offset, BytesRead; - ILubyte PaddingData[16]; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - //@TODO: Right now, iGetSunHead cannot fail. - if (!iGetSunHead(&Header) || !iCheckSun(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - switch (Header.Depth) - { - case 1: //@TODO: Find a file to test this on. - File = bfile(iGetFile()); - if (File == NULL) - return IL_FALSE; - - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - if (Header.ColorMapLength != 0) { - // Data should be an index into the color map, but the color map should only be RGB (6 bytes, 2 entries). - if (Header.ColorMapLength != 6) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - } - iCurImage->Pal.Palette = (ILubyte*)ialloc(6); // Just need 2 entries in the color map. - if (Header.ColorMapLength == 0) { // Create the color map - iCurImage->Pal.Palette[0] = 0x00; // Entry for black - iCurImage->Pal.Palette[1] = 0x00; - iCurImage->Pal.Palette[2] = 0x00; - iCurImage->Pal.Palette[3] = 0xFF; // Entry for white - iCurImage->Pal.Palette[4] = 0xFF; - iCurImage->Pal.Palette[5] = 0xFF; - } - else { - iread(iCurImage->Pal.Palette, 1, 6); // Read in the color map. - } - iCurImage->Pal.PalSize = 6; - iCurImage->Pal.PalType = IL_PAL_RGB24; - - Padding = (16 - (iCurImage->Width % 16)) % 16; // Has to be aligned on a 16-bit boundary. The rest is padding. - - // Reads the bits - for (i = 0; i < iCurImage->Height; i++) { - bread(&iCurImage->Data[iCurImage->Width * i], 1, iCurImage->Width, File); - //bseek(File, BitPadding, IL_SEEK_CUR); //@TODO: This function does not work correctly. - bread(PaddingData, 1, Padding, File); // Skip padding bits. - } - break; - - - case 8: - if (Header.ColorMapType == IL_SUN_NO_MAP) { // Greyscale image - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - else { // Colour-mapped image - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Pal.Palette = (ILubyte*)ialloc(Header.ColorMapLength); // Allocate color map. - if (iCurImage->Pal.Palette == NULL) - return IL_FALSE; - if (iread(iCurImage->Pal.Palette, 1, Header.ColorMapLength) != Header.ColorMapLength) { // Read color map. - ilSetError(IL_FILE_READ_ERROR); - return IL_FALSE; - } - - iCurImage->Pal.PalSize = Header.ColorMapLength; - iCurImage->Pal.PalType = IL_PAL_RGB24; - } - - if (Header.Type != IL_SUN_BYTE_ENC) { // Regular uncompressed image data - Padding = (2 - (iCurImage->Bps % 2)) % 2; // Must be padded on a 16-bit boundary (2 bytes) - for (i = 0; i < Header.Height; i++) { - iread(iCurImage->Data + i * Header.Width, 1, iCurImage->Bps); - if (Padding) // Only possible for padding to be 0 or 1. - igetc(); - } - } - else { // RLE image data - for (i = 0; i < iCurImage->Height; i++) { - BytesRead = iSunGetRle(iCurImage->Data + iCurImage->Bps * i, iCurImage->Bps); - if (BytesRead % 2) // Each scanline must be aligned on a 2-byte boundary. - igetc(); // Skip padding - } - } - break; - - case 24: - if (Header.ColorMapLength > 0) // Ignore any possible colormaps. - iseek(Header.ColorMapLength, IL_SEEK_CUR); - - if (Header.Type == IL_SUN_RGB) { - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - else { - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - - if (Header.Type != IL_SUN_BYTE_ENC) { // Regular uncompressed image data - Padding = (2 - (iCurImage->Bps % 2)) % 2; // Must be padded on a 16-bit boundary (2 bytes) - for (i = 0; i < Header.Height; i++) { - iread(iCurImage->Data + i * Header.Width * 3, 1, iCurImage->Bps); - if (Padding) // Only possible for padding to be 0 or 1. - igetc(); - } - } - else { // RLE image data - for (i = 0; i < iCurImage->Height; i++) { - BytesRead = iSunGetRle(iCurImage->Data + iCurImage->Bps * i, iCurImage->Bps); - if (BytesRead % 2) // Each scanline must be aligned on a 2-byte boundary. - igetc(); // Skip padding - } - } - - break; - - case 32: - if (Header.ColorMapLength > 0) // Ignore any possible colormaps. - iseek(Header.ColorMapLength, IL_SEEK_CUR); - - if (Header.Type == IL_SUN_RGB) { - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - else { - if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - - // There is no padding at the end of each scanline. - Offset = 0; - for (i = 0; i < Header.Height; i++) { - for (j = 0; j < Header.Width; j++) { - igetc(); // There is a pad byte before each pixel. - iCurImage->Data[Offset] = igetc(); - iCurImage->Data[Offset+1] = igetc(); - iCurImage->Data[Offset+2] = igetc(); - } - } - break; - - - default: // Should have already been checked with iGetSunHead. - return IL_FALSE; - } - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - return ilFixImage(); -} - - -ILuint iSunGetRle(ILubyte *Data, ILuint Length) -{ - ILuint i = 0, j; - ILubyte Flag, Value; - ILuint Count; - - for (i = 0; i < Length; ) { - Flag = igetc(); - if (Flag == 0x80) { // Run follows (or 1 byte of 0x80) - Count = igetc(); - if (Count == 0) { // 1 pixel of value (0x80) - *Data = 0x80; - Data++; - i++; - } - else { // Here we have a run. - Value = igetc(); - Count++; // Should really be Count+1 - for (j = 0; j < Count && i + j < Length; j++, Data++) { - *Data = Value; - } - i += Count; - } - } - else { // 1 byte of this value (cannot be 0x80) - *Data = Flag; - Data++; - i++; - } - } - - return i; -} - - -#endif//IL_NO_SUN - diff --git a/DevIL/src-IL/src/il_sun.cpp b/DevIL/src-IL/src/il_sun.cpp new file mode 100644 index 00000000..62009034 --- /dev/null +++ b/DevIL/src-IL/src/il_sun.cpp @@ -0,0 +1,398 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 01/06/2009 +// +// Filename: src-IL/src/il_sun.c +// +// Description: Reads from a Sun RAS file. Specifications available from +// http://www.fileformat.info/format/sunraster/egff.htm. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_SUN +#include "il_bits.h" + +ILboolean iLoadSunInternal(void); +ILboolean iIsValidSun(void); +ILuint iSunGetRle(ILubyte *Data, ILuint Length); + +typedef struct SUNHEAD +{ + ILuint MagicNumber; // Magic (identification) number + ILuint Width; // Width of image in pixels + ILuint Height; // Height of image in pixels + ILuint Depth; // Number of bits per pixel + ILuint Length; // Size of image data in bytes + ILuint Type; // Type of raster file + ILuint ColorMapType; // Type of color map + ILuint ColorMapLength; // Size of the color map in bytes +} SUNHEAD; + +// Data storage types +#define IL_SUN_OLD 0x00 +#define IL_SUN_STANDARD 0x01 +#define IL_SUN_BYTE_ENC 0x02 +#define IL_SUN_RGB 0x03 +#define IL_SUN_TIFF 0x04 +#define IL_SUN_IFF 0x05 +#define IL_SUN_EXPER 0xFFFF // Experimental, not supported. + +// Colormap types +#define IL_SUN_NO_MAP 0x00 +#define IL_SUN_RGB_MAP 0x01 +#define IL_SUN_RAW_MAP 0x02 + + +//! Checks if the file specified in FileName is a valid Sun file. +ILboolean ilIsValidSun(ILconst_string FileName) +{ + ILHANDLE SunFile; + ILboolean bSun = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("sun")) && !iCheckExtension(FileName, IL_TEXT("ras")) && + !iCheckExtension(FileName, IL_TEXT("im1")) && !iCheckExtension(FileName, IL_TEXT("im8")) && + !iCheckExtension(FileName, IL_TEXT("im24")) && !iCheckExtension(FileName, IL_TEXT("im32")) && + !iCheckExtension(FileName, IL_TEXT("rs"))) { // Lots of names possible... + ilSetError(IL_INVALID_EXTENSION); + return bSun; + } + + SunFile = iopenr(FileName); + if (SunFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bSun; + } + + bSun = ilIsValidSunF(SunFile); + icloser(SunFile); + + return bSun; +} + + +//! Checks if the ILHANDLE contains a valid Sun file at the current position. +ILboolean ilIsValidSunF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidSun(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid Sun lump. +ILboolean ilIsValidSunL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidSun(); +} + + +// Internal function used to get the Sun header from the current file. +ILboolean iGetSunHead(SUNHEAD *Header) +{ + Header->MagicNumber = GetBigUInt(); + Header->Width = GetBigUInt(); + Header->Height = GetBigUInt(); + Header->Depth = GetBigUInt(); + Header->Length = GetBigUInt(); + Header->Type = GetBigUInt(); + Header->ColorMapType = GetBigUInt(); + Header->ColorMapLength = GetBigUInt(); + + return IL_TRUE; +} + + +// Internal function used to check if the HEADER is a valid SUN header. +ILboolean iCheckSun(SUNHEAD *Header) +{ + if (Header->MagicNumber != 0x59A66A95) // Magic number is always 0x59A66A95. + return IL_FALSE; + if (Header->Width == 0 || Header->Height == 0) // 0 dimensions are meaningless. + return IL_FALSE; + // These are the only valid depths that I know of. + if (Header->Depth != 1 && Header->Depth != 8 && Header->Depth != 24 && Header->Depth != 32) + return IL_FALSE; + if (Header->Type > IL_SUN_RGB) //@TODO: Support further types. + return IL_FALSE; + if (Header->ColorMapType > IL_SUN_RGB_MAP) //@TODO: Find out more about raw map. + return IL_FALSE; + // Color map cannot be 0 if there is a map indicated. + if (Header->ColorMapType > IL_SUN_NO_MAP && Header->ColorMapLength == 0) + return IL_FALSE; + //@TODO: These wouldn't make sense. Are they valid somehow? Find out... + if ((Header->Depth == 1 || Header->Depth == 32) && Header->Type == IL_SUN_BYTE_ENC) + return IL_FALSE; + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidSun() +{ + SUNHEAD Head; + + if (!iGetSunHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(SUNHEAD), IL_SEEK_CUR); + + return iCheckSun(&Head); +} + + +// Reads a Sun file +ILboolean ilLoadSun(ILconst_string FileName) +{ + ILHANDLE SunFile; + ILboolean bSun = IL_FALSE; + + SunFile = iopenr(FileName); + if (SunFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bSun; + } + + iSetInputFile(SunFile); + + bSun = ilLoadSunF(SunFile); + + icloser(SunFile); + + return bSun; +} + + +//! Reads an already-opened Sun file +ILboolean ilLoadSunF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadSunInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Sun +ILboolean ilLoadSunL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadSunInternal(); +} + + +ILboolean iLoadSunInternal(void) +{ + SUNHEAD Header; + BITFILE *File; + ILuint i, j, Padding, Offset, BytesRead; + ILubyte PaddingData[16]; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + //@TODO: Right now, iGetSunHead cannot fail. + if (!iGetSunHead(&Header) || !iCheckSun(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + switch (Header.Depth) + { + case 1: //@TODO: Find a file to test this on. + File = bfile(iGetFile()); + if (File == NULL) + return IL_FALSE; + + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + if (Header.ColorMapLength != 0) { + // Data should be an index into the color map, but the color map should only be RGB (6 bytes, 2 entries). + if (Header.ColorMapLength != 6) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + } + iCurImage->Pal.Palette = (ILubyte*)ialloc(6); // Just need 2 entries in the color map. + if (Header.ColorMapLength == 0) { // Create the color map + iCurImage->Pal.Palette[0] = 0x00; // Entry for black + iCurImage->Pal.Palette[1] = 0x00; + iCurImage->Pal.Palette[2] = 0x00; + iCurImage->Pal.Palette[3] = 0xFF; // Entry for white + iCurImage->Pal.Palette[4] = 0xFF; + iCurImage->Pal.Palette[5] = 0xFF; + } + else { + iread(iCurImage->Pal.Palette, 1, 6); // Read in the color map. + } + iCurImage->Pal.PalSize = 6; + iCurImage->Pal.PalType = IL_PAL_RGB24; + + Padding = (16 - (iCurImage->Width % 16)) % 16; // Has to be aligned on a 16-bit boundary. The rest is padding. + + // Reads the bits + for (i = 0; i < iCurImage->Height; i++) { + bread(&iCurImage->Data[iCurImage->Width * i], 1, iCurImage->Width, File); + //bseek(File, BitPadding, IL_SEEK_CUR); //@TODO: This function does not work correctly. + bread(PaddingData, 1, Padding, File); // Skip padding bits. + } + break; + + + case 8: + if (Header.ColorMapType == IL_SUN_NO_MAP) { // Greyscale image + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + else { // Colour-mapped image + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Pal.Palette = (ILubyte*)ialloc(Header.ColorMapLength); // Allocate color map. + if (iCurImage->Pal.Palette == NULL) + return IL_FALSE; + if (iread(iCurImage->Pal.Palette, 1, Header.ColorMapLength) != Header.ColorMapLength) { // Read color map. + ilSetError(IL_FILE_READ_ERROR); + return IL_FALSE; + } + + iCurImage->Pal.PalSize = Header.ColorMapLength; + iCurImage->Pal.PalType = IL_PAL_RGB24; + } + + if (Header.Type != IL_SUN_BYTE_ENC) { // Regular uncompressed image data + Padding = (2 - (iCurImage->Bps % 2)) % 2; // Must be padded on a 16-bit boundary (2 bytes) + for (i = 0; i < Header.Height; i++) { + iread(iCurImage->Data + i * Header.Width, 1, iCurImage->Bps); + if (Padding) // Only possible for padding to be 0 or 1. + igetc(); + } + } + else { // RLE image data + for (i = 0; i < iCurImage->Height; i++) { + BytesRead = iSunGetRle(iCurImage->Data + iCurImage->Bps * i, iCurImage->Bps); + if (BytesRead % 2) // Each scanline must be aligned on a 2-byte boundary. + igetc(); // Skip padding + } + } + break; + + case 24: + if (Header.ColorMapLength > 0) // Ignore any possible colormaps. + iseek(Header.ColorMapLength, IL_SEEK_CUR); + + if (Header.Type == IL_SUN_RGB) { + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + else { + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + + if (Header.Type != IL_SUN_BYTE_ENC) { // Regular uncompressed image data + Padding = (2 - (iCurImage->Bps % 2)) % 2; // Must be padded on a 16-bit boundary (2 bytes) + for (i = 0; i < Header.Height; i++) { + iread(iCurImage->Data + i * Header.Width * 3, 1, iCurImage->Bps); + if (Padding) // Only possible for padding to be 0 or 1. + igetc(); + } + } + else { // RLE image data + for (i = 0; i < iCurImage->Height; i++) { + BytesRead = iSunGetRle(iCurImage->Data + iCurImage->Bps * i, iCurImage->Bps); + if (BytesRead % 2) // Each scanline must be aligned on a 2-byte boundary. + igetc(); // Skip padding + } + } + + break; + + case 32: + if (Header.ColorMapLength > 0) // Ignore any possible colormaps. + iseek(Header.ColorMapLength, IL_SEEK_CUR); + + if (Header.Type == IL_SUN_RGB) { + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + else { + if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + + // There is no padding at the end of each scanline. + Offset = 0; + for (i = 0; i < Header.Height; i++) { + for (j = 0; j < Header.Width; j++) { + igetc(); // There is a pad byte before each pixel. + iCurImage->Data[Offset] = igetc(); + iCurImage->Data[Offset+1] = igetc(); + iCurImage->Data[Offset+2] = igetc(); + } + } + break; + + + default: // Should have already been checked with iGetSunHead. + return IL_FALSE; + } + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + return ilFixImage(); +} + + +ILuint iSunGetRle(ILubyte *Data, ILuint Length) +{ + ILuint i = 0, j; + ILubyte Flag, Value; + ILuint Count; + + for (i = 0; i < Length; ) { + Flag = igetc(); + if (Flag == 0x80) { // Run follows (or 1 byte of 0x80) + Count = igetc(); + if (Count == 0) { // 1 pixel of value (0x80) + *Data = 0x80; + Data++; + i++; + } + else { // Here we have a run. + Value = igetc(); + Count++; // Should really be Count+1 + for (j = 0; j < Count && i + j < Length; j++, Data++) { + *Data = Value; + } + i += Count; + } + } + else { // 1 byte of this value (cannot be 0x80) + *Data = Flag; + Data++; + i++; + } + } + + return i; +} + + +#endif//IL_NO_SUN + diff --git a/DevIL/src-IL/src/il_targa.c b/DevIL/src-IL/src/il_targa.c deleted file mode 100644 index 55b4070f..00000000 --- a/DevIL/src-IL/src/il_targa.c +++ /dev/null @@ -1,961 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_targa.c -// -// Description: Reads from and writes to a Targa (.tga) file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_TGA -#include "il_targa.h" -//#include // for ilMakeString() -#include -#include "il_bits.h" - -#ifdef DJGPP -#include -#endif - - -//! Checks if the file specified in FileName is a valid Targa file. -ILboolean ilIsValidTga(ILconst_string FileName) -{ - ILHANDLE TargaFile; - ILboolean bTarga = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("tga")) && - !iCheckExtension(FileName, IL_TEXT("vda")) && - !iCheckExtension(FileName, IL_TEXT("icb")) && - !iCheckExtension(FileName, IL_TEXT("vst"))) { - ilSetError(IL_INVALID_EXTENSION); - return bTarga; - } - - TargaFile = iopenr(FileName); - if (TargaFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bTarga; - } - - bTarga = ilIsValidTgaF(TargaFile); - icloser(TargaFile); - - return bTarga; -} - - -//! Checks if the ILHANDLE contains a valid Targa file at the current position. -ILboolean ilIsValidTgaF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidTarga(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid Targa lump. -ILboolean ilIsValidTgaL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidTarga(); -} - - -// Internal function used to get the Targa header from the current file. -ILboolean iGetTgaHead(TARGAHEAD *Header) -{ - Header->IDLen = (ILubyte)igetc(); - Header->ColMapPresent = (ILubyte)igetc(); - Header->ImageType = (ILubyte)igetc(); - Header->FirstEntry = GetLittleShort(); - Header->ColMapLen = GetLittleShort(); - Header->ColMapEntSize = (ILubyte)igetc(); - - Header->OriginX = GetLittleShort(); - Header->OriginY = GetLittleShort(); - Header->Width = GetLittleUShort(); - Header->Height = GetLittleUShort(); - Header->Bpp = (ILubyte)igetc(); - Header->ImageDesc = (ILubyte)igetc(); - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidTarga() -{ - TARGAHEAD Head; - - if (!iGetTgaHead(&Head)) - return IL_FALSE; - iseek(-(ILint)sizeof(TARGAHEAD), IL_SEEK_CUR); - - return iCheckTarga(&Head); -} - - -// Internal function used to check if the HEADER is a valid Targa header. -ILboolean iCheckTarga(TARGAHEAD *Header) -{ - if (Header->Width == 0 || Header->Height == 0) - return IL_FALSE; - if (Header->Bpp != 8 && Header->Bpp != 15 && Header->Bpp != 16 - && Header->Bpp != 24 && Header->Bpp != 32) - return IL_FALSE; - if (Header->ImageDesc & BIT_4) // Supposed to be set to 0 - return IL_FALSE; - - // check type (added 20040218) - if (Header->ImageType != TGA_NO_DATA - && Header->ImageType != TGA_COLMAP_UNCOMP - && Header->ImageType != TGA_UNMAP_UNCOMP - && Header->ImageType != TGA_BW_UNCOMP - && Header->ImageType != TGA_COLMAP_COMP - && Header->ImageType != TGA_UNMAP_COMP - && Header->ImageType != TGA_BW_COMP) - return IL_FALSE; - - // Doesn't work well with the bitshift so change it. - if (Header->Bpp == 15) - Header->Bpp = 16; - - return IL_TRUE; -} - - -//! Reads a Targa file -ILboolean ilLoadTarga(ILconst_string FileName) -{ - ILHANDLE TargaFile; - ILboolean bTarga = IL_FALSE; - - TargaFile = iopenr(FileName); - if (TargaFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bTarga; - } - - bTarga = ilLoadTargaF(TargaFile); - icloser(TargaFile); - - return bTarga; -} - - -//! Reads an already-opened Targa file -ILboolean ilLoadTargaF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadTargaInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a Targa -ILboolean ilLoadTargaL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadTargaInternal(); -} - - -// Internal function used to load the Targa. -ILboolean iLoadTargaInternal() -{ - TARGAHEAD Header; - ILboolean bTarga; - ILenum iOrigin; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (!iGetTgaHead(&Header)) - return IL_FALSE; - if (!iCheckTarga(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - switch (Header.ImageType) - { - case TGA_NO_DATA: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - case TGA_COLMAP_UNCOMP: - case TGA_COLMAP_COMP: - bTarga = iReadColMapTga(&Header); - break; - case TGA_UNMAP_UNCOMP: - case TGA_UNMAP_COMP: - bTarga = iReadUnmapTga(&Header); - break; - case TGA_BW_UNCOMP: - case TGA_BW_COMP: - bTarga = iReadBwTga(&Header); - break; - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - // @JASON Extra Code to manipulate the image depending on - // the Image Descriptor's origin bits. - iOrigin = Header.ImageDesc & IMAGEDESC_ORIGIN_MASK; - - switch (iOrigin) - { - case IMAGEDESC_TOPLEFT: - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - break; - - case IMAGEDESC_TOPRIGHT: - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - iMirror(); - break; - - case IMAGEDESC_BOTLEFT: - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - break; - - case IMAGEDESC_BOTRIGHT: - iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; - iMirror(); - break; - } - - return ilFixImage(); -} - - -ILboolean iReadColMapTga(TARGAHEAD *Header) -{ - char ID[255]; - ILuint i; - ILushort Pixel; - - if (iread(ID, 1, Header->IDLen) != Header->IDLen) - return IL_FALSE; - - if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize) - ifree(iCurImage->Pal.Palette); - - iCurImage->Format = IL_COLOUR_INDEX; - iCurImage->Pal.PalSize = Header->ColMapLen * (Header->ColMapEntSize >> 3); - - switch (Header->ColMapEntSize) - { - case 16: - iCurImage->Pal.PalType = IL_PAL_BGRA32; - iCurImage->Pal.PalSize = Header->ColMapLen * 4; - break; - case 24: - iCurImage->Pal.PalType = IL_PAL_BGR24; - break; - case 32: - iCurImage->Pal.PalType = IL_PAL_BGRA32; - break; - default: - // Should *never* reach here - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); - if (iCurImage->Pal.Palette == NULL) { - return IL_FALSE; - } - - // Do we need to do something with FirstEntry? Like maybe: - // iread(Image->Pal + Targa->FirstEntry, 1, Image->Pal.PalSize); ?? - if (Header->ColMapEntSize != 16) - { - if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) - return IL_FALSE; - } - else { - // 16 bit palette, so we have to break it up. - for (i = 0; i < iCurImage->Pal.PalSize; i += 4) - { - Pixel = GetBigUShort(); - if (ieof()) - return IL_FALSE; - iCurImage->Pal.Palette[3] = (Pixel & 0x8000) >> 12; - iCurImage->Pal.Palette[0] = (Pixel & 0xFC00) >> 7; - iCurImage->Pal.Palette[1] = (Pixel & 0x03E0) >> 2; - iCurImage->Pal.Palette[2] = (Pixel & 0x001F) << 3; - } - } - - if (Header->ImageType == TGA_COLMAP_COMP) - { - if (!iUncompressTgaData(iCurImage)) - { - return IL_FALSE; - } - } - else - { - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) - { - return IL_FALSE; - } - } - - return IL_TRUE; -} - - -ILboolean iReadUnmapTga(TARGAHEAD *Header) -{ - ILubyte Bpp; - char ID[255]; - - if (iread(ID, 1, Header->IDLen) != Header->IDLen) - return IL_FALSE; - - /*if (Header->Bpp == 16) - Bpp = 3; - else*/ - Bpp = (ILubyte)(Header->Bpp >> 3); - - if (!ilTexImage(Header->Width, Header->Height, 1, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - - switch (iCurImage->Bpp) - { - case 1: - iCurImage->Format = IL_COLOUR_INDEX; // wtf? How is this possible? - break; - case 2: // 16-bit is not supported directly! - //iCurImage->Format = IL_RGB5_A1; - /*iCurImage->Format = IL_RGBA; - iCurImage->Type = IL_UNSIGNED_SHORT_5_5_5_1_EXT;*/ - //iCurImage->Type = IL_UNSIGNED_SHORT_5_6_5_REV; - - // Remove? - //ilCloseImage(iCurImage); - //ilSetError(IL_FORMAT_NOT_SUPPORTED); - //return IL_FALSE; - - /*iCurImage->Bpp = 4; - iCurImage->Format = IL_BGRA; - iCurImage->Type = IL_UNSIGNED_SHORT_1_5_5_5_REV;*/ - - iCurImage->Format = IL_BGR; - - break; - case 3: - iCurImage->Format = IL_BGR; - break; - case 4: - iCurImage->Format = IL_BGRA; - break; - default: - ilSetError(IL_INVALID_VALUE); - return IL_FALSE; - } - - - // @TODO: Determine this: - // We assume that no palette is present, but it's possible... - // Should we mess with it or not? - - - if (Header->ImageType == TGA_UNMAP_COMP) { - if (!iUncompressTgaData(iCurImage)) { - return IL_FALSE; - } - } - else { - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) { - return IL_FALSE; - } - } - - // Go ahead and expand it to 24-bit. - if (Header->Bpp == 16) { - if (!i16BitTarga(iCurImage)) - return IL_FALSE; - return IL_TRUE; - } - - return IL_TRUE; -} - - -ILboolean iReadBwTga(TARGAHEAD *Header) -{ - char ID[255]; - - if (iread(ID, 1, Header->IDLen) != Header->IDLen) - return IL_FALSE; - - // We assume that no palette is present, but it's possible... - // Should we mess with it or not? - - if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) { - return IL_FALSE; - } - - if (Header->ImageType == TGA_BW_COMP) { - if (!iUncompressTgaData(iCurImage)) { - return IL_FALSE; - } - } - else { - if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) { - return IL_FALSE; - } - } - - return IL_TRUE; -} - - -ILboolean iUncompressTgaData(ILimage *Image) -{ - ILuint BytesRead = 0, Size, RunLen, i, ToRead; - ILubyte Header, Color[4]; - ILint c; - - Size = Image->Width * Image->Height * Image->Depth * Image->Bpp; - - if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) - iPreCache(iCurImage->SizeOfData / 2); - - while (BytesRead < Size) { - Header = (ILubyte)igetc(); - if (Header & BIT_7) { - ClearBits(Header, BIT_7); - if (iread(Color, 1, Image->Bpp) != Image->Bpp) { - iUnCache(); - return IL_FALSE; - } - RunLen = (Header+1) * Image->Bpp; - for (i = 0; i < RunLen; i += Image->Bpp) { - // Read the color in, but we check to make sure that we do not go past the end of the image. - for (c = 0; c < Image->Bpp && BytesRead+i+c < Size; c++) { - Image->Data[BytesRead+i+c] = Color[c]; - } - } - BytesRead += RunLen; - } - else { - RunLen = (Header+1) * Image->Bpp; - // We have to check that we do not go past the end of the image data. - if (BytesRead + RunLen > Size) - ToRead = Size - BytesRead; - else - ToRead = RunLen; - if (iread(Image->Data + BytesRead, 1, ToRead) != ToRead) { - iUnCache(); //@TODO: Error needed here? - return IL_FALSE; - } - BytesRead += RunLen; - - if (BytesRead + RunLen > Size) - iseek(RunLen - ToRead, IL_SEEK_CUR); - } - } - - iUnCache(); - - return IL_TRUE; -} - - -// Pretty damn unoptimized -ILboolean i16BitTarga(ILimage *Image) -{ - ILushort *Temp1; - ILubyte *Data, *Temp2; - ILuint x, PixSize = Image->Width * Image->Height; - - Data = (ILubyte*)ialloc(Image->Width * Image->Height * 3); - Temp1 = (ILushort*)Image->Data; - Temp2 = Data; - - if (Data == NULL) - return IL_FALSE; - - for (x = 0; x < PixSize; x++) { - *Temp2++ = (*Temp1 & 0x001F) << 3; // Blue - *Temp2++ = (*Temp1 & 0x03E0) >> 2; // Green - *Temp2++ = (*Temp1 & 0x7C00) >> 7; // Red - - Temp1++; - - - /*s = *Temp; - s = SwapShort(s); - a = !!(s & BIT_15); - - s = s << 1; - - //if (a) { - SetBits(s, BIT_0); - //} - - //SetBits(s, BIT_15); - - *Temp++ = s;*/ - } - - if (!ilTexImage(Image->Width, Image->Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, Data)) { - ifree(Data); - return IL_FALSE; - } - - ifree(Data); - - return IL_TRUE; -} - - -//! Writes a Targa file -ILboolean ilSaveTarga(const ILstring FileName) -{ - ILHANDLE TargaFile; - ILuint TargaSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - TargaFile = iopenw(FileName); - if (TargaFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - TargaSize = ilSaveTargaF(TargaFile); - iclosew(TargaFile); - - if (TargaSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Targa to an already-opened file -ILuint ilSaveTargaF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveTargaInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Targa to a memory "lump" -ILuint ilSaveTargaL(void *Lump, ILuint Size) -{ - ILuint Pos = itellw(); - iSetOutputLump(Lump, Size); - if (iSaveTargaInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the Targa. -ILboolean iSaveTargaInternal() -{ - const char *ID = iGetString(IL_TGA_ID_STRING); - const char *AuthName = iGetString(IL_TGA_AUTHNAME_STRING); - const char *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING); - ILubyte IDLen = 0, UsePal, Type, PalEntSize; - ILshort ColMapStart = 0, PalSize; - ILubyte Temp; - ILenum Format; - ILboolean Compress; - ILuint RleLen; - ILubyte *Rle; - ILpal *TempPal = NULL; - ILimage *TempImage = NULL; - ILuint ExtOffset, i; - char *Footer = "TRUEVISION-XFILE.\0"; - char *idString = "Developer's Image Library (DevIL)"; - ILuint Day, Month, Year, Hour, Minute, Second; - char *TempData; - ILshort zero_short = 0; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (iGetInt(IL_TGA_RLE) == IL_TRUE) - Compress = IL_TRUE; - else - Compress = IL_FALSE; - - if (ID) - IDLen = (ILubyte)ilCharStrLen(ID); - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) - UsePal = IL_TRUE; - else - UsePal = IL_FALSE; - - iwrite(&IDLen, sizeof(ILubyte), 1); - iwrite(&UsePal, sizeof(ILubyte), 1); - - Format = iCurImage->Format; - switch (Format) { - case IL_COLOUR_INDEX: - if (Compress) - Type = 9; - else - Type = 1; - break; - case IL_BGR: - case IL_BGRA: - if (Compress) - Type = 10; - else - Type = 2; - break; - case IL_RGB: - case IL_RGBA: - ilSwapColours(); - if (Compress) - Type = 10; - else - Type = 2; - break; - case IL_LUMINANCE: - if (Compress) - Type = 11; - else - Type = 3; - break; - default: - // Should convert the types here... - ilSetError(IL_INVALID_VALUE); - ifree(ID); - ifree(AuthName); - ifree(AuthComment); - return IL_FALSE; - } - - iwrite(&Type, sizeof(ILubyte), 1); - SaveLittleShort(ColMapStart); - - switch (iCurImage->Pal.PalType) - { - case IL_PAL_NONE: - PalSize = 0; - PalEntSize = 0; - break; - case IL_PAL_BGR24: - PalSize = (ILshort)(iCurImage->Pal.PalSize / 3); - PalEntSize = 24; - TempPal = &iCurImage->Pal; - break; - - case IL_PAL_RGB24: - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_BGR24); - if (TempPal == NULL) - return IL_FALSE; - PalSize = (ILshort)(TempPal->PalSize / 3); - PalEntSize = 24; - break; - default: - ilSetError(IL_INVALID_VALUE); - ifree(ID); - ifree(AuthName); - ifree(AuthComment); - PalSize = 0; - PalEntSize = 0; - return IL_FALSE; - } - SaveLittleShort(PalSize); - iwrite(&PalEntSize, sizeof(ILubyte), 1); - - if (iCurImage->Bpc > 1) { - TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); - if (TempImage == NULL) { - ifree(ID); - ifree(AuthName); - ifree(AuthComment); - return IL_FALSE; - } - } - else { - TempImage = iCurImage; - } - - if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) { - TempData = (char*)iGetFlipped(TempImage); - } - else - TempData = (char*)TempImage->Data; - - // Write out the origin stuff. - iwrite(&zero_short, sizeof(ILshort), 1); - iwrite(&zero_short, sizeof(ILshort), 1); - - Temp = iCurImage->Bpp << 3; // Changes to bits per pixel - SaveLittleUShort((ILushort)iCurImage->Width); - SaveLittleUShort((ILushort)iCurImage->Height); - iwrite(&Temp, sizeof(ILubyte), 1); - - // Still don't know what exactly this is for... - // It's actually the 'Image Descriptor Byte' - // from wiki: Image descriptor (1 byte): bits 3-0 give the alpha channel depth, bits 5-4 give direction - Temp = 0; - if (iCurImage->Bpp > 3) - Temp = 8; - if (TempImage->Origin == IL_ORIGIN_UPPER_LEFT) - Temp |= 0x20; //set 5th bit - iwrite(&Temp, sizeof(ILubyte), 1); - iwrite(ID, sizeof(char), IDLen); - ifree(ID); - //iwrite(ID, sizeof(ILbyte), IDLen - sizeof(ILuint)); - //iwrite(&iCurImage->Depth, sizeof(ILuint), 1); - - // Write out the colormap - if (UsePal) - iwrite(TempPal->Palette, sizeof(ILubyte), TempPal->PalSize); - // else do nothing - - if (!Compress) - iwrite(TempData, sizeof(ILubyte), TempImage->SizeOfData); - else { - Rle = (ILubyte*)ialloc(TempImage->SizeOfData + TempImage->SizeOfData / 2 + 1); // max - if (Rle == NULL) { - ifree(AuthName); - ifree(AuthComment); - return IL_FALSE; - } - RleLen = ilRleCompress((unsigned char*)TempData, TempImage->Width, TempImage->Height, - TempImage->Depth, TempImage->Bpp, Rle, IL_TGACOMP, NULL); - - iwrite(Rle, 1, RleLen); - ifree(Rle); - } - - // Write the extension area. - ExtOffset = itellw(); - SaveLittleUShort(495); // Number of bytes in the extension area (TGA 2.0 spec) - iwrite(AuthName, 1, ilCharStrLen(AuthName)); - ipad(41 - ilCharStrLen(AuthName)); - iwrite(AuthComment, 1, ilCharStrLen(AuthComment)); - ipad(324 - ilCharStrLen(AuthComment)); - ifree(AuthName); - ifree(AuthComment); - - // Write time/date - iGetDateTime(&Month, &Day, &Year, &Hour, &Minute, &Second); - SaveLittleUShort((ILushort)Month); - SaveLittleUShort((ILushort)Day); - SaveLittleUShort((ILushort)Year); - SaveLittleUShort((ILushort)Hour); - SaveLittleUShort((ILushort)Minute); - SaveLittleUShort((ILushort)Second); - - for (i = 0; i < 6; i++) { // Time created - SaveLittleUShort(0); - } - for (i = 0; i < 41; i++) { // Job name/ID - iputc(0); - } - for (i = 0; i < 3; i++) { // Job time - SaveLittleUShort(0); - } - - iwrite(idString, 1, ilCharStrLen(idString)); // Software ID - for (i = 0; i < 41 - ilCharStrLen(idString); i++) { - iputc(0); - } - SaveLittleUShort(IL_VERSION); // Software version - iputc(' '); // Release letter (not beta anymore, so use a space) - - SaveLittleUInt(0); // Key colour - SaveLittleUInt(0); // Pixel aspect ratio - SaveLittleUInt(0); // Gamma correction offset - SaveLittleUInt(0); // Colour correction offset - SaveLittleUInt(0); // Postage stamp offset - SaveLittleUInt(0); // Scan line offset - iputc(3); // Attributes type - - // Write the footer. - SaveLittleUInt(ExtOffset); // No extension area - SaveLittleUInt(0); // No developer directory - iwrite(Footer, 1, ilCharStrLen(Footer)+1); - - if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) { - ifree(TempData); - } - if (Format == IL_RGB || Format == IL_RGBA) { - ilSwapColours(); - } - - if (TempPal != &iCurImage->Pal && TempPal != NULL) { - ifree(TempPal->Palette); - ifree(TempPal); - } - - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return IL_TRUE; -} - - -// Only to be called by ilDetermineSize. Returns the buffer size needed to save the -// current image as a Targa file. -ILuint iTargaSize(void) -{ - ILuint Size, Bpp; - ILubyte IDLen = 0; - const char *ID = iGetString(IL_TGA_ID_STRING); - const char *AuthName = iGetString(IL_TGA_AUTHNAME_STRING); - const char *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING); - - //@TODO: Support color indexed images. - if (iGetInt(IL_TGA_RLE) == IL_TRUE || iCurImage->Format == IL_COLOUR_INDEX) { - // Use the slower method, since we are using compression. We do a "fake" write. - ilSaveTargaL(NULL, 0); - } - - if (ID) - IDLen = (ILubyte)ilCharStrLen(ID); - - Size = 18 + IDLen; // Header + ID - - // Bpp may not be iCurImage->Bpp. - switch (iCurImage->Format) - { - case IL_BGR: - case IL_RGB: - Bpp = 3; - break; - case IL_BGRA: - case IL_RGBA: - Bpp = 4; - break; - case IL_LUMINANCE: - Bpp = 1; - break; - default: //@TODO: Do not know what to do with the others yet. - return 0; - } - - Size += iCurImage->Width * iCurImage->Height * Bpp; - Size += 532; // Size of the extension area - - return Size; -} - - -/*// Makes a neat string to go into the id field of the .tga -void iMakeString(char *Str) -{ - char *PSG = "Generated by Developer's Image Library: "; - char TimeStr[255]; - - time_t Time; - struct tm *CurTime; - - time(&Time); -#ifdef _WIN32 - _tzset(); -#endif - CurTime = localtime(&Time); - - strftime(TimeStr, 255 - ilCharStrLen(PSG), "%#c (%z)", CurTime); - //strftime(TimeStr, 255 - ilCharStrLen(PSG), "%C (%Z)", CurTime); - sprintf(Str, "%s%s", PSG, TimeStr); - - return; -}*/ - - -//changed name to iGetDateTime on 20031221 to fix bug 830196 -void iGetDateTime(ILuint *Month, ILuint *Day, ILuint *Yr, ILuint *Hr, ILuint *Min, ILuint *Sec) -{ -#ifdef DJGPP - struct date day; - struct time curtime; - - gettime(&curtime); - getdate(&day); - - *Month = day.da_mon; - *Day = day.da_day; - *Yr = day.da_year; - - *Hr = curtime.ti_hour; - *Min = curtime.ti_min; - *Sec = curtime.ti_sec; - - return; -#else - -#ifdef _WIN32 - SYSTEMTIME Time; - - GetSystemTime(&Time); - - *Month = Time.wMonth; - *Day = Time.wDay; - *Yr = Time.wYear; - - *Hr = Time.wHour; - *Min = Time.wMinute; - *Sec = Time.wSecond; - - return; -#else - - *Month = 0; - *Day = 0; - *Yr = 0; - - *Hr = 0; - *Min = 0; - *Sec = 0; - - return; -#endif -#endif -} - - -#endif//IL_NO_TGA diff --git a/DevIL/src-IL/src/il_targa.cpp b/DevIL/src-IL/src/il_targa.cpp new file mode 100644 index 00000000..55b4070f --- /dev/null +++ b/DevIL/src-IL/src/il_targa.cpp @@ -0,0 +1,961 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_targa.c +// +// Description: Reads from and writes to a Targa (.tga) file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_TGA +#include "il_targa.h" +//#include // for ilMakeString() +#include +#include "il_bits.h" + +#ifdef DJGPP +#include +#endif + + +//! Checks if the file specified in FileName is a valid Targa file. +ILboolean ilIsValidTga(ILconst_string FileName) +{ + ILHANDLE TargaFile; + ILboolean bTarga = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("tga")) && + !iCheckExtension(FileName, IL_TEXT("vda")) && + !iCheckExtension(FileName, IL_TEXT("icb")) && + !iCheckExtension(FileName, IL_TEXT("vst"))) { + ilSetError(IL_INVALID_EXTENSION); + return bTarga; + } + + TargaFile = iopenr(FileName); + if (TargaFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bTarga; + } + + bTarga = ilIsValidTgaF(TargaFile); + icloser(TargaFile); + + return bTarga; +} + + +//! Checks if the ILHANDLE contains a valid Targa file at the current position. +ILboolean ilIsValidTgaF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidTarga(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid Targa lump. +ILboolean ilIsValidTgaL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidTarga(); +} + + +// Internal function used to get the Targa header from the current file. +ILboolean iGetTgaHead(TARGAHEAD *Header) +{ + Header->IDLen = (ILubyte)igetc(); + Header->ColMapPresent = (ILubyte)igetc(); + Header->ImageType = (ILubyte)igetc(); + Header->FirstEntry = GetLittleShort(); + Header->ColMapLen = GetLittleShort(); + Header->ColMapEntSize = (ILubyte)igetc(); + + Header->OriginX = GetLittleShort(); + Header->OriginY = GetLittleShort(); + Header->Width = GetLittleUShort(); + Header->Height = GetLittleUShort(); + Header->Bpp = (ILubyte)igetc(); + Header->ImageDesc = (ILubyte)igetc(); + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidTarga() +{ + TARGAHEAD Head; + + if (!iGetTgaHead(&Head)) + return IL_FALSE; + iseek(-(ILint)sizeof(TARGAHEAD), IL_SEEK_CUR); + + return iCheckTarga(&Head); +} + + +// Internal function used to check if the HEADER is a valid Targa header. +ILboolean iCheckTarga(TARGAHEAD *Header) +{ + if (Header->Width == 0 || Header->Height == 0) + return IL_FALSE; + if (Header->Bpp != 8 && Header->Bpp != 15 && Header->Bpp != 16 + && Header->Bpp != 24 && Header->Bpp != 32) + return IL_FALSE; + if (Header->ImageDesc & BIT_4) // Supposed to be set to 0 + return IL_FALSE; + + // check type (added 20040218) + if (Header->ImageType != TGA_NO_DATA + && Header->ImageType != TGA_COLMAP_UNCOMP + && Header->ImageType != TGA_UNMAP_UNCOMP + && Header->ImageType != TGA_BW_UNCOMP + && Header->ImageType != TGA_COLMAP_COMP + && Header->ImageType != TGA_UNMAP_COMP + && Header->ImageType != TGA_BW_COMP) + return IL_FALSE; + + // Doesn't work well with the bitshift so change it. + if (Header->Bpp == 15) + Header->Bpp = 16; + + return IL_TRUE; +} + + +//! Reads a Targa file +ILboolean ilLoadTarga(ILconst_string FileName) +{ + ILHANDLE TargaFile; + ILboolean bTarga = IL_FALSE; + + TargaFile = iopenr(FileName); + if (TargaFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bTarga; + } + + bTarga = ilLoadTargaF(TargaFile); + icloser(TargaFile); + + return bTarga; +} + + +//! Reads an already-opened Targa file +ILboolean ilLoadTargaF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadTargaInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a Targa +ILboolean ilLoadTargaL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadTargaInternal(); +} + + +// Internal function used to load the Targa. +ILboolean iLoadTargaInternal() +{ + TARGAHEAD Header; + ILboolean bTarga; + ILenum iOrigin; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (!iGetTgaHead(&Header)) + return IL_FALSE; + if (!iCheckTarga(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + switch (Header.ImageType) + { + case TGA_NO_DATA: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + case TGA_COLMAP_UNCOMP: + case TGA_COLMAP_COMP: + bTarga = iReadColMapTga(&Header); + break; + case TGA_UNMAP_UNCOMP: + case TGA_UNMAP_COMP: + bTarga = iReadUnmapTga(&Header); + break; + case TGA_BW_UNCOMP: + case TGA_BW_COMP: + bTarga = iReadBwTga(&Header); + break; + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + // @JASON Extra Code to manipulate the image depending on + // the Image Descriptor's origin bits. + iOrigin = Header.ImageDesc & IMAGEDESC_ORIGIN_MASK; + + switch (iOrigin) + { + case IMAGEDESC_TOPLEFT: + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + break; + + case IMAGEDESC_TOPRIGHT: + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + iMirror(); + break; + + case IMAGEDESC_BOTLEFT: + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + break; + + case IMAGEDESC_BOTRIGHT: + iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; + iMirror(); + break; + } + + return ilFixImage(); +} + + +ILboolean iReadColMapTga(TARGAHEAD *Header) +{ + char ID[255]; + ILuint i; + ILushort Pixel; + + if (iread(ID, 1, Header->IDLen) != Header->IDLen) + return IL_FALSE; + + if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize) + ifree(iCurImage->Pal.Palette); + + iCurImage->Format = IL_COLOUR_INDEX; + iCurImage->Pal.PalSize = Header->ColMapLen * (Header->ColMapEntSize >> 3); + + switch (Header->ColMapEntSize) + { + case 16: + iCurImage->Pal.PalType = IL_PAL_BGRA32; + iCurImage->Pal.PalSize = Header->ColMapLen * 4; + break; + case 24: + iCurImage->Pal.PalType = IL_PAL_BGR24; + break; + case 32: + iCurImage->Pal.PalType = IL_PAL_BGRA32; + break; + default: + // Should *never* reach here + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); + if (iCurImage->Pal.Palette == NULL) { + return IL_FALSE; + } + + // Do we need to do something with FirstEntry? Like maybe: + // iread(Image->Pal + Targa->FirstEntry, 1, Image->Pal.PalSize); ?? + if (Header->ColMapEntSize != 16) + { + if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) + return IL_FALSE; + } + else { + // 16 bit palette, so we have to break it up. + for (i = 0; i < iCurImage->Pal.PalSize; i += 4) + { + Pixel = GetBigUShort(); + if (ieof()) + return IL_FALSE; + iCurImage->Pal.Palette[3] = (Pixel & 0x8000) >> 12; + iCurImage->Pal.Palette[0] = (Pixel & 0xFC00) >> 7; + iCurImage->Pal.Palette[1] = (Pixel & 0x03E0) >> 2; + iCurImage->Pal.Palette[2] = (Pixel & 0x001F) << 3; + } + } + + if (Header->ImageType == TGA_COLMAP_COMP) + { + if (!iUncompressTgaData(iCurImage)) + { + return IL_FALSE; + } + } + else + { + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) + { + return IL_FALSE; + } + } + + return IL_TRUE; +} + + +ILboolean iReadUnmapTga(TARGAHEAD *Header) +{ + ILubyte Bpp; + char ID[255]; + + if (iread(ID, 1, Header->IDLen) != Header->IDLen) + return IL_FALSE; + + /*if (Header->Bpp == 16) + Bpp = 3; + else*/ + Bpp = (ILubyte)(Header->Bpp >> 3); + + if (!ilTexImage(Header->Width, Header->Height, 1, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + + switch (iCurImage->Bpp) + { + case 1: + iCurImage->Format = IL_COLOUR_INDEX; // wtf? How is this possible? + break; + case 2: // 16-bit is not supported directly! + //iCurImage->Format = IL_RGB5_A1; + /*iCurImage->Format = IL_RGBA; + iCurImage->Type = IL_UNSIGNED_SHORT_5_5_5_1_EXT;*/ + //iCurImage->Type = IL_UNSIGNED_SHORT_5_6_5_REV; + + // Remove? + //ilCloseImage(iCurImage); + //ilSetError(IL_FORMAT_NOT_SUPPORTED); + //return IL_FALSE; + + /*iCurImage->Bpp = 4; + iCurImage->Format = IL_BGRA; + iCurImage->Type = IL_UNSIGNED_SHORT_1_5_5_5_REV;*/ + + iCurImage->Format = IL_BGR; + + break; + case 3: + iCurImage->Format = IL_BGR; + break; + case 4: + iCurImage->Format = IL_BGRA; + break; + default: + ilSetError(IL_INVALID_VALUE); + return IL_FALSE; + } + + + // @TODO: Determine this: + // We assume that no palette is present, but it's possible... + // Should we mess with it or not? + + + if (Header->ImageType == TGA_UNMAP_COMP) { + if (!iUncompressTgaData(iCurImage)) { + return IL_FALSE; + } + } + else { + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) { + return IL_FALSE; + } + } + + // Go ahead and expand it to 24-bit. + if (Header->Bpp == 16) { + if (!i16BitTarga(iCurImage)) + return IL_FALSE; + return IL_TRUE; + } + + return IL_TRUE; +} + + +ILboolean iReadBwTga(TARGAHEAD *Header) +{ + char ID[255]; + + if (iread(ID, 1, Header->IDLen) != Header->IDLen) + return IL_FALSE; + + // We assume that no palette is present, but it's possible... + // Should we mess with it or not? + + if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) { + return IL_FALSE; + } + + if (Header->ImageType == TGA_BW_COMP) { + if (!iUncompressTgaData(iCurImage)) { + return IL_FALSE; + } + } + else { + if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) { + return IL_FALSE; + } + } + + return IL_TRUE; +} + + +ILboolean iUncompressTgaData(ILimage *Image) +{ + ILuint BytesRead = 0, Size, RunLen, i, ToRead; + ILubyte Header, Color[4]; + ILint c; + + Size = Image->Width * Image->Height * Image->Depth * Image->Bpp; + + if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) + iPreCache(iCurImage->SizeOfData / 2); + + while (BytesRead < Size) { + Header = (ILubyte)igetc(); + if (Header & BIT_7) { + ClearBits(Header, BIT_7); + if (iread(Color, 1, Image->Bpp) != Image->Bpp) { + iUnCache(); + return IL_FALSE; + } + RunLen = (Header+1) * Image->Bpp; + for (i = 0; i < RunLen; i += Image->Bpp) { + // Read the color in, but we check to make sure that we do not go past the end of the image. + for (c = 0; c < Image->Bpp && BytesRead+i+c < Size; c++) { + Image->Data[BytesRead+i+c] = Color[c]; + } + } + BytesRead += RunLen; + } + else { + RunLen = (Header+1) * Image->Bpp; + // We have to check that we do not go past the end of the image data. + if (BytesRead + RunLen > Size) + ToRead = Size - BytesRead; + else + ToRead = RunLen; + if (iread(Image->Data + BytesRead, 1, ToRead) != ToRead) { + iUnCache(); //@TODO: Error needed here? + return IL_FALSE; + } + BytesRead += RunLen; + + if (BytesRead + RunLen > Size) + iseek(RunLen - ToRead, IL_SEEK_CUR); + } + } + + iUnCache(); + + return IL_TRUE; +} + + +// Pretty damn unoptimized +ILboolean i16BitTarga(ILimage *Image) +{ + ILushort *Temp1; + ILubyte *Data, *Temp2; + ILuint x, PixSize = Image->Width * Image->Height; + + Data = (ILubyte*)ialloc(Image->Width * Image->Height * 3); + Temp1 = (ILushort*)Image->Data; + Temp2 = Data; + + if (Data == NULL) + return IL_FALSE; + + for (x = 0; x < PixSize; x++) { + *Temp2++ = (*Temp1 & 0x001F) << 3; // Blue + *Temp2++ = (*Temp1 & 0x03E0) >> 2; // Green + *Temp2++ = (*Temp1 & 0x7C00) >> 7; // Red + + Temp1++; + + + /*s = *Temp; + s = SwapShort(s); + a = !!(s & BIT_15); + + s = s << 1; + + //if (a) { + SetBits(s, BIT_0); + //} + + //SetBits(s, BIT_15); + + *Temp++ = s;*/ + } + + if (!ilTexImage(Image->Width, Image->Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, Data)) { + ifree(Data); + return IL_FALSE; + } + + ifree(Data); + + return IL_TRUE; +} + + +//! Writes a Targa file +ILboolean ilSaveTarga(const ILstring FileName) +{ + ILHANDLE TargaFile; + ILuint TargaSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + TargaFile = iopenw(FileName); + if (TargaFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + TargaSize = ilSaveTargaF(TargaFile); + iclosew(TargaFile); + + if (TargaSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Targa to an already-opened file +ILuint ilSaveTargaF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveTargaInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Targa to a memory "lump" +ILuint ilSaveTargaL(void *Lump, ILuint Size) +{ + ILuint Pos = itellw(); + iSetOutputLump(Lump, Size); + if (iSaveTargaInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the Targa. +ILboolean iSaveTargaInternal() +{ + const char *ID = iGetString(IL_TGA_ID_STRING); + const char *AuthName = iGetString(IL_TGA_AUTHNAME_STRING); + const char *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING); + ILubyte IDLen = 0, UsePal, Type, PalEntSize; + ILshort ColMapStart = 0, PalSize; + ILubyte Temp; + ILenum Format; + ILboolean Compress; + ILuint RleLen; + ILubyte *Rle; + ILpal *TempPal = NULL; + ILimage *TempImage = NULL; + ILuint ExtOffset, i; + char *Footer = "TRUEVISION-XFILE.\0"; + char *idString = "Developer's Image Library (DevIL)"; + ILuint Day, Month, Year, Hour, Minute, Second; + char *TempData; + ILshort zero_short = 0; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (iGetInt(IL_TGA_RLE) == IL_TRUE) + Compress = IL_TRUE; + else + Compress = IL_FALSE; + + if (ID) + IDLen = (ILubyte)ilCharStrLen(ID); + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) + UsePal = IL_TRUE; + else + UsePal = IL_FALSE; + + iwrite(&IDLen, sizeof(ILubyte), 1); + iwrite(&UsePal, sizeof(ILubyte), 1); + + Format = iCurImage->Format; + switch (Format) { + case IL_COLOUR_INDEX: + if (Compress) + Type = 9; + else + Type = 1; + break; + case IL_BGR: + case IL_BGRA: + if (Compress) + Type = 10; + else + Type = 2; + break; + case IL_RGB: + case IL_RGBA: + ilSwapColours(); + if (Compress) + Type = 10; + else + Type = 2; + break; + case IL_LUMINANCE: + if (Compress) + Type = 11; + else + Type = 3; + break; + default: + // Should convert the types here... + ilSetError(IL_INVALID_VALUE); + ifree(ID); + ifree(AuthName); + ifree(AuthComment); + return IL_FALSE; + } + + iwrite(&Type, sizeof(ILubyte), 1); + SaveLittleShort(ColMapStart); + + switch (iCurImage->Pal.PalType) + { + case IL_PAL_NONE: + PalSize = 0; + PalEntSize = 0; + break; + case IL_PAL_BGR24: + PalSize = (ILshort)(iCurImage->Pal.PalSize / 3); + PalEntSize = 24; + TempPal = &iCurImage->Pal; + break; + + case IL_PAL_RGB24: + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_BGR24); + if (TempPal == NULL) + return IL_FALSE; + PalSize = (ILshort)(TempPal->PalSize / 3); + PalEntSize = 24; + break; + default: + ilSetError(IL_INVALID_VALUE); + ifree(ID); + ifree(AuthName); + ifree(AuthComment); + PalSize = 0; + PalEntSize = 0; + return IL_FALSE; + } + SaveLittleShort(PalSize); + iwrite(&PalEntSize, sizeof(ILubyte), 1); + + if (iCurImage->Bpc > 1) { + TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE); + if (TempImage == NULL) { + ifree(ID); + ifree(AuthName); + ifree(AuthComment); + return IL_FALSE; + } + } + else { + TempImage = iCurImage; + } + + if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) { + TempData = (char*)iGetFlipped(TempImage); + } + else + TempData = (char*)TempImage->Data; + + // Write out the origin stuff. + iwrite(&zero_short, sizeof(ILshort), 1); + iwrite(&zero_short, sizeof(ILshort), 1); + + Temp = iCurImage->Bpp << 3; // Changes to bits per pixel + SaveLittleUShort((ILushort)iCurImage->Width); + SaveLittleUShort((ILushort)iCurImage->Height); + iwrite(&Temp, sizeof(ILubyte), 1); + + // Still don't know what exactly this is for... + // It's actually the 'Image Descriptor Byte' + // from wiki: Image descriptor (1 byte): bits 3-0 give the alpha channel depth, bits 5-4 give direction + Temp = 0; + if (iCurImage->Bpp > 3) + Temp = 8; + if (TempImage->Origin == IL_ORIGIN_UPPER_LEFT) + Temp |= 0x20; //set 5th bit + iwrite(&Temp, sizeof(ILubyte), 1); + iwrite(ID, sizeof(char), IDLen); + ifree(ID); + //iwrite(ID, sizeof(ILbyte), IDLen - sizeof(ILuint)); + //iwrite(&iCurImage->Depth, sizeof(ILuint), 1); + + // Write out the colormap + if (UsePal) + iwrite(TempPal->Palette, sizeof(ILubyte), TempPal->PalSize); + // else do nothing + + if (!Compress) + iwrite(TempData, sizeof(ILubyte), TempImage->SizeOfData); + else { + Rle = (ILubyte*)ialloc(TempImage->SizeOfData + TempImage->SizeOfData / 2 + 1); // max + if (Rle == NULL) { + ifree(AuthName); + ifree(AuthComment); + return IL_FALSE; + } + RleLen = ilRleCompress((unsigned char*)TempData, TempImage->Width, TempImage->Height, + TempImage->Depth, TempImage->Bpp, Rle, IL_TGACOMP, NULL); + + iwrite(Rle, 1, RleLen); + ifree(Rle); + } + + // Write the extension area. + ExtOffset = itellw(); + SaveLittleUShort(495); // Number of bytes in the extension area (TGA 2.0 spec) + iwrite(AuthName, 1, ilCharStrLen(AuthName)); + ipad(41 - ilCharStrLen(AuthName)); + iwrite(AuthComment, 1, ilCharStrLen(AuthComment)); + ipad(324 - ilCharStrLen(AuthComment)); + ifree(AuthName); + ifree(AuthComment); + + // Write time/date + iGetDateTime(&Month, &Day, &Year, &Hour, &Minute, &Second); + SaveLittleUShort((ILushort)Month); + SaveLittleUShort((ILushort)Day); + SaveLittleUShort((ILushort)Year); + SaveLittleUShort((ILushort)Hour); + SaveLittleUShort((ILushort)Minute); + SaveLittleUShort((ILushort)Second); + + for (i = 0; i < 6; i++) { // Time created + SaveLittleUShort(0); + } + for (i = 0; i < 41; i++) { // Job name/ID + iputc(0); + } + for (i = 0; i < 3; i++) { // Job time + SaveLittleUShort(0); + } + + iwrite(idString, 1, ilCharStrLen(idString)); // Software ID + for (i = 0; i < 41 - ilCharStrLen(idString); i++) { + iputc(0); + } + SaveLittleUShort(IL_VERSION); // Software version + iputc(' '); // Release letter (not beta anymore, so use a space) + + SaveLittleUInt(0); // Key colour + SaveLittleUInt(0); // Pixel aspect ratio + SaveLittleUInt(0); // Gamma correction offset + SaveLittleUInt(0); // Colour correction offset + SaveLittleUInt(0); // Postage stamp offset + SaveLittleUInt(0); // Scan line offset + iputc(3); // Attributes type + + // Write the footer. + SaveLittleUInt(ExtOffset); // No extension area + SaveLittleUInt(0); // No developer directory + iwrite(Footer, 1, ilCharStrLen(Footer)+1); + + if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) { + ifree(TempData); + } + if (Format == IL_RGB || Format == IL_RGBA) { + ilSwapColours(); + } + + if (TempPal != &iCurImage->Pal && TempPal != NULL) { + ifree(TempPal->Palette); + ifree(TempPal); + } + + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return IL_TRUE; +} + + +// Only to be called by ilDetermineSize. Returns the buffer size needed to save the +// current image as a Targa file. +ILuint iTargaSize(void) +{ + ILuint Size, Bpp; + ILubyte IDLen = 0; + const char *ID = iGetString(IL_TGA_ID_STRING); + const char *AuthName = iGetString(IL_TGA_AUTHNAME_STRING); + const char *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING); + + //@TODO: Support color indexed images. + if (iGetInt(IL_TGA_RLE) == IL_TRUE || iCurImage->Format == IL_COLOUR_INDEX) { + // Use the slower method, since we are using compression. We do a "fake" write. + ilSaveTargaL(NULL, 0); + } + + if (ID) + IDLen = (ILubyte)ilCharStrLen(ID); + + Size = 18 + IDLen; // Header + ID + + // Bpp may not be iCurImage->Bpp. + switch (iCurImage->Format) + { + case IL_BGR: + case IL_RGB: + Bpp = 3; + break; + case IL_BGRA: + case IL_RGBA: + Bpp = 4; + break; + case IL_LUMINANCE: + Bpp = 1; + break; + default: //@TODO: Do not know what to do with the others yet. + return 0; + } + + Size += iCurImage->Width * iCurImage->Height * Bpp; + Size += 532; // Size of the extension area + + return Size; +} + + +/*// Makes a neat string to go into the id field of the .tga +void iMakeString(char *Str) +{ + char *PSG = "Generated by Developer's Image Library: "; + char TimeStr[255]; + + time_t Time; + struct tm *CurTime; + + time(&Time); +#ifdef _WIN32 + _tzset(); +#endif + CurTime = localtime(&Time); + + strftime(TimeStr, 255 - ilCharStrLen(PSG), "%#c (%z)", CurTime); + //strftime(TimeStr, 255 - ilCharStrLen(PSG), "%C (%Z)", CurTime); + sprintf(Str, "%s%s", PSG, TimeStr); + + return; +}*/ + + +//changed name to iGetDateTime on 20031221 to fix bug 830196 +void iGetDateTime(ILuint *Month, ILuint *Day, ILuint *Yr, ILuint *Hr, ILuint *Min, ILuint *Sec) +{ +#ifdef DJGPP + struct date day; + struct time curtime; + + gettime(&curtime); + getdate(&day); + + *Month = day.da_mon; + *Day = day.da_day; + *Yr = day.da_year; + + *Hr = curtime.ti_hour; + *Min = curtime.ti_min; + *Sec = curtime.ti_sec; + + return; +#else + +#ifdef _WIN32 + SYSTEMTIME Time; + + GetSystemTime(&Time); + + *Month = Time.wMonth; + *Day = Time.wDay; + *Yr = Time.wYear; + + *Hr = Time.wHour; + *Min = Time.wMinute; + *Sec = Time.wSecond; + + return; +#else + + *Month = 0; + *Day = 0; + *Yr = 0; + + *Hr = 0; + *Min = 0; + *Sec = 0; + + return; +#endif +#endif +} + + +#endif//IL_NO_TGA diff --git a/DevIL/src-IL/src/il_texture.c b/DevIL/src-IL/src/il_texture.c deleted file mode 100644 index ec00d7aa..00000000 --- a/DevIL/src-IL/src/il_texture.c +++ /dev/null @@ -1,66 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/16/2009 -// -// Filename: src-IL/src/il_texture.c -// -// Description: Reads from a Medieval II: Total War (by Creative Assembly) -// Texture (.texture) file. -// -//----------------------------------------------------------------------------- - -#include "il_internal.h" -#ifndef IL_NO_TEXTURE - - -//! Reads a TEXTURE file -ILboolean ilLoadTexture(ILconst_string FileName) -{ - ILHANDLE TextureFile; - ILboolean bTexture = IL_FALSE; - - TextureFile = iopenr(FileName); - if (TextureFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bTexture; - } - - bTexture = ilLoadTextureF(TextureFile); - icloser(TextureFile); - - return bTexture; -} - - -//! Reads an already-opened TEXTURE file -ILboolean ilLoadTextureF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - // From http://forums.totalwar.org/vb/showthread.php?t=70886, all that needs to be done - // is to strip out the first 48 bytes, and then it is DDS data. - iseek(48, IL_SEEK_CUR); - bRet = ilLoadDdsF(File); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a TEXTURE -ILboolean ilLoadTextureL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - // From http://forums.totalwar.org/vb/showthread.php?t=70886, all that needs to be done - // is to strip out the first 48 bytes, and then it is DDS data. - iseek(48, IL_SEEK_CUR); - return ilLoadDdsL(Lump, Size); -} - -#endif//IL_NO_TEXTURE - diff --git a/DevIL/src-IL/src/il_texture.cpp b/DevIL/src-IL/src/il_texture.cpp new file mode 100644 index 00000000..ec00d7aa --- /dev/null +++ b/DevIL/src-IL/src/il_texture.cpp @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/16/2009 +// +// Filename: src-IL/src/il_texture.c +// +// Description: Reads from a Medieval II: Total War (by Creative Assembly) +// Texture (.texture) file. +// +//----------------------------------------------------------------------------- + +#include "il_internal.h" +#ifndef IL_NO_TEXTURE + + +//! Reads a TEXTURE file +ILboolean ilLoadTexture(ILconst_string FileName) +{ + ILHANDLE TextureFile; + ILboolean bTexture = IL_FALSE; + + TextureFile = iopenr(FileName); + if (TextureFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bTexture; + } + + bTexture = ilLoadTextureF(TextureFile); + icloser(TextureFile); + + return bTexture; +} + + +//! Reads an already-opened TEXTURE file +ILboolean ilLoadTextureF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + // From http://forums.totalwar.org/vb/showthread.php?t=70886, all that needs to be done + // is to strip out the first 48 bytes, and then it is DDS data. + iseek(48, IL_SEEK_CUR); + bRet = ilLoadDdsF(File); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a TEXTURE +ILboolean ilLoadTextureL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + // From http://forums.totalwar.org/vb/showthread.php?t=70886, all that needs to be done + // is to strip out the first 48 bytes, and then it is DDS data. + iseek(48, IL_SEEK_CUR); + return ilLoadDdsL(Lump, Size); +} + +#endif//IL_NO_TEXTURE + diff --git a/DevIL/src-IL/src/il_tiff.c b/DevIL/src-IL/src/il_tiff.c deleted file mode 100644 index 6febc9c7..00000000 --- a/DevIL/src-IL/src/il_tiff.c +++ /dev/null @@ -1,1112 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_tiff.c -// -// Description: Tiff (.tif) functions -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_TIF - -#include "tiffio.h" - -#include - -#define MAGIC_HEADER1 0x4949 -#define MAGIC_HEADER2 0x4D4D - - -#if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "tiff.lib") - #else - //#pragma comment(lib, "tiff-d.lib") - #pragma comment(lib, "tiff.lib") - #endif - #endif -#endif - - -/*----------------------------------------------------------------------------*/ - -// No need for a separate header -static ILboolean iLoadTiffInternal(void); -static char* iMakeString(void); -static TIFF* iTIFFOpen(char *Mode); -static ILboolean iSaveTiffInternal(/*ILconst_string Filename*/); - -/*----------------------------------------------------------------------------*/ - -ILboolean ilisValidTiffExtension(ILconst_string FileName) -{ - if (!iCheckExtension((ILstring)FileName, IL_TEXT("tif")) && - !iCheckExtension((ILstring)FileName, IL_TEXT("tiff"))) - return IL_FALSE; - else - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -//! Checks if the file specified in FileName is a valid tiff file. -ILboolean ilIsValidTiff(ILconst_string FileName) -{ - ILHANDLE TiffFile; - ILboolean bTiff = IL_FALSE; - - if (!ilisValidTiffExtension((ILstring) FileName)) { - ilSetError(IL_INVALID_EXTENSION); - return bTiff; - } - - TiffFile = iopenr((ILstring)FileName); - if (TiffFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bTiff; - } - - bTiff = ilIsValidTiffF(TiffFile); - icloser(TiffFile); - - return bTiff; -} - -/*----------------------------------------------------------------------------*/ - -ILboolean ilisValidTiffFunc() -{ - ILushort Header1, Header2; - - Header1 = GetLittleUShort(); - - if (Header1 != MAGIC_HEADER1 && Header1 != MAGIC_HEADER2) - return IL_FALSE; - - if (Header1 == MAGIC_HEADER1) - Header2 = GetLittleUShort(); - else - Header2 = GetBigUShort(); - - if (Header2 != 42) - return IL_FALSE; - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ - -//! Checks if the ILHANDLE contains a valid tiff file at the current position. -ILboolean ilIsValidTiffF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = ilisValidTiffFunc(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - -/*----------------------------------------------------------------------------*/ - -//! Checks if Lump is a valid Tiff lump. -ILboolean ilIsValidTiffL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return ilisValidTiffFunc(); -} - -/*----------------------------------------------------------------------------*/ - -//! Reads a Tiff file -ILboolean ilLoadTiff(ILconst_string FileName) -{ - ILHANDLE TiffFile; - ILboolean bTiff = IL_FALSE; - - TiffFile = iopenr(FileName); - if (TiffFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - } - else { - bTiff = ilLoadTiffF(TiffFile); - icloser(TiffFile); - } - - return bTiff; -} - -/*----------------------------------------------------------------------------*/ - -//! Reads an already-opened Tiff file -ILboolean ilLoadTiffF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadTiffInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - -/*----------------------------------------------------------------------------*/ - -//! Reads from a memory "lump" that contains a Tiff -ILboolean ilLoadTiffL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadTiffInternal(); -} - -/*----------------------------------------------------------------------------*/ - -void warningHandler(const char* mod, const char* fmt, va_list ap) -{ - mod; fmt; ap; - //char buff[1024]; - //vsnprintf(buff, 1024, fmt, ap); -} - -void errorHandler(const char* mod, const char* fmt, va_list ap) -{ - mod; fmt; ap; - //char buff[1024]; - //vsnprintf(buff, 1024, fmt, ap); -} - -//// - -/* -ILboolean iLoadTiffInternal (TIFF* tif, ILimage* Image) -{ - //// - - uint16 photometric, planarconfig, orientation; - uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; - uint32 w, h, d, linesize, tilewidth, tilelength; - ILushort si; - - //// - - TIFFSetDirectory(tif, directory); - //// - - // Process fields - - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); - - TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); //TODO: d is ignored... - TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); - TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); - TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); - TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation); - - linesize = TIFFScanlineSize(tif); - - TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric); - TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); - - tilewidth = w; tilelength = h; - TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tilewidth); - TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength); - - //// - - if (extrasamples != 0) { - return IL_FALSE; - } - - //// - - if (!Image) { - int type = IL_UNSIGNED_BYTE; - if (bitspersample == 16) type = IL_UNSIGNED_SHORT; - if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) { - TIFFClose(tif); - return IL_FALSE; - } - iCurImage->NumNext = 0; - Image = iCurImage; - } - else { - Image->Next = ilNewImage(w, h, 1, 1, 1); - if(Image->Next == NULL) { - TIFFClose(tif); - return IL_FALSE; - } - Image = Image->Next; - iCurImage->NumNext++; - } -} -*/ - -//// - - -// Internal function used to load the Tiff. -ILboolean iLoadTiffInternal() -{ - TIFF *tif; - uint16 photometric, planarconfig, orientation; - uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; - uint32 w, h, d, linesize, tilewidth, tilelength; - ILubyte *pImageData; - ILuint i, ProfileLen, DirCount = 0; - void *Buffer; - ILimage *Image, *TempImage; - ILushort si; - ILfloat x_position, x_resolution, y_position, y_resolution; - //TIFFRGBAImage img; - //char emsg[1024]; - - // to avoid high order bits garbage when used as shorts - w = h = d = linesize = tilewidth = tilelength = 0; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - TIFFSetWarningHandler (NULL); - TIFFSetErrorHandler (NULL); - - //for debugging only - //TIFFSetWarningHandler(warningHandler); - //TIFFSetErrorHandler(errorHandler); - - tif = iTIFFOpen("r"); - if (tif == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - do { - DirCount++; - } while (TIFFReadDirectory(tif)); - - /* - if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { - TIFFClose(tif); - return IL_FALSE; - } - Image = iCurImage; - for (i = 1; i < DirCount; i++) { - Image->Next = ilNewImage(1, 1, 1, 1, 1); - if (Image->Next == NULL) { - TIFFClose(tif); - return IL_FALSE; - } - Image = Image->Next; - } - iCurImage->NumNext = DirCount - 1; - */ - Image = NULL; - for (i = 0; i < DirCount; i++) { - TIFFSetDirectory(tif, (tdir_t)i); - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); - - TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); //TODO: d is ignored... - TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); - TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); - TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); - TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation); - - linesize = TIFFScanlineSize(tif); - - //added 2003-08-31 - //1 bpp tiffs are not neccessarily greyscale, they can - //have a palette (photometric == 3)...get this information - TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric); - TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); - - //special-case code for frequent data cases that may be read more - //efficiently than with the TIFFReadRGBAImage() interface. - - //added 2004-05-12 - //Get tile sizes and use TIFFReadRGBAImage() for tiled images for now - tilewidth = w; tilelength = h; - TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tilewidth); - TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength); - - - if (extrasamples == 0 - && samplesperpixel == 1 //luminance or palette - && (bitspersample == 8 || bitspersample == 1 || bitspersample == 16) - && (photometric == PHOTOMETRIC_MINISWHITE - || photometric == PHOTOMETRIC_MINISBLACK - || photometric == PHOTOMETRIC_PALETTE) - && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) - && tilewidth == w && tilelength == h - ) { - ILubyte* strip; - tsize_t stripsize; - ILuint y; - uint32 rowsperstrip, j, linesread; - - //TODO: 1 bit/pixel images should not be stored as 8 bits... - //(-> add new format) - if (!Image) { - int type = IL_UNSIGNED_BYTE; - if (bitspersample == 16) type = IL_UNSIGNED_SHORT; - if (!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) { - TIFFClose(tif); - return IL_FALSE; - } - Image = iCurImage; - } - else { - Image->Next = ilNewImage(w, h, 1, 1, 1); - if (Image->Next == NULL) { - TIFFClose(tif); - return IL_FALSE; - } - Image = Image->Next; - } - - if (photometric == PHOTOMETRIC_PALETTE) { //read palette - uint16 *red, *green, *blue; - //ILboolean is16bitpalette = IL_FALSE; - ILubyte *entry; - uint32 count = 1 << bitspersample, j; - - TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); - - Image->Format = IL_COLOUR_INDEX; - Image->Pal.PalSize = (count)*3; - Image->Pal.PalType = IL_PAL_RGB24; - Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); - entry = Image->Pal.Palette; - for (j = 0; j < count; ++j) { - entry[0] = (ILubyte)(red[j] >> 8); - entry[1] = (ILubyte)(green[j] >> 8); - entry[2] = (ILubyte)(blue[j] >> 8); - - entry += 3; - } - } - - TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - stripsize = TIFFStripSize(tif); - - strip = (ILubyte*)ialloc(stripsize); - - if (bitspersample == 8 || bitspersample == 16) { - ILubyte *dat = Image->Data; - for (y = 0; y < h; y += rowsperstrip) { - //the last strip may contain less data if the image - //height is not evenly divisible by rowsperstrip - if (y + rowsperstrip > h) { - stripsize = linesize*(h - y); - linesread = h - y; - } - else - linesread = rowsperstrip; - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { - ilSetError(IL_LIB_TIFF_ERROR); - ifree(strip); - TIFFClose(tif); - return IL_FALSE; - } - - if (photometric == PHOTOMETRIC_MINISWHITE) { //invert channel - uint32 k, t2; - for (j = 0; j < linesread; ++j) { - t2 = j*linesize; - //this works for 16bit images as well: the two bytes - //making up a pixel can be inverted independently - for (k = 0; k < Image->Bps; ++k) - dat[k] = ~strip[t2 + k]; - dat += w; - } - } - else - for(j = 0; j < linesread; ++j) - memcpy(&Image->Data[(y + j)*Image->Bps], &strip[j*linesize], Image->Bps); - } - } - else if (bitspersample == 1) { - //TODO: add a native format to devil, so we don't have to - //unpack the values here - ILubyte mask, curr, *dat = Image->Data; - uint32 k, sx, t2; - for (y = 0; y < h; y += rowsperstrip) { - //the last strip may contain less data if the image - //height is not evenly divisible by rowsperstrip - if (y + rowsperstrip > h) { - stripsize = linesize*(h - y); - linesread = h - y; - } - else - linesread = rowsperstrip; - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { - ilSetError(IL_LIB_TIFF_ERROR); - ifree(strip); - TIFFClose(tif); - return IL_FALSE; - } - - for (j = 0; j < linesread; ++j) { - k = 0; - sx = 0; - t2 = j*linesize; - while (k < w) { - curr = strip[t2 + sx]; - if (photometric == PHOTOMETRIC_MINISWHITE) - curr = ~curr; - for (mask = 0x80; mask != 0 && k < w; mask >>= 1){ - if((curr & mask) != 0) - dat[k] = 255; - else - dat[k] = 0; - ++k; - } - ++sx; - } - dat += w; - } - } - } - - ifree(strip); - - if(orientation == ORIENTATION_TOPLEFT) - Image->Origin = IL_ORIGIN_UPPER_LEFT; - else if(orientation == ORIENTATION_BOTLEFT) - Image->Origin = IL_ORIGIN_LOWER_LEFT; - } - //for 16bit rgb images: - else if (extrasamples == 0 - && samplesperpixel == 3 - && (bitspersample == 8 || bitspersample == 16) - && photometric == PHOTOMETRIC_RGB - && planarconfig == 1 - && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) - && tilewidth == w && tilelength == h - ) { - ILubyte *strip, *dat; - tsize_t stripsize; - ILuint y; - uint32 rowsperstrip, j, linesread; - - if (!Image) { - int type = IL_UNSIGNED_BYTE; - if (bitspersample == 16) type = IL_UNSIGNED_SHORT; - if(!ilTexImage(w, h, 1, 3, IL_RGB, type, NULL)) { - TIFFClose(tif); - return IL_FALSE; - } - Image = iCurImage; - } - else { - Image->Next = ilNewImage(w, h, 1, 1, 1); - if(Image->Next == NULL) { - TIFFClose(tif); - return IL_FALSE; - } - Image = Image->Next; - } - - TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - stripsize = TIFFStripSize(tif); - - strip = (ILubyte*)ialloc(stripsize); - - dat = Image->Data; - for (y = 0; y < h; y += rowsperstrip) { - //the last strip may contain less data if the image - //height is not evenly divisible by rowsperstrip - if (y + rowsperstrip > h) { - stripsize = linesize*(h - y); - linesread = h - y; - } - else - linesread = rowsperstrip; - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { - ilSetError(IL_LIB_TIFF_ERROR); - ifree(strip); - TIFFClose(tif); - return IL_FALSE; - } - - for(j = 0; j < linesread; ++j) - memcpy(&Image->Data[(y + j)*Image->Bps], &strip[j*linesize], Image->Bps); - } - - ifree(strip); - - if(orientation == ORIENTATION_TOPLEFT) - Image->Origin = IL_ORIGIN_UPPER_LEFT; - else if(orientation == ORIENTATION_BOTLEFT) - Image->Origin = IL_ORIGIN_LOWER_LEFT; - }/* - else if (extrasamples == 0 && samplesperpixel == 3 //rgb - && (bitspersample == 8 || bitspersample == 1 || bitspersample == 16) - && photometric == PHOTOMETRIC_RGB - && (planarconfig == PLANARCONFIG_CONTIG || planarcon - && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) - ) { - } - */ - else { - //not direclty supported format - if(!Image) { - if(!ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { - TIFFClose(tif); - return IL_FALSE; - } - Image = iCurImage; - } - else { - Image->Next = ilNewImage(w, h, 1, 4, 1); - if(Image->Next == NULL) { - TIFFClose(tif); - return IL_FALSE; - } - Image = Image->Next; - } - - if (samplesperpixel == 4) { - TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); - if (!sampleinfo || sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED) { - si = EXTRASAMPLE_ASSOCALPHA; - TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &si); - } - } - /* - if (!ilResizeImage(Image, Image->Width, Image->Height, 1, 4, 1)) { - TIFFClose(tif); - return IL_FALSE; - } - */ - Image->Format = IL_RGBA; - Image->Type = IL_UNSIGNED_BYTE; - - // Siigron: added u_long cast to shut up compiler warning - //2003-08-31: changed flag from 1 (exit on error) to 0 (keep decoding) - //this lets me view text.tif, but can give crashes with unsupported - //tiffs... - //2003-09-04: keep flag 1 for official version for now - if (!TIFFReadRGBAImage(tif, Image->Width, Image->Height, (uint32*)Image->Data, 0)) { - TIFFClose(tif); - ilSetError(IL_LIB_TIFF_ERROR); - return IL_FALSE; - } - Image->Origin = IL_ORIGIN_LOWER_LEFT; // eiu...dunno if this is right - -#ifdef __BIG_ENDIAN__ //TIFFReadRGBAImage reads abgr on big endian, convert to rgba - EndianSwapData(Image); -#endif - - /* - The following switch() should not be needed, - because we take care of the special cases that needed - these conversions. But since not all special cases - are handled right now, keep it :) - */ - //TODO: put switch into the loop?? - TempImage = iCurImage; - iCurImage = Image; //ilConvertImage() converts iCurImage - switch (samplesperpixel) - { - case 1: - //added 2003-08-31 to keep palettized tiffs colored - if(photometric != 3) - ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE); - else //strip alpha as tiff supports no alpha palettes - ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); - break; - - case 3: - //TODO: why the ifdef?? -#ifdef __LITTLE_ENDIAN__ - ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); -#endif - break; - - case 4: - pImageData = Image->Data; - //removed on 2003-08-26...why was this here? libtiff should and does - //take care of these things??? - /* - //invert alpha -#ifdef __LITTLE_ENDIAN__ - pImageData += 3; -#endif - for (i = Image->Width * Image->Height; i > 0; i--) { - *pImageData ^= 255; - pImageData += 4; - } - */ - break; - } - iCurImage = TempImage; - - } //else not directly supported format - - if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &ProfileLen, &Buffer)) { - if (Image->Profile && Image->ProfileSize) - ifree(Image->Profile); - Image->Profile = (ILubyte*)ialloc(ProfileLen); - if (Image->Profile == NULL) { - TIFFClose(tif); - return IL_FALSE; - } - - memcpy(Image->Profile, Buffer, ProfileLen); - Image->ProfileSize = ProfileLen; - - //removed on 2003-08-24 as explained in bug 579574 on sourceforge - //_TIFFfree(Buffer); - } - - // dangelo: read offset from tiff tags. - //If nothing is stored in these tags, then this must be an "uncropped" TIFF - //file, in which case, the "full size" width/height is the same as the - //"cropped" width and height - // - // the full size is currently not supported by DevIL - //if (TIFFGetField(tif, TIFFTAG_PIXAR_IMAGEFULLWIDTH, &(c->full_width)) == - // 0) - // (c->full_width = c->cropped_width); - //if (TIFFGetField(tif, TIFFTAG_PIXAR_IMAGEFULLLENGTH, &(c->full_height)) == - // 0) - // (c->full_height = c->cropped_height); - - if (TIFFGetField(tif, TIFFTAG_XPOSITION, &x_position) == 0) - x_position = 0; - if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &x_resolution) == 0) - x_resolution = 0; - if (TIFFGetField(tif, TIFFTAG_YPOSITION, &y_position) == 0) - y_position = 0; - if (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &y_resolution) == 0) - y_resolution = 0; - - //offset in pixels of "cropped" image from top left corner of - //full image (rounded to nearest integer) - Image->OffX = (uint32) ((x_position * x_resolution) + 0.49); - Image->OffY = (uint32) ((y_position * y_resolution) + 0.49); - - - /* - Image = Image->Next; - if (Image == NULL) // Should never happen except when we reach the end, but check anyway. - break; - */ - } //for tiff directories - - TIFFClose(tif); - - return ilFixImage(); -} - -/*----------------------------------------------------------------------------*/ - -///////////////////////////////////////////////////////////////////////////////////////// -// Extension to load tiff files from memory -// Marco Fabbricatore (fabbrica@ai-lab.fh-furtwangen.de) -///////////////////////////////////////////////////////////////////////////////////////// - -static tsize_t -_tiffFileReadProc(thandle_t fd, tdata_t pData, tsize_t tSize) -{ - fd; - return iread(pData, 1, tSize); -} - -/*----------------------------------------------------------------------------*/ - -// We have trouble sometimes reading when writing a file. Specifically, the only time -// I have seen libtiff call this is at the beginning of writing a tiff, before -// anything is ever even written! Also, we have to return 0, no matter what tSize -// is. If we return tSize like would be expected, then TIFFClientOpen fails. -static tsize_t -_tiffFileReadProcW(thandle_t fd, tdata_t pData, tsize_t tSize) -{ - fd; - return 0; -} - -/*----------------------------------------------------------------------------*/ - -static tsize_t -_tiffFileWriteProc(thandle_t fd, tdata_t pData, tsize_t tSize) -{ - fd; - return iwrite(pData, 1, tSize); -} - -/*----------------------------------------------------------------------------*/ - -static toff_t -_tiffFileSeekProc(thandle_t fd, toff_t tOff, int whence) -{ - fd; - /* we use this as a special code, so avoid accepting it */ - if (tOff == 0xFFFFFFFF) - return 0xFFFFFFFF; - - iseek(tOff, whence); - return itell(); - //return tOff; -} - -/*----------------------------------------------------------------------------*/ - -static toff_t -_tiffFileSeekProcW(thandle_t fd, toff_t tOff, int whence) -{ - /* we use this as a special code, so avoid accepting it */ - if (tOff == 0xFFFFFFFF) - return 0xFFFFFFFF; - - iseekw(tOff, whence); - return itellw(); - //return tOff; -} - -/*----------------------------------------------------------------------------*/ - -static int -_tiffFileCloseProc(thandle_t fd) -{ - fd; - return (0); -} - -/*----------------------------------------------------------------------------*/ - -static toff_t -_tiffFileSizeProc(thandle_t fd) -{ - ILint Offset, Size; - Offset = itell(); - iseek(0, IL_SEEK_END); - Size = itell(); - iseek(Offset, IL_SEEK_SET); - - fd; - - return Size; -} - -/*----------------------------------------------------------------------------*/ - -static toff_t -_tiffFileSizeProcW(thandle_t fd) -{ - ILint Offset, Size; - Offset = itellw(); - iseekw(0, IL_SEEK_END); - Size = itellw(); - iseekw(Offset, IL_SEEK_SET); - - return Size; -} - -/*----------------------------------------------------------------------------*/ - -#ifdef __BORLANDC__ -#pragma argsused -#endif -static int -_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) -{ - fd; pbase; psize; - return 0; -} - -/*----------------------------------------------------------------------------*/ - -#ifdef __BORLANDC__ -#pragma argsused -#endif -static void -_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) -{ - fd; base; size; - return; -} - -/*----------------------------------------------------------------------------*/ - -TIFF *iTIFFOpen(char *Mode) -{ - TIFF *tif; - - if (Mode[0] == 'w') - tif = TIFFClientOpen("TIFFMemFile", Mode, - NULL, - _tiffFileReadProcW, _tiffFileWriteProc, - _tiffFileSeekProcW, _tiffFileCloseProc, - _tiffFileSizeProcW, _tiffDummyMapProc, - _tiffDummyUnmapProc); - else - tif = TIFFClientOpen("TIFFMemFile", Mode, - NULL, - _tiffFileReadProc, _tiffFileWriteProc, - _tiffFileSeekProc, _tiffFileCloseProc, - _tiffFileSizeProc, _tiffDummyMapProc, - _tiffDummyUnmapProc); - - return tif; -} - -/*----------------------------------------------------------------------------*/ - - -//! Writes a Tiff file -ILboolean ilSaveTiff(const ILstring FileName) -{ - ILHANDLE TiffFile; - ILuint TiffSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - TiffFile = iopenw(FileName); - if (TiffFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - TiffSize = ilSaveTiffF(TiffFile); - iclosew(TiffFile); - - if (TiffSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a Tiff to an already-opened file -ILuint ilSaveTiffF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveTiffInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a Tiff to a memory "lump" -ILuint ilSaveTiffL(void *Lump, ILuint Size) -{ - ILuint Pos = itellw(); - iSetOutputLump(Lump, Size); - if (iSaveTiffInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// @TODO: Accept palettes! - -// Internal function used to save the Tiff. -ILboolean iSaveTiffInternal(/*ILconst_string Filename*/) -{ - ILenum Format; - ILenum Compression; - ILuint ixLine; - TIFF *File; - char Description[512]; - ILimage *TempImage; - const char *str; - ILboolean SwapColors; - ILubyte *OldData; - - if(iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - -#if 1 - TIFFSetWarningHandler (NULL); - TIFFSetErrorHandler (NULL); -#else - //for debugging only - TIFFSetWarningHandler(warningHandler); - TIFFSetErrorHandler(errorHandler); -#endif - if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) - Compression = COMPRESSION_LZW; - else - Compression = COMPRESSION_NONE; - - if (iCurImage->Format == IL_COLOUR_INDEX) { - if (ilGetBppPal(iCurImage->Pal.PalType) == 4) // Preserve the alpha. - TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); - else - TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); - - if (TempImage == NULL) { - return IL_FALSE; - } - } - else { - TempImage = iCurImage; - } - - /*#ifndef _UNICODE - File = TIFFOpen(Filename, "w"); - #else - File = TIFFOpenW(Filename, "w"); - #endif*/ - - // Control writing functions ourself. - File = iTIFFOpen("w"); - if (File == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - sprintf(Description, "Tiff generated by %s", ilGetString(IL_VERSION_NUM)); - - TIFFSetField(File, TIFFTAG_IMAGEWIDTH, TempImage->Width); - TIFFSetField(File, TIFFTAG_IMAGELENGTH, TempImage->Height); - TIFFSetField(File, TIFFTAG_COMPRESSION, Compression); - TIFFSetField(File, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); - TIFFSetField(File, TIFFTAG_BITSPERSAMPLE, TempImage->Bpc << 3); - TIFFSetField(File, TIFFTAG_SAMPLESPERPIXEL, TempImage->Bpp); - if (TempImage->Bpp == 4) //TODO: LUMINANCE, LUMINANCE_ALPHA - TIFFSetField(File, TIFFTAG_MATTEING, 1); - TIFFSetField(File, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(File, TIFFTAG_ROWSPERSTRIP, 1); - TIFFSetField(File, TIFFTAG_SOFTWARE, ilGetString(IL_VERSION_NUM)); - /*TIFFSetField(File, TIFFTAG_DOCUMENTNAME, - iGetString(IL_TIF_DOCUMENTNAME_STRING) ? - iGetString(IL_TIF_DOCUMENTNAME_STRING) : FileName); -*/ - str = iGetString(IL_TIF_DOCUMENTNAME_STRING); - if (str) { - TIFFSetField(File, TIFFTAG_DOCUMENTNAME, str); - ifree(str); - } - - - str = iGetString(IL_TIF_AUTHNAME_STRING); - if (iGetString(IL_TIF_AUTHNAME_STRING)) { - TIFFSetField(File, TIFFTAG_ARTIST, str); - ifree(str); - } - - str = iGetString(IL_TIF_HOSTCOMPUTER_STRING); - if (str) { - TIFFSetField(File, TIFFTAG_HOSTCOMPUTER, str); - ifree(str); - } - - str = iGetString(IL_TIF_HOSTCOMPUTER_STRING); - if (str) { - TIFFSetField(File, TIFFTAG_IMAGEDESCRIPTION, str); - ifree(str); - } - - // Set the date and time string. - TIFFSetField(File, TIFFTAG_DATETIME, iMakeString()); - - // 24/4/2003 - // Orientation flag is not always supported (Photoshop, ...), orient the image data - // and set it always to normal view - TIFFSetField(File, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); - if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { - ILubyte* Data = iGetFlipped(TempImage); - OldData = TempImage->Data; - TempImage->Data = Data; - } - else - OldData = TempImage->Data; - - /* - TIFFSetField(File, TIFFTAG_ORIENTATION, - TempImage->Origin == IL_ORIGIN_UPPER_LEFT ? ORIENTATION_TOPLEFT : ORIENTATION_BOTLEFT); - */ - - Format = TempImage->Format; - SwapColors = (Format == IL_BGR || Format == IL_BGRA); - if (SwapColors) - ilSwapColours(); - - for (ixLine = 0; ixLine < TempImage->Height; ++ixLine) { - if (TIFFWriteScanline(File, TempImage->Data + ixLine * TempImage->Bps, ixLine, 0) < 0) { - TIFFClose(File); - ilSetError(IL_LIB_TIFF_ERROR); - if (SwapColors) - ilSwapColours(); - if (TempImage->Data != OldData) { - ifree( TempImage->Data ); - TempImage->Data = OldData; - } - if (TempImage != iCurImage) - ilCloseImage(TempImage); - return IL_FALSE; - } - } - - if (SwapColors) - ilSwapColours(); - - if (TempImage->Data != OldData) { - ifree(TempImage->Data); - TempImage->Data = OldData; - } - - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - TIFFClose(File); - - return IL_TRUE; -} - -/*----------------------------------------------------------------------------*/ -// Makes a neat date string for the date field. -// From http://www.awaresystems.be/imaging/tiff/tifftags/datetime.html : -// The format is: "YYYY:MM:DD HH:MM:SS", with hours like those on -// a 24-hour clock, and one space character between the date and the -// time. The length of the string, including the terminating NUL, is -// 20 bytes.) -char *iMakeString() -{ - static char TimeStr[20]; - time_t Time; - struct tm *CurTime; - - imemclear(TimeStr, 20); - - time(&Time); -#ifdef _WIN32 - _tzset(); -#endif - CurTime = localtime(&Time); - - strftime(TimeStr, 20, "%Y:%m:%d %H:%M:%S", CurTime); - - return TimeStr; -} - -/*----------------------------------------------------------------------------*/ - -#endif//IL_NO_TIF diff --git a/DevIL/src-IL/src/il_tiff.cpp b/DevIL/src-IL/src/il_tiff.cpp new file mode 100644 index 00000000..6febc9c7 --- /dev/null +++ b/DevIL/src-IL/src/il_tiff.cpp @@ -0,0 +1,1112 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_tiff.c +// +// Description: Tiff (.tif) functions +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_TIF + +#include "tiffio.h" + +#include + +#define MAGIC_HEADER1 0x4949 +#define MAGIC_HEADER2 0x4D4D + + +#if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "tiff.lib") + #else + //#pragma comment(lib, "tiff-d.lib") + #pragma comment(lib, "tiff.lib") + #endif + #endif +#endif + + +/*----------------------------------------------------------------------------*/ + +// No need for a separate header +static ILboolean iLoadTiffInternal(void); +static char* iMakeString(void); +static TIFF* iTIFFOpen(char *Mode); +static ILboolean iSaveTiffInternal(/*ILconst_string Filename*/); + +/*----------------------------------------------------------------------------*/ + +ILboolean ilisValidTiffExtension(ILconst_string FileName) +{ + if (!iCheckExtension((ILstring)FileName, IL_TEXT("tif")) && + !iCheckExtension((ILstring)FileName, IL_TEXT("tiff"))) + return IL_FALSE; + else + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +//! Checks if the file specified in FileName is a valid tiff file. +ILboolean ilIsValidTiff(ILconst_string FileName) +{ + ILHANDLE TiffFile; + ILboolean bTiff = IL_FALSE; + + if (!ilisValidTiffExtension((ILstring) FileName)) { + ilSetError(IL_INVALID_EXTENSION); + return bTiff; + } + + TiffFile = iopenr((ILstring)FileName); + if (TiffFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bTiff; + } + + bTiff = ilIsValidTiffF(TiffFile); + icloser(TiffFile); + + return bTiff; +} + +/*----------------------------------------------------------------------------*/ + +ILboolean ilisValidTiffFunc() +{ + ILushort Header1, Header2; + + Header1 = GetLittleUShort(); + + if (Header1 != MAGIC_HEADER1 && Header1 != MAGIC_HEADER2) + return IL_FALSE; + + if (Header1 == MAGIC_HEADER1) + Header2 = GetLittleUShort(); + else + Header2 = GetBigUShort(); + + if (Header2 != 42) + return IL_FALSE; + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ + +//! Checks if the ILHANDLE contains a valid tiff file at the current position. +ILboolean ilIsValidTiffF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = ilisValidTiffFunc(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ + +//! Checks if Lump is a valid Tiff lump. +ILboolean ilIsValidTiffL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return ilisValidTiffFunc(); +} + +/*----------------------------------------------------------------------------*/ + +//! Reads a Tiff file +ILboolean ilLoadTiff(ILconst_string FileName) +{ + ILHANDLE TiffFile; + ILboolean bTiff = IL_FALSE; + + TiffFile = iopenr(FileName); + if (TiffFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + } + else { + bTiff = ilLoadTiffF(TiffFile); + icloser(TiffFile); + } + + return bTiff; +} + +/*----------------------------------------------------------------------------*/ + +//! Reads an already-opened Tiff file +ILboolean ilLoadTiffF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadTiffInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + +/*----------------------------------------------------------------------------*/ + +//! Reads from a memory "lump" that contains a Tiff +ILboolean ilLoadTiffL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadTiffInternal(); +} + +/*----------------------------------------------------------------------------*/ + +void warningHandler(const char* mod, const char* fmt, va_list ap) +{ + mod; fmt; ap; + //char buff[1024]; + //vsnprintf(buff, 1024, fmt, ap); +} + +void errorHandler(const char* mod, const char* fmt, va_list ap) +{ + mod; fmt; ap; + //char buff[1024]; + //vsnprintf(buff, 1024, fmt, ap); +} + +//// + +/* +ILboolean iLoadTiffInternal (TIFF* tif, ILimage* Image) +{ + //// + + uint16 photometric, planarconfig, orientation; + uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; + uint32 w, h, d, linesize, tilewidth, tilelength; + ILushort si; + + //// + + TIFFSetDirectory(tif, directory); + //// + + // Process fields + + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); + + TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); //TODO: d is ignored... + TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); + TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); + TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation); + + linesize = TIFFScanlineSize(tif); + + TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric); + TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); + + tilewidth = w; tilelength = h; + TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tilewidth); + TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength); + + //// + + if (extrasamples != 0) { + return IL_FALSE; + } + + //// + + if (!Image) { + int type = IL_UNSIGNED_BYTE; + if (bitspersample == 16) type = IL_UNSIGNED_SHORT; + if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) { + TIFFClose(tif); + return IL_FALSE; + } + iCurImage->NumNext = 0; + Image = iCurImage; + } + else { + Image->Next = ilNewImage(w, h, 1, 1, 1); + if(Image->Next == NULL) { + TIFFClose(tif); + return IL_FALSE; + } + Image = Image->Next; + iCurImage->NumNext++; + } +} +*/ + +//// + + +// Internal function used to load the Tiff. +ILboolean iLoadTiffInternal() +{ + TIFF *tif; + uint16 photometric, planarconfig, orientation; + uint16 samplesperpixel, bitspersample, *sampleinfo, extrasamples; + uint32 w, h, d, linesize, tilewidth, tilelength; + ILubyte *pImageData; + ILuint i, ProfileLen, DirCount = 0; + void *Buffer; + ILimage *Image, *TempImage; + ILushort si; + ILfloat x_position, x_resolution, y_position, y_resolution; + //TIFFRGBAImage img; + //char emsg[1024]; + + // to avoid high order bits garbage when used as shorts + w = h = d = linesize = tilewidth = tilelength = 0; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + TIFFSetWarningHandler (NULL); + TIFFSetErrorHandler (NULL); + + //for debugging only + //TIFFSetWarningHandler(warningHandler); + //TIFFSetErrorHandler(errorHandler); + + tif = iTIFFOpen("r"); + if (tif == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + do { + DirCount++; + } while (TIFFReadDirectory(tif)); + + /* + if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { + TIFFClose(tif); + return IL_FALSE; + } + Image = iCurImage; + for (i = 1; i < DirCount; i++) { + Image->Next = ilNewImage(1, 1, 1, 1, 1); + if (Image->Next == NULL) { + TIFFClose(tif); + return IL_FALSE; + } + Image = Image->Next; + } + iCurImage->NumNext = DirCount - 1; + */ + Image = NULL; + for (i = 0; i < DirCount; i++) { + TIFFSetDirectory(tif, (tdir_t)i); + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); + + TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d); //TODO: d is ignored... + TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); + TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample); + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); + TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation); + + linesize = TIFFScanlineSize(tif); + + //added 2003-08-31 + //1 bpp tiffs are not neccessarily greyscale, they can + //have a palette (photometric == 3)...get this information + TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric); + TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); + + //special-case code for frequent data cases that may be read more + //efficiently than with the TIFFReadRGBAImage() interface. + + //added 2004-05-12 + //Get tile sizes and use TIFFReadRGBAImage() for tiled images for now + tilewidth = w; tilelength = h; + TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tilewidth); + TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength); + + + if (extrasamples == 0 + && samplesperpixel == 1 //luminance or palette + && (bitspersample == 8 || bitspersample == 1 || bitspersample == 16) + && (photometric == PHOTOMETRIC_MINISWHITE + || photometric == PHOTOMETRIC_MINISBLACK + || photometric == PHOTOMETRIC_PALETTE) + && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) + && tilewidth == w && tilelength == h + ) { + ILubyte* strip; + tsize_t stripsize; + ILuint y; + uint32 rowsperstrip, j, linesread; + + //TODO: 1 bit/pixel images should not be stored as 8 bits... + //(-> add new format) + if (!Image) { + int type = IL_UNSIGNED_BYTE; + if (bitspersample == 16) type = IL_UNSIGNED_SHORT; + if (!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) { + TIFFClose(tif); + return IL_FALSE; + } + Image = iCurImage; + } + else { + Image->Next = ilNewImage(w, h, 1, 1, 1); + if (Image->Next == NULL) { + TIFFClose(tif); + return IL_FALSE; + } + Image = Image->Next; + } + + if (photometric == PHOTOMETRIC_PALETTE) { //read palette + uint16 *red, *green, *blue; + //ILboolean is16bitpalette = IL_FALSE; + ILubyte *entry; + uint32 count = 1 << bitspersample, j; + + TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); + + Image->Format = IL_COLOUR_INDEX; + Image->Pal.PalSize = (count)*3; + Image->Pal.PalType = IL_PAL_RGB24; + Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); + entry = Image->Pal.Palette; + for (j = 0; j < count; ++j) { + entry[0] = (ILubyte)(red[j] >> 8); + entry[1] = (ILubyte)(green[j] >> 8); + entry[2] = (ILubyte)(blue[j] >> 8); + + entry += 3; + } + } + + TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + stripsize = TIFFStripSize(tif); + + strip = (ILubyte*)ialloc(stripsize); + + if (bitspersample == 8 || bitspersample == 16) { + ILubyte *dat = Image->Data; + for (y = 0; y < h; y += rowsperstrip) { + //the last strip may contain less data if the image + //height is not evenly divisible by rowsperstrip + if (y + rowsperstrip > h) { + stripsize = linesize*(h - y); + linesread = h - y; + } + else + linesread = rowsperstrip; + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { + ilSetError(IL_LIB_TIFF_ERROR); + ifree(strip); + TIFFClose(tif); + return IL_FALSE; + } + + if (photometric == PHOTOMETRIC_MINISWHITE) { //invert channel + uint32 k, t2; + for (j = 0; j < linesread; ++j) { + t2 = j*linesize; + //this works for 16bit images as well: the two bytes + //making up a pixel can be inverted independently + for (k = 0; k < Image->Bps; ++k) + dat[k] = ~strip[t2 + k]; + dat += w; + } + } + else + for(j = 0; j < linesread; ++j) + memcpy(&Image->Data[(y + j)*Image->Bps], &strip[j*linesize], Image->Bps); + } + } + else if (bitspersample == 1) { + //TODO: add a native format to devil, so we don't have to + //unpack the values here + ILubyte mask, curr, *dat = Image->Data; + uint32 k, sx, t2; + for (y = 0; y < h; y += rowsperstrip) { + //the last strip may contain less data if the image + //height is not evenly divisible by rowsperstrip + if (y + rowsperstrip > h) { + stripsize = linesize*(h - y); + linesread = h - y; + } + else + linesread = rowsperstrip; + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { + ilSetError(IL_LIB_TIFF_ERROR); + ifree(strip); + TIFFClose(tif); + return IL_FALSE; + } + + for (j = 0; j < linesread; ++j) { + k = 0; + sx = 0; + t2 = j*linesize; + while (k < w) { + curr = strip[t2 + sx]; + if (photometric == PHOTOMETRIC_MINISWHITE) + curr = ~curr; + for (mask = 0x80; mask != 0 && k < w; mask >>= 1){ + if((curr & mask) != 0) + dat[k] = 255; + else + dat[k] = 0; + ++k; + } + ++sx; + } + dat += w; + } + } + } + + ifree(strip); + + if(orientation == ORIENTATION_TOPLEFT) + Image->Origin = IL_ORIGIN_UPPER_LEFT; + else if(orientation == ORIENTATION_BOTLEFT) + Image->Origin = IL_ORIGIN_LOWER_LEFT; + } + //for 16bit rgb images: + else if (extrasamples == 0 + && samplesperpixel == 3 + && (bitspersample == 8 || bitspersample == 16) + && photometric == PHOTOMETRIC_RGB + && planarconfig == 1 + && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) + && tilewidth == w && tilelength == h + ) { + ILubyte *strip, *dat; + tsize_t stripsize; + ILuint y; + uint32 rowsperstrip, j, linesread; + + if (!Image) { + int type = IL_UNSIGNED_BYTE; + if (bitspersample == 16) type = IL_UNSIGNED_SHORT; + if(!ilTexImage(w, h, 1, 3, IL_RGB, type, NULL)) { + TIFFClose(tif); + return IL_FALSE; + } + Image = iCurImage; + } + else { + Image->Next = ilNewImage(w, h, 1, 1, 1); + if(Image->Next == NULL) { + TIFFClose(tif); + return IL_FALSE; + } + Image = Image->Next; + } + + TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + stripsize = TIFFStripSize(tif); + + strip = (ILubyte*)ialloc(stripsize); + + dat = Image->Data; + for (y = 0; y < h; y += rowsperstrip) { + //the last strip may contain less data if the image + //height is not evenly divisible by rowsperstrip + if (y + rowsperstrip > h) { + stripsize = linesize*(h - y); + linesread = h - y; + } + else + linesread = rowsperstrip; + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) { + ilSetError(IL_LIB_TIFF_ERROR); + ifree(strip); + TIFFClose(tif); + return IL_FALSE; + } + + for(j = 0; j < linesread; ++j) + memcpy(&Image->Data[(y + j)*Image->Bps], &strip[j*linesize], Image->Bps); + } + + ifree(strip); + + if(orientation == ORIENTATION_TOPLEFT) + Image->Origin = IL_ORIGIN_UPPER_LEFT; + else if(orientation == ORIENTATION_BOTLEFT) + Image->Origin = IL_ORIGIN_LOWER_LEFT; + }/* + else if (extrasamples == 0 && samplesperpixel == 3 //rgb + && (bitspersample == 8 || bitspersample == 1 || bitspersample == 16) + && photometric == PHOTOMETRIC_RGB + && (planarconfig == PLANARCONFIG_CONTIG || planarcon + && (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT) + ) { + } + */ + else { + //not direclty supported format + if(!Image) { + if(!ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { + TIFFClose(tif); + return IL_FALSE; + } + Image = iCurImage; + } + else { + Image->Next = ilNewImage(w, h, 1, 4, 1); + if(Image->Next == NULL) { + TIFFClose(tif); + return IL_FALSE; + } + Image = Image->Next; + } + + if (samplesperpixel == 4) { + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo); + if (!sampleinfo || sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED) { + si = EXTRASAMPLE_ASSOCALPHA; + TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &si); + } + } + /* + if (!ilResizeImage(Image, Image->Width, Image->Height, 1, 4, 1)) { + TIFFClose(tif); + return IL_FALSE; + } + */ + Image->Format = IL_RGBA; + Image->Type = IL_UNSIGNED_BYTE; + + // Siigron: added u_long cast to shut up compiler warning + //2003-08-31: changed flag from 1 (exit on error) to 0 (keep decoding) + //this lets me view text.tif, but can give crashes with unsupported + //tiffs... + //2003-09-04: keep flag 1 for official version for now + if (!TIFFReadRGBAImage(tif, Image->Width, Image->Height, (uint32*)Image->Data, 0)) { + TIFFClose(tif); + ilSetError(IL_LIB_TIFF_ERROR); + return IL_FALSE; + } + Image->Origin = IL_ORIGIN_LOWER_LEFT; // eiu...dunno if this is right + +#ifdef __BIG_ENDIAN__ //TIFFReadRGBAImage reads abgr on big endian, convert to rgba + EndianSwapData(Image); +#endif + + /* + The following switch() should not be needed, + because we take care of the special cases that needed + these conversions. But since not all special cases + are handled right now, keep it :) + */ + //TODO: put switch into the loop?? + TempImage = iCurImage; + iCurImage = Image; //ilConvertImage() converts iCurImage + switch (samplesperpixel) + { + case 1: + //added 2003-08-31 to keep palettized tiffs colored + if(photometric != 3) + ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE); + else //strip alpha as tiff supports no alpha palettes + ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); + break; + + case 3: + //TODO: why the ifdef?? +#ifdef __LITTLE_ENDIAN__ + ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); +#endif + break; + + case 4: + pImageData = Image->Data; + //removed on 2003-08-26...why was this here? libtiff should and does + //take care of these things??? + /* + //invert alpha +#ifdef __LITTLE_ENDIAN__ + pImageData += 3; +#endif + for (i = Image->Width * Image->Height; i > 0; i--) { + *pImageData ^= 255; + pImageData += 4; + } + */ + break; + } + iCurImage = TempImage; + + } //else not directly supported format + + if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &ProfileLen, &Buffer)) { + if (Image->Profile && Image->ProfileSize) + ifree(Image->Profile); + Image->Profile = (ILubyte*)ialloc(ProfileLen); + if (Image->Profile == NULL) { + TIFFClose(tif); + return IL_FALSE; + } + + memcpy(Image->Profile, Buffer, ProfileLen); + Image->ProfileSize = ProfileLen; + + //removed on 2003-08-24 as explained in bug 579574 on sourceforge + //_TIFFfree(Buffer); + } + + // dangelo: read offset from tiff tags. + //If nothing is stored in these tags, then this must be an "uncropped" TIFF + //file, in which case, the "full size" width/height is the same as the + //"cropped" width and height + // + // the full size is currently not supported by DevIL + //if (TIFFGetField(tif, TIFFTAG_PIXAR_IMAGEFULLWIDTH, &(c->full_width)) == + // 0) + // (c->full_width = c->cropped_width); + //if (TIFFGetField(tif, TIFFTAG_PIXAR_IMAGEFULLLENGTH, &(c->full_height)) == + // 0) + // (c->full_height = c->cropped_height); + + if (TIFFGetField(tif, TIFFTAG_XPOSITION, &x_position) == 0) + x_position = 0; + if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &x_resolution) == 0) + x_resolution = 0; + if (TIFFGetField(tif, TIFFTAG_YPOSITION, &y_position) == 0) + y_position = 0; + if (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &y_resolution) == 0) + y_resolution = 0; + + //offset in pixels of "cropped" image from top left corner of + //full image (rounded to nearest integer) + Image->OffX = (uint32) ((x_position * x_resolution) + 0.49); + Image->OffY = (uint32) ((y_position * y_resolution) + 0.49); + + + /* + Image = Image->Next; + if (Image == NULL) // Should never happen except when we reach the end, but check anyway. + break; + */ + } //for tiff directories + + TIFFClose(tif); + + return ilFixImage(); +} + +/*----------------------------------------------------------------------------*/ + +///////////////////////////////////////////////////////////////////////////////////////// +// Extension to load tiff files from memory +// Marco Fabbricatore (fabbrica@ai-lab.fh-furtwangen.de) +///////////////////////////////////////////////////////////////////////////////////////// + +static tsize_t +_tiffFileReadProc(thandle_t fd, tdata_t pData, tsize_t tSize) +{ + fd; + return iread(pData, 1, tSize); +} + +/*----------------------------------------------------------------------------*/ + +// We have trouble sometimes reading when writing a file. Specifically, the only time +// I have seen libtiff call this is at the beginning of writing a tiff, before +// anything is ever even written! Also, we have to return 0, no matter what tSize +// is. If we return tSize like would be expected, then TIFFClientOpen fails. +static tsize_t +_tiffFileReadProcW(thandle_t fd, tdata_t pData, tsize_t tSize) +{ + fd; + return 0; +} + +/*----------------------------------------------------------------------------*/ + +static tsize_t +_tiffFileWriteProc(thandle_t fd, tdata_t pData, tsize_t tSize) +{ + fd; + return iwrite(pData, 1, tSize); +} + +/*----------------------------------------------------------------------------*/ + +static toff_t +_tiffFileSeekProc(thandle_t fd, toff_t tOff, int whence) +{ + fd; + /* we use this as a special code, so avoid accepting it */ + if (tOff == 0xFFFFFFFF) + return 0xFFFFFFFF; + + iseek(tOff, whence); + return itell(); + //return tOff; +} + +/*----------------------------------------------------------------------------*/ + +static toff_t +_tiffFileSeekProcW(thandle_t fd, toff_t tOff, int whence) +{ + /* we use this as a special code, so avoid accepting it */ + if (tOff == 0xFFFFFFFF) + return 0xFFFFFFFF; + + iseekw(tOff, whence); + return itellw(); + //return tOff; +} + +/*----------------------------------------------------------------------------*/ + +static int +_tiffFileCloseProc(thandle_t fd) +{ + fd; + return (0); +} + +/*----------------------------------------------------------------------------*/ + +static toff_t +_tiffFileSizeProc(thandle_t fd) +{ + ILint Offset, Size; + Offset = itell(); + iseek(0, IL_SEEK_END); + Size = itell(); + iseek(Offset, IL_SEEK_SET); + + fd; + + return Size; +} + +/*----------------------------------------------------------------------------*/ + +static toff_t +_tiffFileSizeProcW(thandle_t fd) +{ + ILint Offset, Size; + Offset = itellw(); + iseekw(0, IL_SEEK_END); + Size = itellw(); + iseekw(Offset, IL_SEEK_SET); + + return Size; +} + +/*----------------------------------------------------------------------------*/ + +#ifdef __BORLANDC__ +#pragma argsused +#endif +static int +_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + fd; pbase; psize; + return 0; +} + +/*----------------------------------------------------------------------------*/ + +#ifdef __BORLANDC__ +#pragma argsused +#endif +static void +_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + fd; base; size; + return; +} + +/*----------------------------------------------------------------------------*/ + +TIFF *iTIFFOpen(char *Mode) +{ + TIFF *tif; + + if (Mode[0] == 'w') + tif = TIFFClientOpen("TIFFMemFile", Mode, + NULL, + _tiffFileReadProcW, _tiffFileWriteProc, + _tiffFileSeekProcW, _tiffFileCloseProc, + _tiffFileSizeProcW, _tiffDummyMapProc, + _tiffDummyUnmapProc); + else + tif = TIFFClientOpen("TIFFMemFile", Mode, + NULL, + _tiffFileReadProc, _tiffFileWriteProc, + _tiffFileSeekProc, _tiffFileCloseProc, + _tiffFileSizeProc, _tiffDummyMapProc, + _tiffDummyUnmapProc); + + return tif; +} + +/*----------------------------------------------------------------------------*/ + + +//! Writes a Tiff file +ILboolean ilSaveTiff(const ILstring FileName) +{ + ILHANDLE TiffFile; + ILuint TiffSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + TiffFile = iopenw(FileName); + if (TiffFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + TiffSize = ilSaveTiffF(TiffFile); + iclosew(TiffFile); + + if (TiffSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a Tiff to an already-opened file +ILuint ilSaveTiffF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveTiffInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a Tiff to a memory "lump" +ILuint ilSaveTiffL(void *Lump, ILuint Size) +{ + ILuint Pos = itellw(); + iSetOutputLump(Lump, Size); + if (iSaveTiffInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// @TODO: Accept palettes! + +// Internal function used to save the Tiff. +ILboolean iSaveTiffInternal(/*ILconst_string Filename*/) +{ + ILenum Format; + ILenum Compression; + ILuint ixLine; + TIFF *File; + char Description[512]; + ILimage *TempImage; + const char *str; + ILboolean SwapColors; + ILubyte *OldData; + + if(iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + +#if 1 + TIFFSetWarningHandler (NULL); + TIFFSetErrorHandler (NULL); +#else + //for debugging only + TIFFSetWarningHandler(warningHandler); + TIFFSetErrorHandler(errorHandler); +#endif + if (iGetHint(IL_COMPRESSION_HINT) == IL_USE_COMPRESSION) + Compression = COMPRESSION_LZW; + else + Compression = COMPRESSION_NONE; + + if (iCurImage->Format == IL_COLOUR_INDEX) { + if (ilGetBppPal(iCurImage->Pal.PalType) == 4) // Preserve the alpha. + TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE); + else + TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE); + + if (TempImage == NULL) { + return IL_FALSE; + } + } + else { + TempImage = iCurImage; + } + + /*#ifndef _UNICODE + File = TIFFOpen(Filename, "w"); + #else + File = TIFFOpenW(Filename, "w"); + #endif*/ + + // Control writing functions ourself. + File = iTIFFOpen("w"); + if (File == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + sprintf(Description, "Tiff generated by %s", ilGetString(IL_VERSION_NUM)); + + TIFFSetField(File, TIFFTAG_IMAGEWIDTH, TempImage->Width); + TIFFSetField(File, TIFFTAG_IMAGELENGTH, TempImage->Height); + TIFFSetField(File, TIFFTAG_COMPRESSION, Compression); + TIFFSetField(File, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(File, TIFFTAG_BITSPERSAMPLE, TempImage->Bpc << 3); + TIFFSetField(File, TIFFTAG_SAMPLESPERPIXEL, TempImage->Bpp); + if (TempImage->Bpp == 4) //TODO: LUMINANCE, LUMINANCE_ALPHA + TIFFSetField(File, TIFFTAG_MATTEING, 1); + TIFFSetField(File, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(File, TIFFTAG_ROWSPERSTRIP, 1); + TIFFSetField(File, TIFFTAG_SOFTWARE, ilGetString(IL_VERSION_NUM)); + /*TIFFSetField(File, TIFFTAG_DOCUMENTNAME, + iGetString(IL_TIF_DOCUMENTNAME_STRING) ? + iGetString(IL_TIF_DOCUMENTNAME_STRING) : FileName); +*/ + str = iGetString(IL_TIF_DOCUMENTNAME_STRING); + if (str) { + TIFFSetField(File, TIFFTAG_DOCUMENTNAME, str); + ifree(str); + } + + + str = iGetString(IL_TIF_AUTHNAME_STRING); + if (iGetString(IL_TIF_AUTHNAME_STRING)) { + TIFFSetField(File, TIFFTAG_ARTIST, str); + ifree(str); + } + + str = iGetString(IL_TIF_HOSTCOMPUTER_STRING); + if (str) { + TIFFSetField(File, TIFFTAG_HOSTCOMPUTER, str); + ifree(str); + } + + str = iGetString(IL_TIF_HOSTCOMPUTER_STRING); + if (str) { + TIFFSetField(File, TIFFTAG_IMAGEDESCRIPTION, str); + ifree(str); + } + + // Set the date and time string. + TIFFSetField(File, TIFFTAG_DATETIME, iMakeString()); + + // 24/4/2003 + // Orientation flag is not always supported (Photoshop, ...), orient the image data + // and set it always to normal view + TIFFSetField(File, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { + ILubyte* Data = iGetFlipped(TempImage); + OldData = TempImage->Data; + TempImage->Data = Data; + } + else + OldData = TempImage->Data; + + /* + TIFFSetField(File, TIFFTAG_ORIENTATION, + TempImage->Origin == IL_ORIGIN_UPPER_LEFT ? ORIENTATION_TOPLEFT : ORIENTATION_BOTLEFT); + */ + + Format = TempImage->Format; + SwapColors = (Format == IL_BGR || Format == IL_BGRA); + if (SwapColors) + ilSwapColours(); + + for (ixLine = 0; ixLine < TempImage->Height; ++ixLine) { + if (TIFFWriteScanline(File, TempImage->Data + ixLine * TempImage->Bps, ixLine, 0) < 0) { + TIFFClose(File); + ilSetError(IL_LIB_TIFF_ERROR); + if (SwapColors) + ilSwapColours(); + if (TempImage->Data != OldData) { + ifree( TempImage->Data ); + TempImage->Data = OldData; + } + if (TempImage != iCurImage) + ilCloseImage(TempImage); + return IL_FALSE; + } + } + + if (SwapColors) + ilSwapColours(); + + if (TempImage->Data != OldData) { + ifree(TempImage->Data); + TempImage->Data = OldData; + } + + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + TIFFClose(File); + + return IL_TRUE; +} + +/*----------------------------------------------------------------------------*/ +// Makes a neat date string for the date field. +// From http://www.awaresystems.be/imaging/tiff/tifftags/datetime.html : +// The format is: "YYYY:MM:DD HH:MM:SS", with hours like those on +// a 24-hour clock, and one space character between the date and the +// time. The length of the string, including the terminating NUL, is +// 20 bytes.) +char *iMakeString() +{ + static char TimeStr[20]; + time_t Time; + struct tm *CurTime; + + imemclear(TimeStr, 20); + + time(&Time); +#ifdef _WIN32 + _tzset(); +#endif + CurTime = localtime(&Time); + + strftime(TimeStr, 20, "%Y:%m:%d %H:%M:%S", CurTime); + + return TimeStr; +} + +/*----------------------------------------------------------------------------*/ + +#endif//IL_NO_TIF diff --git a/DevIL/src-IL/src/il_tpl.c b/DevIL/src-IL/src/il_tpl.c deleted file mode 100755 index 8806016e..00000000 --- a/DevIL/src-IL/src/il_tpl.c +++ /dev/null @@ -1,782 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_tpl.c -// -// Description: Reads from a Gamecube Texture Palette (.tpl). -// Specifications were found at -// http://pabut.homeip.net:8000/yagcd/chap14.html. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_TPL -#include "il_dds.h" - - -typedef struct TPLHEAD -{ - ILuint Magic; - ILuint nTextures; - ILuint HeaderSize; -} TPLHEAD; - -// Data formats -#define TPL_I4 0 -#define TPL_I8 1 -#define TPL_IA4 2 -#define TPL_IA8 3 -#define TPL_RGB565 4 -#define TPL_RGB5A3 5 -#define TPL_RGBA8 6 -#define TPL_CI4 8 -#define TPL_CI8 9 -#define TPL_CI14X2 10 -#define TPL_CMP 14 - -// Wrapping -#define TPL_CLAMP 0 -#define TPL_REPEAT 1 -#define TPL_MIRROR 2 - -// Palette entries -#define TPL_PAL_IA8 0 -#define TPL_PAL_RGB565 1 -#define TPL_PAL_RGB5A3 2 - - -ILboolean iIsValidTpl(void); -ILboolean iCheckTpl(TPLHEAD *Header); -ILboolean iLoadTplInternal(void); -ILboolean TplGetIndexImage(ILimage *Image, ILuint TexOff, ILuint DataFormat); - - -//! Checks if the file specified in FileName is a valid TPL file. -ILboolean ilIsValidTpl(ILconst_string FileName) -{ - ILHANDLE TplFile; - ILboolean bTpl = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("tpl"))) { - ilSetError(IL_INVALID_EXTENSION); - return bTpl; - } - - TplFile = iopenr(FileName); - if (TplFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bTpl; - } - - bTpl = ilIsValidTplF(TplFile); - icloser(TplFile); - - return bTpl; -} - - -//! Checks if the ILHANDLE contains a valid TPL file at the current position. -ILboolean ilIsValidTplF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidTpl(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid TPL lump. -ILboolean ilIsValidTplL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidTpl(); -} - - -// Internal function used to get the TPL header from the current file. -ILboolean iGetTplHead(TPLHEAD *Header) -{ - Header->Magic = GetBigUInt(); - Header->nTextures = GetBigUInt(); - Header->HeaderSize = GetBigUInt(); - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidTpl(void) -{ - TPLHEAD Header; - - if (!iGetTplHead(&Header)) - return IL_FALSE; - iseek(-12, IL_SEEK_CUR); - - return iCheckTpl(&Header); -} - - -// Internal function used to check if the HEADER is a valid TPL header. -ILboolean iCheckTpl(TPLHEAD *Header) -{ - // The file signature is 0x0020AF30. - if (Header->Magic != 0x0020AF30) - return IL_FALSE; - // Only valid header size is 0x0C. - if (Header->HeaderSize != 0x0C) - return IL_FALSE; - // We have to have at least 1 texture. - if (Header->nTextures == 0) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a TPL file -ILboolean ilLoadTpl(ILconst_string FileName) -{ - ILHANDLE TplFile; - ILboolean bTpl = IL_FALSE; - - TplFile = iopenr(FileName); - if (TplFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bTpl; - } - - bTpl = ilLoadTplF(TplFile); - icloser(TplFile); - - return bTpl; -} - - -//! Reads an already-opened TPL file -ILboolean ilLoadTplF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadTplInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a TPL -ILboolean ilLoadTplL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadTplInternal(); -} - - -// Internal function used to load the TPL. -ILboolean iLoadTplInternal(void) -{ - TPLHEAD Header; - ILimage *Image/*, *BaseImage*/; - ILuint Pos, TexOff, PalOff, DataFormat, Bpp, DataOff, WrapS, WrapT; - ILuint x, y, xBlock, yBlock, i, j, k, n; - ILenum Format; - ILushort Width, Height, ShortPixel; - ILubyte BytePixel, CompData[8]; - Color8888 colours[4], *col; - ILushort color_0, color_1; - ILuint bitmask, Select; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - Image = iCurImage; // Top-level image - - if (!iGetTplHead(&Header)) - return IL_FALSE; - if (!iCheckTpl(&Header)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - // Points to the beginning of the texture header directory. - Pos = itell(); - - for (n = 0; n < Header.nTextures; n++) { - // Go back to the texture header directory for texture number n+1. - iseek(Pos + n * 8, IL_SEEK_SET); - TexOff = GetBigUInt(); - PalOff = GetBigUInt(); - // Go to the texture header. - if (iseek(TexOff, IL_SEEK_SET)) - return IL_FALSE; - - Height = GetBigUShort(); - Width = GetBigUShort(); - // It looks like files actually have n-1 images, with the nth one having 0 height and width. - if (Width == 0 || Height == 0) { - // If this is our first image, however, we error out. - if (Image == iCurImage) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - // Break out of our for loop and run ilFixImage on the images. - break; - } - - DataFormat = GetBigUInt(); - TexOff = GetBigUInt(); - WrapS = GetBigUInt(); - WrapT = GetBigUInt(); - if (WrapS == TPL_REPEAT || WrapS == TPL_MIRROR) { - // By the specs, repeated and mirrored textures must have dimensions of power of 2. - if ((Width != ilNextPower2(Width)) || (Height != ilNextPower2(Height))) { - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - } - - // Go to the actual texture data. - if (iseek(TexOff, IL_SEEK_SET)) - return IL_FALSE; - - switch (DataFormat) - { - case TPL_I4: - case TPL_I8: - Format = IL_LUMINANCE; - Bpp = 1; - break; - case TPL_IA4: - case TPL_IA8: - Format = IL_LUMINANCE_ALPHA; - Bpp = 1; - break; - case TPL_RGB565: - Format = IL_RGB; - Bpp = 3; - break; - case TPL_RGB5A3: - Format = IL_RGBA; - Bpp = 4; - break; - case TPL_RGBA8: - Format = IL_RGBA; - Bpp = 4; - break; - case TPL_CI4: - case TPL_CI8: - Format = IL_COLOR_INDEX; - Bpp = 1; - break; - case TPL_CI14X2: - Format = IL_RGBA; - Bpp = 3; - break; - case TPL_CMP: - Format = IL_RGBA; - Bpp = 4; - break; - - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - if (Image == iCurImage) { // This is our first image. - if (!ilTexImage(Width, Height, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - } - else { - Image->Next = ilNewImageFull(Width, Height, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL); - if (Image->Next == NULL) - return IL_FALSE; - Image = Image->Next; - } - Image->Origin = IL_ORIGIN_UPPER_LEFT; // Origins are always fixed here. - - switch (DataFormat) - { - case TPL_I4: - // 8x8 tiles of 4-bit intensity values - for (y = 0; y < Image->Height; y += 8) { - for (x = 0; x < Image->Width; x += 8) { - for (yBlock = 0; yBlock < 8; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 8; xBlock += 2) { - BytePixel = igetc(); - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - Image->Data[DataOff] = (BytePixel & 0xF0) | (BytePixel & 0xF0) >> 4; - DataOff++; - // We have to do this check again, so we do not go past the last pixel in the image (ex. 1 pixel wide image). - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - Image->Data[DataOff+1] = (BytePixel & 0x0F) << 4 | (BytePixel & 0x0F); - DataOff++; - } - } - } - } - break; - - case TPL_I8: - // 8x4 tiles of 8-bit intensity values - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 8) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 8; xBlock++) { - if ((x + xBlock) >= Image->Width) { - igetc(); // Skip the pad byte. - continue; - } - Image->Data[DataOff] = igetc(); // Luminance value - DataOff++; - } - } - } - } - break; - - case TPL_IA4: - // 8x4 tiles of 4-bit intensity and 4-bit alpha values - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 8) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 8; xBlock += 2) { - BytePixel = igetc(); - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - Image->Data[DataOff] = (BytePixel & 0xF0) | (BytePixel & 0xF0) >> 4; - Image->Data[DataOff+1] = (BytePixel & 0x0F) << 4 | (BytePixel & 0x0F); - DataOff += 2; - } - } - } - } - break; - - case TPL_IA8: - // 4x4 tiles of 8-bit intensity and 8-bit alpha values - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 4; xBlock += 2) { - if ((x + xBlock) >= Image->Width) { - iseek(2, IL_SEEK_CUR); // Skip the pad bytes. - continue; - } - Image->Data[DataOff] = igetc(); - Image->Data[DataOff+1] = igetc(); - DataOff += 2; - } - } - } - } - break; - - case TPL_RGB565: - // 4x4 tiles of RGB565 data - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 4; xBlock++) { - ShortPixel = GetBigUShort(); - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - Image->Data[DataOff] = ((ShortPixel & 0xF800) >> 8) | ((ShortPixel & 0xE000) >> 13); // Red - Image->Data[DataOff+1] = ((ShortPixel & 0x7E0) >> 3) | ((ShortPixel & 0x600) >> 9); // Green - Image->Data[DataOff+2] = ((ShortPixel & 0x1f) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue - DataOff += 3; - } - } - } - } - break; - - case TPL_RGB5A3: - // 4x4 tiles of either RGB5 or RGB4A3 depending on the MSB. 0x80 - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 4; xBlock++) { - ShortPixel = GetBigUShort(); - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - - if (ShortPixel & 0x8000) { // Check MSB. - // We have RGB5. - Image->Data[DataOff] = ((ShortPixel & 0x7C00) >> 7) | ((ShortPixel & 0x7000) >> 12); // Red - Image->Data[DataOff+1] = ((ShortPixel & 0x3E0) >> 2) | ((ShortPixel & 0x380) >> 7); // Green - Image->Data[DataOff+2] = ((ShortPixel & 0x1F) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue - Image->Data[DataOff+3] = 0xFF; // I am just assuming that it is opaque. - } - else { - // We have RGB4A3. - Image->Data[DataOff] = ((ShortPixel & 0x7800) >> 7) | ((ShortPixel & 0x7800) >> 11); // Red - Image->Data[DataOff+1] = ((ShortPixel & 0x0780) >> 3) | ((ShortPixel & 0x0780) >> 7); // Green - Image->Data[DataOff+2] = ((ShortPixel & 0x0078) << 1) | ((ShortPixel & 0x0078) >> 3); // Blue - Image->Data[DataOff+3] = ((ShortPixel & 0x07) << 5) | ((ShortPixel & 0x07) << 2) | (ShortPixel >> 1); // Alpha - } - DataOff += 3; - } - } - } - } - break; - - case TPL_RGBA8: - // 4x4 tiles of RGBA data - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - for (yBlock = 0; yBlock < 4; yBlock++) { - // Skip pad bytes at the bottom of the tile if any. - if ((y + yBlock) >= Image->Height) { - iseek(16, IL_SEEK_CUR); // Entire row of pad bytes skipped - continue; - } - - // First it has the AR data. - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 4; xBlock++) { - if ((x + xBlock) >= Image->Width) { - iseek(2, IL_SEEK_CUR); // Skip pad bytes. - continue; - } - Image->Data[DataOff+3] = igetc(); // Alpha - Image->Data[DataOff] = igetc(); // Red - DataOff += 3; - } - - // Then it has the GB data. - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 4 && x + xBlock < Image->Width; xBlock++) { - if ((x + xBlock) >= Image->Width) { - iseek(2, IL_SEEK_CUR); // Skip pad bytes. - continue; - } - Image->Data[DataOff+1] = igetc(); // Green - Image->Data[DataOff+2] = igetc(); // Blue - DataOff += 3; - } - } - } - } - break; - - case TPL_CI4: - case TPL_CI8: - case TPL_CI14X2: - // Seek to the palette header. - if (iseek(PalOff, IL_SEEK_SET)) - return IL_FALSE; - if (!TplGetIndexImage(Image, TexOff, DataFormat)) - return IL_FALSE; - break; - - case TPL_CMP: - // S3TC 2x2 blocks of 4x4 tiles. I am assuming that this is DXT1, since it is not specified in the specs. - // Most of this ended up being copied from il_dds.c, from the DecompressDXT1 function. - //@TODO: Make this/that code a bit more modular. - for (y = 0; y < Image->Height; y += 8) { - for (x = 0; x < Image->Width; x += 8) { - for (yBlock = 0; yBlock < 8 && (y + yBlock) < Image->Height; yBlock += 4) { - for (xBlock = 0; xBlock < 8 && (x + xBlock) < Image->Width; xBlock += 4) { - if (iread(CompData, 1, 8) != 8) - return IL_FALSE; //@TODO: Need to do any cleanup here? - color_0 = *((ILushort*)CompData); - UShort(&color_0); - color_1 = *((ILushort*)(CompData + 2)); - UShort(&color_1); - DxtcReadColor(color_0, colours); - DxtcReadColor(color_1, colours + 1); - bitmask = ((ILuint*)CompData)[1]; - UInt(&bitmask); - - if (color_0 > color_1) { - // Four-color block: derive the other two colors. - // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; - colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; - colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; - //colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - colours[3].a = 0xFF; - } - else { - // Three-color block: derive the other color. - // 00 = color_0, 01 = color_1, 10 = color_2, - // 11 = transparent. - // These 2-bit codes correspond to the 2-bit fields - // stored in the 64-bit block. - colours[2].b = (colours[0].b + colours[1].b) / 2; - colours[2].g = (colours[0].g + colours[1].g) / 2; - colours[2].r = (colours[0].r + colours[1].r) / 2; - //colours[2].a = 0xFF; - - colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; - colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; - colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; - colours[3].a = 0x00; - } - - for (j = 0, k = 0; j < 4; j++) { - for (i = 0; i < 4; i++, k++) { - Select = (bitmask & (0x03 << k*2)) >> k*2; - col = &colours[Select]; - - if (((x + xBlock + i) < Image->Width) && ((y + yBlock + j) < Image->Height)) { - DataOff = (y + yBlock + j) * Image->Bps + (x + xBlock + i) * Image->Bpp; - Image->Data[DataOff + 0] = col->r; - Image->Data[DataOff + 1] = col->g; - Image->Data[DataOff + 2] = col->b; - Image->Data[DataOff + 3] = col->a; - } - } - } - } - } - } - } - break; - } - } - - return ilFixImage(); -} - - -ILboolean TplGetIndexImage(ILimage *Image, ILuint TexOff, ILuint DataFormat) -{ - ILushort NumPal, ShortPixel; - ILubyte LumVal, BytePixel; - ILuint PalFormat, PalOff, PalBpp, DataOff; - ILuint x, y, xBlock, yBlock, i; - - NumPal = GetBigUShort(); - iseek(2, IL_SEEK_CUR); // Do we need to do anything with the 'unpacked' entry? I see nothing in the specs about it. - PalFormat = GetBigUInt(); - - // Now we have to find out where the actual palette data is stored. - //@TODO: Do we need to set any errors here? - PalOff = GetBigUInt(); - if (iseek(PalOff, IL_SEEK_SET)) - return IL_FALSE; - - switch (PalFormat) - { - case TPL_PAL_IA8: - Image->Pal.Palette = (ILubyte*)ialloc(NumPal * 4); - if (Image->Pal.Palette == NULL) - return IL_FALSE; - Image->Pal.PalType = IL_PAL_RGBA32; //@TODO: Use this format natively. - Image->Pal.PalSize = NumPal * 4; - PalBpp = 4; - - for (i = 0; i < NumPal; i++) { - LumVal = igetc(); - //@TODO: Do proper conversion of luminance, or support this format natively. - Image->Pal.Palette[i * 4] = LumVal; // Assign the luminance value. - Image->Pal.Palette[i * 4 + 1] = LumVal; - Image->Pal.Palette[i * 4 + 2] = LumVal; - Image->Pal.Palette[i * 4 + 3] = igetc(); // Get alpha value. - } - break; - - case TPL_PAL_RGB565: - Image->Pal.Palette = (ILubyte*)ialloc(NumPal * 3); - if (Image->Pal.Palette == NULL) - return IL_FALSE; - Image->Pal.PalType = IL_PAL_RGB24; - Image->Pal.PalSize = NumPal * 3; - PalBpp = 3; - - for (i = 0; i < NumPal; i++) { - ShortPixel = GetBigUShort(); - // This is mostly the same code as in the TPL_RGB565 case. - Image->Pal.Palette[i*3] = ((ShortPixel & 0xF800) >> 8) | ((ShortPixel & 0xE000) >> 13); // Red - Image->Pal.Palette[i*3+1] = ((ShortPixel & 0x7E0) >> 3) | ((ShortPixel & 0x600) >> 9); // Green - Image->Pal.Palette[i*3+2] = ((ShortPixel & 0x1f) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue - } - break; - - case TPL_PAL_RGB5A3: - Image->Pal.Palette = (ILubyte*)ialloc(NumPal * 4); - if (Image->Pal.Palette == NULL) - return IL_FALSE; - Image->Pal.PalType = IL_PAL_RGBA32; - Image->Pal.PalSize = NumPal * 4; - PalBpp = 4; - - for (i = 0; i < NumPal; i++) { - ShortPixel = GetBigUShort(); - // This is mostly the same code as in the TPL_RGB565 case. - if (ShortPixel & 0x8000) { // Check MSB. - // We have RGB5. - Image->Pal.Palette[i*4] = ((ShortPixel & 0x7C00) >> 7) | ((ShortPixel & 0x7000) >> 12); // Red - Image->Pal.Palette[i*4+1] = ((ShortPixel & 0x3E0) >> 2) | ((ShortPixel & 0x380) >> 7); // Green - Image->Pal.Palette[i*4+2] = ((ShortPixel & 0x1F) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue - Image->Pal.Palette[i*4+3] = 0xFF; // I am just assuming that it is opaque. - } - else { - // We have RGB4A3. - Image->Pal.Palette[i*4] = ((ShortPixel & 0x7800) >> 7) | ((ShortPixel & 0x7800) >> 11); // Red - Image->Pal.Palette[i*4+1] = ((ShortPixel & 0x0780) >> 3) | ((ShortPixel & 0x0780) >> 7); // Green - Image->Pal.Palette[i*4+2] = ((ShortPixel & 0x0078) << 1) | ((ShortPixel & 0x0078) >> 3); // Blue - Image->Pal.Palette[i*4+3] = ((ShortPixel & 0x07) << 5) | ((ShortPixel & 0x07) << 2) | (ShortPixel >> 1); // Alpha - } - } - break; - - default: - ilSetError(IL_ILLEGAL_FILE_VALUE); - return IL_FALSE; - } - - // Go back to the texture data. - if (iseek(TexOff, IL_SEEK_SET)) - return IL_FALSE; - - switch (DataFormat) - { - case TPL_CI4: - // 8x8 tiles of 4-bit color indices - // This is the exact same code as the TPL_I4 case. - for (y = 0; y < Image->Height; y += 8) { - for (x = 0; x < Image->Width; x += 8) { - for (yBlock = 0; yBlock < 8; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 8; xBlock += 2) { - BytePixel = igetc(); - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - Image->Data[DataOff] = (BytePixel & 0xF0) | (BytePixel & 0xF0) >> 4; - DataOff++; - // We have to do this check again, so we do not go past the last pixel in the image (ex. 1 pixel wide image). - if ((x + xBlock) >= Image->Width) - continue; // Already read the pad byte. - Image->Data[DataOff+1] = (BytePixel & 0x0F) << 4 | (BytePixel & 0x0F); - DataOff++; - } - } - } - } - break; - - case TPL_CI8: - // 8x4 tiles of 8-bit intensity values - // This is the exact same code as the TPL_I8 case. - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 8) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 8; xBlock++) { - if ((x + xBlock) >= Image->Width) { - igetc(); // Skip the pad byte. - continue; - } - Image->Data[DataOff] = igetc(); // Color index - DataOff++; - } - } - } - } - break; - - - //@TODO: Convert to more formats than just RGBA. - case TPL_CI14X2: - // 4x4 tiles of 14-bit indices into a palette. Not supported at all in DevIL, since - // it has a huge palette (> 256 colors). Convert to RGBA. - for (y = 0; y < Image->Height; y += 4) { - for (x = 0; x < Image->Width; x += 4) { - for (yBlock = 0; yBlock < 4; yBlock++) { - if ((y + yBlock) >= Image->Height) { - iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. - continue; - } - DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; - for (xBlock = 0; xBlock < 4; xBlock++) { - if ((x + xBlock) >= Image->Width) { - GetBigUShort(); // Skip the pad short. - continue; - } - ShortPixel = GetBigUShort(); - ShortPixel >>= 2; // Lower 2 bits are padding bits. - Image->Data[DataOff] = Image->Pal.Palette[ShortPixel * PalBpp]; - Image->Data[DataOff+1] = Image->Pal.Palette[ShortPixel * PalBpp + 1]; - Image->Data[DataOff+2] = Image->Pal.Palette[ShortPixel * PalBpp + 2]; - if (PalFormat == TPL_PAL_RGB565) - Image->Data[DataOff+3] = 0xFF; - else - Image->Data[DataOff+3] = Image->Pal.Palette[ShortPixel * PalBpp + 3]; - DataOff++; - } - } - } - } - // Get rid of the palette, since we no longer need it. - ifree(Image->Pal.Palette); - Image->Pal.PalType = IL_PAL_NONE; - Image->Pal.PalSize = 0; - break; - - } - - return IL_TRUE; -} -#endif//IL_NO_TPL diff --git a/DevIL/src-IL/src/il_tpl.cpp b/DevIL/src-IL/src/il_tpl.cpp new file mode 100755 index 00000000..8806016e --- /dev/null +++ b/DevIL/src-IL/src/il_tpl.cpp @@ -0,0 +1,782 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_tpl.c +// +// Description: Reads from a Gamecube Texture Palette (.tpl). +// Specifications were found at +// http://pabut.homeip.net:8000/yagcd/chap14.html. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_TPL +#include "il_dds.h" + + +typedef struct TPLHEAD +{ + ILuint Magic; + ILuint nTextures; + ILuint HeaderSize; +} TPLHEAD; + +// Data formats +#define TPL_I4 0 +#define TPL_I8 1 +#define TPL_IA4 2 +#define TPL_IA8 3 +#define TPL_RGB565 4 +#define TPL_RGB5A3 5 +#define TPL_RGBA8 6 +#define TPL_CI4 8 +#define TPL_CI8 9 +#define TPL_CI14X2 10 +#define TPL_CMP 14 + +// Wrapping +#define TPL_CLAMP 0 +#define TPL_REPEAT 1 +#define TPL_MIRROR 2 + +// Palette entries +#define TPL_PAL_IA8 0 +#define TPL_PAL_RGB565 1 +#define TPL_PAL_RGB5A3 2 + + +ILboolean iIsValidTpl(void); +ILboolean iCheckTpl(TPLHEAD *Header); +ILboolean iLoadTplInternal(void); +ILboolean TplGetIndexImage(ILimage *Image, ILuint TexOff, ILuint DataFormat); + + +//! Checks if the file specified in FileName is a valid TPL file. +ILboolean ilIsValidTpl(ILconst_string FileName) +{ + ILHANDLE TplFile; + ILboolean bTpl = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("tpl"))) { + ilSetError(IL_INVALID_EXTENSION); + return bTpl; + } + + TplFile = iopenr(FileName); + if (TplFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bTpl; + } + + bTpl = ilIsValidTplF(TplFile); + icloser(TplFile); + + return bTpl; +} + + +//! Checks if the ILHANDLE contains a valid TPL file at the current position. +ILboolean ilIsValidTplF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidTpl(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid TPL lump. +ILboolean ilIsValidTplL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidTpl(); +} + + +// Internal function used to get the TPL header from the current file. +ILboolean iGetTplHead(TPLHEAD *Header) +{ + Header->Magic = GetBigUInt(); + Header->nTextures = GetBigUInt(); + Header->HeaderSize = GetBigUInt(); + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidTpl(void) +{ + TPLHEAD Header; + + if (!iGetTplHead(&Header)) + return IL_FALSE; + iseek(-12, IL_SEEK_CUR); + + return iCheckTpl(&Header); +} + + +// Internal function used to check if the HEADER is a valid TPL header. +ILboolean iCheckTpl(TPLHEAD *Header) +{ + // The file signature is 0x0020AF30. + if (Header->Magic != 0x0020AF30) + return IL_FALSE; + // Only valid header size is 0x0C. + if (Header->HeaderSize != 0x0C) + return IL_FALSE; + // We have to have at least 1 texture. + if (Header->nTextures == 0) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a TPL file +ILboolean ilLoadTpl(ILconst_string FileName) +{ + ILHANDLE TplFile; + ILboolean bTpl = IL_FALSE; + + TplFile = iopenr(FileName); + if (TplFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bTpl; + } + + bTpl = ilLoadTplF(TplFile); + icloser(TplFile); + + return bTpl; +} + + +//! Reads an already-opened TPL file +ILboolean ilLoadTplF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadTplInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a TPL +ILboolean ilLoadTplL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadTplInternal(); +} + + +// Internal function used to load the TPL. +ILboolean iLoadTplInternal(void) +{ + TPLHEAD Header; + ILimage *Image/*, *BaseImage*/; + ILuint Pos, TexOff, PalOff, DataFormat, Bpp, DataOff, WrapS, WrapT; + ILuint x, y, xBlock, yBlock, i, j, k, n; + ILenum Format; + ILushort Width, Height, ShortPixel; + ILubyte BytePixel, CompData[8]; + Color8888 colours[4], *col; + ILushort color_0, color_1; + ILuint bitmask, Select; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + Image = iCurImage; // Top-level image + + if (!iGetTplHead(&Header)) + return IL_FALSE; + if (!iCheckTpl(&Header)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + // Points to the beginning of the texture header directory. + Pos = itell(); + + for (n = 0; n < Header.nTextures; n++) { + // Go back to the texture header directory for texture number n+1. + iseek(Pos + n * 8, IL_SEEK_SET); + TexOff = GetBigUInt(); + PalOff = GetBigUInt(); + // Go to the texture header. + if (iseek(TexOff, IL_SEEK_SET)) + return IL_FALSE; + + Height = GetBigUShort(); + Width = GetBigUShort(); + // It looks like files actually have n-1 images, with the nth one having 0 height and width. + if (Width == 0 || Height == 0) { + // If this is our first image, however, we error out. + if (Image == iCurImage) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + // Break out of our for loop and run ilFixImage on the images. + break; + } + + DataFormat = GetBigUInt(); + TexOff = GetBigUInt(); + WrapS = GetBigUInt(); + WrapT = GetBigUInt(); + if (WrapS == TPL_REPEAT || WrapS == TPL_MIRROR) { + // By the specs, repeated and mirrored textures must have dimensions of power of 2. + if ((Width != ilNextPower2(Width)) || (Height != ilNextPower2(Height))) { + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + } + + // Go to the actual texture data. + if (iseek(TexOff, IL_SEEK_SET)) + return IL_FALSE; + + switch (DataFormat) + { + case TPL_I4: + case TPL_I8: + Format = IL_LUMINANCE; + Bpp = 1; + break; + case TPL_IA4: + case TPL_IA8: + Format = IL_LUMINANCE_ALPHA; + Bpp = 1; + break; + case TPL_RGB565: + Format = IL_RGB; + Bpp = 3; + break; + case TPL_RGB5A3: + Format = IL_RGBA; + Bpp = 4; + break; + case TPL_RGBA8: + Format = IL_RGBA; + Bpp = 4; + break; + case TPL_CI4: + case TPL_CI8: + Format = IL_COLOR_INDEX; + Bpp = 1; + break; + case TPL_CI14X2: + Format = IL_RGBA; + Bpp = 3; + break; + case TPL_CMP: + Format = IL_RGBA; + Bpp = 4; + break; + + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + if (Image == iCurImage) { // This is our first image. + if (!ilTexImage(Width, Height, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + } + else { + Image->Next = ilNewImageFull(Width, Height, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL); + if (Image->Next == NULL) + return IL_FALSE; + Image = Image->Next; + } + Image->Origin = IL_ORIGIN_UPPER_LEFT; // Origins are always fixed here. + + switch (DataFormat) + { + case TPL_I4: + // 8x8 tiles of 4-bit intensity values + for (y = 0; y < Image->Height; y += 8) { + for (x = 0; x < Image->Width; x += 8) { + for (yBlock = 0; yBlock < 8; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 8; xBlock += 2) { + BytePixel = igetc(); + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + Image->Data[DataOff] = (BytePixel & 0xF0) | (BytePixel & 0xF0) >> 4; + DataOff++; + // We have to do this check again, so we do not go past the last pixel in the image (ex. 1 pixel wide image). + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + Image->Data[DataOff+1] = (BytePixel & 0x0F) << 4 | (BytePixel & 0x0F); + DataOff++; + } + } + } + } + break; + + case TPL_I8: + // 8x4 tiles of 8-bit intensity values + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 8) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 8; xBlock++) { + if ((x + xBlock) >= Image->Width) { + igetc(); // Skip the pad byte. + continue; + } + Image->Data[DataOff] = igetc(); // Luminance value + DataOff++; + } + } + } + } + break; + + case TPL_IA4: + // 8x4 tiles of 4-bit intensity and 4-bit alpha values + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 8) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 8; xBlock += 2) { + BytePixel = igetc(); + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + Image->Data[DataOff] = (BytePixel & 0xF0) | (BytePixel & 0xF0) >> 4; + Image->Data[DataOff+1] = (BytePixel & 0x0F) << 4 | (BytePixel & 0x0F); + DataOff += 2; + } + } + } + } + break; + + case TPL_IA8: + // 4x4 tiles of 8-bit intensity and 8-bit alpha values + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 4; xBlock += 2) { + if ((x + xBlock) >= Image->Width) { + iseek(2, IL_SEEK_CUR); // Skip the pad bytes. + continue; + } + Image->Data[DataOff] = igetc(); + Image->Data[DataOff+1] = igetc(); + DataOff += 2; + } + } + } + } + break; + + case TPL_RGB565: + // 4x4 tiles of RGB565 data + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 4; xBlock++) { + ShortPixel = GetBigUShort(); + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + Image->Data[DataOff] = ((ShortPixel & 0xF800) >> 8) | ((ShortPixel & 0xE000) >> 13); // Red + Image->Data[DataOff+1] = ((ShortPixel & 0x7E0) >> 3) | ((ShortPixel & 0x600) >> 9); // Green + Image->Data[DataOff+2] = ((ShortPixel & 0x1f) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue + DataOff += 3; + } + } + } + } + break; + + case TPL_RGB5A3: + // 4x4 tiles of either RGB5 or RGB4A3 depending on the MSB. 0x80 + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 4; xBlock++) { + ShortPixel = GetBigUShort(); + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + + if (ShortPixel & 0x8000) { // Check MSB. + // We have RGB5. + Image->Data[DataOff] = ((ShortPixel & 0x7C00) >> 7) | ((ShortPixel & 0x7000) >> 12); // Red + Image->Data[DataOff+1] = ((ShortPixel & 0x3E0) >> 2) | ((ShortPixel & 0x380) >> 7); // Green + Image->Data[DataOff+2] = ((ShortPixel & 0x1F) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue + Image->Data[DataOff+3] = 0xFF; // I am just assuming that it is opaque. + } + else { + // We have RGB4A3. + Image->Data[DataOff] = ((ShortPixel & 0x7800) >> 7) | ((ShortPixel & 0x7800) >> 11); // Red + Image->Data[DataOff+1] = ((ShortPixel & 0x0780) >> 3) | ((ShortPixel & 0x0780) >> 7); // Green + Image->Data[DataOff+2] = ((ShortPixel & 0x0078) << 1) | ((ShortPixel & 0x0078) >> 3); // Blue + Image->Data[DataOff+3] = ((ShortPixel & 0x07) << 5) | ((ShortPixel & 0x07) << 2) | (ShortPixel >> 1); // Alpha + } + DataOff += 3; + } + } + } + } + break; + + case TPL_RGBA8: + // 4x4 tiles of RGBA data + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + for (yBlock = 0; yBlock < 4; yBlock++) { + // Skip pad bytes at the bottom of the tile if any. + if ((y + yBlock) >= Image->Height) { + iseek(16, IL_SEEK_CUR); // Entire row of pad bytes skipped + continue; + } + + // First it has the AR data. + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 4; xBlock++) { + if ((x + xBlock) >= Image->Width) { + iseek(2, IL_SEEK_CUR); // Skip pad bytes. + continue; + } + Image->Data[DataOff+3] = igetc(); // Alpha + Image->Data[DataOff] = igetc(); // Red + DataOff += 3; + } + + // Then it has the GB data. + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 4 && x + xBlock < Image->Width; xBlock++) { + if ((x + xBlock) >= Image->Width) { + iseek(2, IL_SEEK_CUR); // Skip pad bytes. + continue; + } + Image->Data[DataOff+1] = igetc(); // Green + Image->Data[DataOff+2] = igetc(); // Blue + DataOff += 3; + } + } + } + } + break; + + case TPL_CI4: + case TPL_CI8: + case TPL_CI14X2: + // Seek to the palette header. + if (iseek(PalOff, IL_SEEK_SET)) + return IL_FALSE; + if (!TplGetIndexImage(Image, TexOff, DataFormat)) + return IL_FALSE; + break; + + case TPL_CMP: + // S3TC 2x2 blocks of 4x4 tiles. I am assuming that this is DXT1, since it is not specified in the specs. + // Most of this ended up being copied from il_dds.c, from the DecompressDXT1 function. + //@TODO: Make this/that code a bit more modular. + for (y = 0; y < Image->Height; y += 8) { + for (x = 0; x < Image->Width; x += 8) { + for (yBlock = 0; yBlock < 8 && (y + yBlock) < Image->Height; yBlock += 4) { + for (xBlock = 0; xBlock < 8 && (x + xBlock) < Image->Width; xBlock += 4) { + if (iread(CompData, 1, 8) != 8) + return IL_FALSE; //@TODO: Need to do any cleanup here? + color_0 = *((ILushort*)CompData); + UShort(&color_0); + color_1 = *((ILushort*)(CompData + 2)); + UShort(&color_1); + DxtcReadColor(color_0, colours); + DxtcReadColor(color_1, colours + 1); + bitmask = ((ILuint*)CompData)[1]; + UInt(&bitmask); + + if (color_0 > color_1) { + // Four-color block: derive the other two colors. + // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3 + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (2 * colours[0].b + colours[1].b + 1) / 3; + colours[2].g = (2 * colours[0].g + colours[1].g + 1) / 3; + colours[2].r = (2 * colours[0].r + colours[1].r + 1) / 3; + //colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + colours[3].a = 0xFF; + } + else { + // Three-color block: derive the other color. + // 00 = color_0, 01 = color_1, 10 = color_2, + // 11 = transparent. + // These 2-bit codes correspond to the 2-bit fields + // stored in the 64-bit block. + colours[2].b = (colours[0].b + colours[1].b) / 2; + colours[2].g = (colours[0].g + colours[1].g) / 2; + colours[2].r = (colours[0].r + colours[1].r) / 2; + //colours[2].a = 0xFF; + + colours[3].b = (colours[0].b + 2 * colours[1].b + 1) / 3; + colours[3].g = (colours[0].g + 2 * colours[1].g + 1) / 3; + colours[3].r = (colours[0].r + 2 * colours[1].r + 1) / 3; + colours[3].a = 0x00; + } + + for (j = 0, k = 0; j < 4; j++) { + for (i = 0; i < 4; i++, k++) { + Select = (bitmask & (0x03 << k*2)) >> k*2; + col = &colours[Select]; + + if (((x + xBlock + i) < Image->Width) && ((y + yBlock + j) < Image->Height)) { + DataOff = (y + yBlock + j) * Image->Bps + (x + xBlock + i) * Image->Bpp; + Image->Data[DataOff + 0] = col->r; + Image->Data[DataOff + 1] = col->g; + Image->Data[DataOff + 2] = col->b; + Image->Data[DataOff + 3] = col->a; + } + } + } + } + } + } + } + break; + } + } + + return ilFixImage(); +} + + +ILboolean TplGetIndexImage(ILimage *Image, ILuint TexOff, ILuint DataFormat) +{ + ILushort NumPal, ShortPixel; + ILubyte LumVal, BytePixel; + ILuint PalFormat, PalOff, PalBpp, DataOff; + ILuint x, y, xBlock, yBlock, i; + + NumPal = GetBigUShort(); + iseek(2, IL_SEEK_CUR); // Do we need to do anything with the 'unpacked' entry? I see nothing in the specs about it. + PalFormat = GetBigUInt(); + + // Now we have to find out where the actual palette data is stored. + //@TODO: Do we need to set any errors here? + PalOff = GetBigUInt(); + if (iseek(PalOff, IL_SEEK_SET)) + return IL_FALSE; + + switch (PalFormat) + { + case TPL_PAL_IA8: + Image->Pal.Palette = (ILubyte*)ialloc(NumPal * 4); + if (Image->Pal.Palette == NULL) + return IL_FALSE; + Image->Pal.PalType = IL_PAL_RGBA32; //@TODO: Use this format natively. + Image->Pal.PalSize = NumPal * 4; + PalBpp = 4; + + for (i = 0; i < NumPal; i++) { + LumVal = igetc(); + //@TODO: Do proper conversion of luminance, or support this format natively. + Image->Pal.Palette[i * 4] = LumVal; // Assign the luminance value. + Image->Pal.Palette[i * 4 + 1] = LumVal; + Image->Pal.Palette[i * 4 + 2] = LumVal; + Image->Pal.Palette[i * 4 + 3] = igetc(); // Get alpha value. + } + break; + + case TPL_PAL_RGB565: + Image->Pal.Palette = (ILubyte*)ialloc(NumPal * 3); + if (Image->Pal.Palette == NULL) + return IL_FALSE; + Image->Pal.PalType = IL_PAL_RGB24; + Image->Pal.PalSize = NumPal * 3; + PalBpp = 3; + + for (i = 0; i < NumPal; i++) { + ShortPixel = GetBigUShort(); + // This is mostly the same code as in the TPL_RGB565 case. + Image->Pal.Palette[i*3] = ((ShortPixel & 0xF800) >> 8) | ((ShortPixel & 0xE000) >> 13); // Red + Image->Pal.Palette[i*3+1] = ((ShortPixel & 0x7E0) >> 3) | ((ShortPixel & 0x600) >> 9); // Green + Image->Pal.Palette[i*3+2] = ((ShortPixel & 0x1f) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue + } + break; + + case TPL_PAL_RGB5A3: + Image->Pal.Palette = (ILubyte*)ialloc(NumPal * 4); + if (Image->Pal.Palette == NULL) + return IL_FALSE; + Image->Pal.PalType = IL_PAL_RGBA32; + Image->Pal.PalSize = NumPal * 4; + PalBpp = 4; + + for (i = 0; i < NumPal; i++) { + ShortPixel = GetBigUShort(); + // This is mostly the same code as in the TPL_RGB565 case. + if (ShortPixel & 0x8000) { // Check MSB. + // We have RGB5. + Image->Pal.Palette[i*4] = ((ShortPixel & 0x7C00) >> 7) | ((ShortPixel & 0x7000) >> 12); // Red + Image->Pal.Palette[i*4+1] = ((ShortPixel & 0x3E0) >> 2) | ((ShortPixel & 0x380) >> 7); // Green + Image->Pal.Palette[i*4+2] = ((ShortPixel & 0x1F) << 3) | ((ShortPixel & 0x1C) >> 2); // Blue + Image->Pal.Palette[i*4+3] = 0xFF; // I am just assuming that it is opaque. + } + else { + // We have RGB4A3. + Image->Pal.Palette[i*4] = ((ShortPixel & 0x7800) >> 7) | ((ShortPixel & 0x7800) >> 11); // Red + Image->Pal.Palette[i*4+1] = ((ShortPixel & 0x0780) >> 3) | ((ShortPixel & 0x0780) >> 7); // Green + Image->Pal.Palette[i*4+2] = ((ShortPixel & 0x0078) << 1) | ((ShortPixel & 0x0078) >> 3); // Blue + Image->Pal.Palette[i*4+3] = ((ShortPixel & 0x07) << 5) | ((ShortPixel & 0x07) << 2) | (ShortPixel >> 1); // Alpha + } + } + break; + + default: + ilSetError(IL_ILLEGAL_FILE_VALUE); + return IL_FALSE; + } + + // Go back to the texture data. + if (iseek(TexOff, IL_SEEK_SET)) + return IL_FALSE; + + switch (DataFormat) + { + case TPL_CI4: + // 8x8 tiles of 4-bit color indices + // This is the exact same code as the TPL_I4 case. + for (y = 0; y < Image->Height; y += 8) { + for (x = 0; x < Image->Width; x += 8) { + for (yBlock = 0; yBlock < 8; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 8; xBlock += 2) { + BytePixel = igetc(); + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + Image->Data[DataOff] = (BytePixel & 0xF0) | (BytePixel & 0xF0) >> 4; + DataOff++; + // We have to do this check again, so we do not go past the last pixel in the image (ex. 1 pixel wide image). + if ((x + xBlock) >= Image->Width) + continue; // Already read the pad byte. + Image->Data[DataOff+1] = (BytePixel & 0x0F) << 4 | (BytePixel & 0x0F); + DataOff++; + } + } + } + } + break; + + case TPL_CI8: + // 8x4 tiles of 8-bit intensity values + // This is the exact same code as the TPL_I8 case. + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 8) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 8; xBlock++) { + if ((x + xBlock) >= Image->Width) { + igetc(); // Skip the pad byte. + continue; + } + Image->Data[DataOff] = igetc(); // Color index + DataOff++; + } + } + } + } + break; + + + //@TODO: Convert to more formats than just RGBA. + case TPL_CI14X2: + // 4x4 tiles of 14-bit indices into a palette. Not supported at all in DevIL, since + // it has a huge palette (> 256 colors). Convert to RGBA. + for (y = 0; y < Image->Height; y += 4) { + for (x = 0; x < Image->Width; x += 4) { + for (yBlock = 0; yBlock < 4; yBlock++) { + if ((y + yBlock) >= Image->Height) { + iseek(8, IL_SEEK_CUR); // Entire row of pad bytes skipped. + continue; + } + DataOff = Image->Bps * (y + yBlock) + Image->Bpp * x; + for (xBlock = 0; xBlock < 4; xBlock++) { + if ((x + xBlock) >= Image->Width) { + GetBigUShort(); // Skip the pad short. + continue; + } + ShortPixel = GetBigUShort(); + ShortPixel >>= 2; // Lower 2 bits are padding bits. + Image->Data[DataOff] = Image->Pal.Palette[ShortPixel * PalBpp]; + Image->Data[DataOff+1] = Image->Pal.Palette[ShortPixel * PalBpp + 1]; + Image->Data[DataOff+2] = Image->Pal.Palette[ShortPixel * PalBpp + 2]; + if (PalFormat == TPL_PAL_RGB565) + Image->Data[DataOff+3] = 0xFF; + else + Image->Data[DataOff+3] = Image->Pal.Palette[ShortPixel * PalBpp + 3]; + DataOff++; + } + } + } + } + // Get rid of the palette, since we no longer need it. + ifree(Image->Pal.Palette); + Image->Pal.PalType = IL_PAL_NONE; + Image->Pal.PalSize = 0; + break; + + } + + return IL_TRUE; +} +#endif//IL_NO_TPL diff --git a/DevIL/src-IL/src/il_utility.c b/DevIL/src-IL/src/il_utility.c deleted file mode 100644 index e2e6ca7a..00000000 --- a/DevIL/src-IL/src/il_utility.c +++ /dev/null @@ -1,171 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 02/04/2009 -// -// Filename: src-IL/src/il_utility.c -// -// Description: Utility functions -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" - - -// Returns the bpp of any Format -ILAPI ILubyte ILAPIENTRY ilGetBppFormat(ILenum Format) -{ - switch (Format) - { - case IL_COLOUR_INDEX: - case IL_LUMINANCE: - case IL_ALPHA: - return 1; - case IL_LUMINANCE_ALPHA: - return 2; - case IL_RGB: - case IL_BGR: - return 3; - case IL_RGBA: - case IL_BGRA: - return 4; - } - return 0; -} - - -// Returns the format of any bpp -ILAPI ILenum ILAPIENTRY ilGetFormatBpp(ILubyte Bpp) -{ - switch (Bpp) - { - case 1: - return IL_LUMINANCE; - case 2: - return IL_LUMINANCE_ALPHA; - case 3: - return IL_RGB; - case 4: - return IL_RGBA; - } - return 0; -} - - -// Returns the bpc of any Type -ILAPI ILubyte ILAPIENTRY ilGetBpcType(ILenum Type) -{ - switch (Type) - { - case IL_BYTE: - case IL_UNSIGNED_BYTE: - return 1; - case IL_SHORT: - case IL_UNSIGNED_SHORT: - case IL_HALF: - return 2; - case IL_INT: - case IL_UNSIGNED_INT: - case IL_FLOAT: - return 4; - case IL_DOUBLE: - return 8; - } - return 0; -} - - -// Returns the type matching a bpc -ILAPI ILenum ILAPIENTRY ilGetTypeBpc(ILubyte Bpc) -{ - switch (Bpc) - { - case 1: - return IL_UNSIGNED_BYTE; - case 2: - return IL_UNSIGNED_SHORT; - case 4: - return IL_UNSIGNED_INT; - case 8: - return IL_DOUBLE; - } - return 0; -} - - -// Returns the bpp of any palette type (PalType) -ILAPI ILubyte ILAPIENTRY ilGetBppPal(ILenum PalType) -{ - switch (PalType) - { - case IL_PAL_RGB24: - case IL_PAL_BGR24: - return 3; - case IL_PAL_RGB32: - case IL_PAL_RGBA32: - case IL_PAL_BGR32: - case IL_PAL_BGRA32: - return 4; - } - return 0; -} - -// Returns the base format of a palette type (PalType) -ILAPI ILenum ILAPIENTRY ilGetPalBaseType(ILenum PalType) -{ - switch (PalType) - { - case IL_PAL_RGB24: - return IL_RGB; - case IL_PAL_RGB32: - return IL_RGBA; // Not sure - case IL_PAL_RGBA32: - return IL_RGBA; - case IL_PAL_BGR24: - return IL_BGR; - case IL_PAL_BGR32: - return IL_BGRA; // Not sure - case IL_PAL_BGRA32: - return IL_BGRA; - } - - return 0; -} - - -// Returns the next power of 2 if Num isn't 2^n or returns Num if Num is 2^n -ILAPI ILuint ILAPIENTRY ilNextPower2(ILuint n) -{ - ILuint power = 1; - while( power < n ) { - power <<= 1; - } - return power; -} - -ILAPI void ILAPIENTRY iMemSwap(ILubyte *s1, ILubyte *s2, const ILuint size) -{ - const ILuint block_size = 4096; - const ILuint blocks = size/block_size; - ILuint i; - - ILubyte *block = (ILubyte*)ialloc(block_size); - if(block == NULL) return; - for( i = 0; i < blocks; i++ ) { - memcpy(block,s1,block_size); - memcpy(s1,s2,block_size); - memcpy(s2,block,block_size); - s2 += block_size; - s1 += block_size; - } - i = size - i*block_size; - if( i > 0 ) { - memcpy(block,s1,i); - memcpy(s1,s2,i); - memcpy(s2,block,i); - } - ifree(block); - return; -} diff --git a/DevIL/src-IL/src/il_utility.cpp b/DevIL/src-IL/src/il_utility.cpp new file mode 100644 index 00000000..e2e6ca7a --- /dev/null +++ b/DevIL/src-IL/src/il_utility.cpp @@ -0,0 +1,171 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 02/04/2009 +// +// Filename: src-IL/src/il_utility.c +// +// Description: Utility functions +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" + + +// Returns the bpp of any Format +ILAPI ILubyte ILAPIENTRY ilGetBppFormat(ILenum Format) +{ + switch (Format) + { + case IL_COLOUR_INDEX: + case IL_LUMINANCE: + case IL_ALPHA: + return 1; + case IL_LUMINANCE_ALPHA: + return 2; + case IL_RGB: + case IL_BGR: + return 3; + case IL_RGBA: + case IL_BGRA: + return 4; + } + return 0; +} + + +// Returns the format of any bpp +ILAPI ILenum ILAPIENTRY ilGetFormatBpp(ILubyte Bpp) +{ + switch (Bpp) + { + case 1: + return IL_LUMINANCE; + case 2: + return IL_LUMINANCE_ALPHA; + case 3: + return IL_RGB; + case 4: + return IL_RGBA; + } + return 0; +} + + +// Returns the bpc of any Type +ILAPI ILubyte ILAPIENTRY ilGetBpcType(ILenum Type) +{ + switch (Type) + { + case IL_BYTE: + case IL_UNSIGNED_BYTE: + return 1; + case IL_SHORT: + case IL_UNSIGNED_SHORT: + case IL_HALF: + return 2; + case IL_INT: + case IL_UNSIGNED_INT: + case IL_FLOAT: + return 4; + case IL_DOUBLE: + return 8; + } + return 0; +} + + +// Returns the type matching a bpc +ILAPI ILenum ILAPIENTRY ilGetTypeBpc(ILubyte Bpc) +{ + switch (Bpc) + { + case 1: + return IL_UNSIGNED_BYTE; + case 2: + return IL_UNSIGNED_SHORT; + case 4: + return IL_UNSIGNED_INT; + case 8: + return IL_DOUBLE; + } + return 0; +} + + +// Returns the bpp of any palette type (PalType) +ILAPI ILubyte ILAPIENTRY ilGetBppPal(ILenum PalType) +{ + switch (PalType) + { + case IL_PAL_RGB24: + case IL_PAL_BGR24: + return 3; + case IL_PAL_RGB32: + case IL_PAL_RGBA32: + case IL_PAL_BGR32: + case IL_PAL_BGRA32: + return 4; + } + return 0; +} + +// Returns the base format of a palette type (PalType) +ILAPI ILenum ILAPIENTRY ilGetPalBaseType(ILenum PalType) +{ + switch (PalType) + { + case IL_PAL_RGB24: + return IL_RGB; + case IL_PAL_RGB32: + return IL_RGBA; // Not sure + case IL_PAL_RGBA32: + return IL_RGBA; + case IL_PAL_BGR24: + return IL_BGR; + case IL_PAL_BGR32: + return IL_BGRA; // Not sure + case IL_PAL_BGRA32: + return IL_BGRA; + } + + return 0; +} + + +// Returns the next power of 2 if Num isn't 2^n or returns Num if Num is 2^n +ILAPI ILuint ILAPIENTRY ilNextPower2(ILuint n) +{ + ILuint power = 1; + while( power < n ) { + power <<= 1; + } + return power; +} + +ILAPI void ILAPIENTRY iMemSwap(ILubyte *s1, ILubyte *s2, const ILuint size) +{ + const ILuint block_size = 4096; + const ILuint blocks = size/block_size; + ILuint i; + + ILubyte *block = (ILubyte*)ialloc(block_size); + if(block == NULL) return; + for( i = 0; i < blocks; i++ ) { + memcpy(block,s1,block_size); + memcpy(s1,s2,block_size); + memcpy(s2,block,block_size); + s2 += block_size; + s1 += block_size; + } + i = size - i*block_size; + if( i > 0 ) { + memcpy(block,s1,i); + memcpy(s1,s2,i); + memcpy(s2,block,i); + } + ifree(block); + return; +} diff --git a/DevIL/src-IL/src/il_vtf.c b/DevIL/src-IL/src/il_vtf.c deleted file mode 100644 index c49a614b..00000000 --- a/DevIL/src-IL/src/il_vtf.c +++ /dev/null @@ -1,953 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_vtf.c -// -// Description: Reads from and writes to a Valve Texture Format (.vtf) file. -// These are used in Valve's Source games. VTF specs available -// from http://developer.valvesoftware.com/wiki/VTF. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_VTF -#include "il_vtf.h" -#include "il_dds.h" - - -//@TODO: Get rid of these globals. -//static VTFHEAD Head; - - -//! Checks if the file specified in FileName is a valid VTF file. -ILboolean ilIsValidVtf(ILconst_string FileName) -{ - ILHANDLE VtfFile; - ILboolean bVtf = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("vtf"))) { - ilSetError(IL_INVALID_EXTENSION); - return bVtf; - } - - VtfFile = iopenr(FileName); - if (VtfFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bVtf; - } - - bVtf = ilIsValidVtfF(VtfFile); - icloser(VtfFile); - - return bVtf; -} - - -//! Checks if the ILHANDLE contains a valid VTF file at the current position. -ILboolean ilIsValidVtfF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidVtf(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid VTF lump. -ILboolean ilIsValidVtfL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidVtf(); -} - - -// Internal function used to get the VTF header from the current file. -ILboolean iGetVtfHead(VTFHEAD *Header) -{ - iread(Header->Signature, 1, 4); - Header->Version[0] = GetLittleUInt(); - Header->Version[1] = GetLittleUInt(); - Header->HeaderSize = GetLittleUInt(); - Header->Width = GetLittleUShort(); - Header->Height = GetLittleUShort(); - Header->Flags = GetLittleUInt(); - Header->Frames = GetLittleUShort(); - Header->FirstFrame = GetLittleUShort(); - iseek(4, IL_SEEK_CUR); // Padding - Header->Reflectivity[0] = GetLittleFloat(); - Header->Reflectivity[1] = GetLittleFloat(); - Header->Reflectivity[2] = GetLittleFloat(); - iseek(4, IL_SEEK_CUR); // Padding - Header->BumpmapScale = GetLittleFloat(); - Header->HighResImageFormat = GetLittleUInt(); - Header->MipmapCount = (ILubyte)igetc(); - Header->LowResImageFormat = GetLittleInt(); - Header->LowResImageWidth = (ILubyte)igetc(); - Header->LowResImageHeight = (ILubyte)igetc(); -//@TODO: This is a hack for the moment. - if (Header->HeaderSize == 64) { - Header->Depth = igetc(); - if (Header->Depth == 0) - Header->Depth = 1; - } - else { - Header->Depth = GetLittleUShort(); - iseek(Header->HeaderSize - sizeof(VTFHEAD), IL_SEEK_CUR); - } - - return IL_TRUE; -} - - -// Internal function to get the header and check it. -ILboolean iIsValidVtf(void) -{ - VTFHEAD Header; - - if (!iGetVtfHead(&Header)) - return IL_FALSE; - iseek(-(ILint)sizeof(VTFHEAD), IL_SEEK_CUR); - - return iCheckVtf(&Header); -} - - -//@TODO: Add more checks. -// Should we check for Frames, MipmapCount and Depth != 0? - -// Internal function used to check if the HEADER is a valid VTF header. -ILboolean iCheckVtf(VTFHEAD *Header) -{ - // The file signature is "VTF\0". - if ((Header->Signature[0] != 'V') || (Header->Signature[1] != 'T') || (Header->Signature[2] != 'F') - || (Header->Signature[3] != 0)) - return IL_FALSE; - // Are there other versions available yet? - if (Header->Version[0] != 7) - return IL_FALSE; - // We have 7.0 through 7.4 as of 12/27/2008. - if (Header->Version[1] > 4) - return IL_FALSE; - // May change in future version of the specifications. - // 80 is through version 7.2, and 96/104 are through 7.4. - // This must be 16-byte aligned, but something is outputting headers with 104. - if ((Header->HeaderSize != 80) && (Header->HeaderSize != 96) && (Header->HeaderSize != 104) - && (Header->HeaderSize != 64)) - return IL_FALSE; - - // 0 is an invalid dimension - if (Header->Width == 0 || Header->Height == 0) - return IL_FALSE; - // Width and Height must be powers of 2. - if ((ilNextPower2(Header->Width) != Header->Width) || (ilNextPower2(Header->Height) != Header->Height)) - return IL_FALSE; - // It looks like width and height of zero are valid - i.e. no low res image. - if (Header->LowResImageWidth != 0 && Header->LowResImageHeight != 0) { - if ((ilNextPower2(Header->LowResImageWidth) != Header->LowResImageWidth) - || (ilNextPower2(Header->LowResImageHeight) != Header->LowResImageHeight)) - return IL_FALSE; - } - // In addition, the LowResImage has to have dimensions no greater than 16. - if ((Header->LowResImageWidth > 16) || (Header->LowResImageHeight > 16)) - //|| (Header->LowResImageWidth == 0) || (Header->LowResImageHeight == 0)) - // It looks like width and height of zero are valid. - return IL_FALSE; - // And the LowResImage has to have dimensions less than or equal to the main image. - if ((Header->LowResImageWidth > Header->Width) || (Header->LowResImageHeight > Header->Height)) - return IL_FALSE; - // The LowResImage must be in DXT1 format, or if it does not exist, it is denoted by all bits set. - if (Header->LowResImageFormat != IMAGE_FORMAT_DXT1 && Header->LowResImageFormat != 0xFFFFFFFF) - return IL_FALSE; - - return IL_TRUE; -} - - -//! Reads a VTF file -ILboolean ilLoadVtf(ILconst_string FileName) -{ - ILHANDLE VtfFile; - ILboolean bVtf = IL_FALSE; - - VtfFile = iopenr(FileName); - if (VtfFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bVtf; - } - - bVtf = ilLoadVtfF(VtfFile); - icloser(VtfFile); - - return bVtf; -} - - -//! Reads an already-opened VTF file -ILboolean ilLoadVtfF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadVtfInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a VTF -ILboolean ilLoadVtfL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadVtfInternal(); -} - - -// Internal function used to load the VTF. -ILboolean iLoadVtfInternal(void) -{ - ILboolean bVtf = IL_TRUE; - ILimage *Image, *BaseImage; - ILenum Format, Type; - ILint Frame, Face, Mipmap; - ILuint SizeOfData, Channels, k; - ILubyte *CompData = NULL, SwapVal, *Data16Bit, *Temp, NumFaces; - VTFHEAD Head; - ILuint CurName; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - CurName = ilGetCurName(); - - if (!iGetVtfHead(&Head)) - return IL_FALSE; - if (!iCheckVtf(&Head)) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (Head.Flags & TEXTUREFLAGS_ENVMAP) { - // If we have a spherical map in addition to the 6 sides of the cubemap, FirstFrame's bits - // are all set. The only place I found out about this was VTFLib. - NumFaces = Head.FirstFrame == 0xFFFF ? 6 : 7; - } - else - NumFaces = 1; // This is not an environmental map. - - // Skip the low resolution image. This is just a thumbnail. - // The block size is 8, and the compression ratio is 6:1. - SizeOfData = IL_MAX(Head.LowResImageWidth * Head.LowResImageHeight / 2, 8); - if (Head.LowResImageWidth == 0 && Head.LowResImageHeight == 0) - SizeOfData = 0; // No low resolution image present. - iseek(SizeOfData, IL_SEEK_CUR); - - //@TODO: Make this a helper function that set channels, bpc and format. - switch (Head.HighResImageFormat) - { - case IMAGE_FORMAT_DXT1: //@TODO: Should we make DXT1 channels = 3? - case IMAGE_FORMAT_DXT1_ONEBITALPHA: - case IMAGE_FORMAT_DXT3: - case IMAGE_FORMAT_DXT5: - Channels = 4; - Format = IL_RGBA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGR888: - case IMAGE_FORMAT_BGR888_BLUESCREEN: - Channels = 3; - Format = IL_BGR; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGRA8888: - Channels = 4; - Format = IL_BGRA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGRX8888: - Channels = 3; - Format = IL_BGR; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_RGB888: - case IMAGE_FORMAT_RGB888_BLUESCREEN: - Channels = 3; - Format = IL_RGB; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_RGBA8888: - Channels = 4; - Format = IL_RGBA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_RGBA16161616: // 16-bit shorts - Channels = 4; - Format = IL_RGBA; - Type = IL_UNSIGNED_SHORT; - break; - case IMAGE_FORMAT_RGBA16161616F: // 16-bit floats - Channels = 4; - Format = IL_RGBA; - Type = IL_FLOAT; - break; - case IMAGE_FORMAT_I8: // 8-bit luminance data - Channels = 1; - Format = IL_LUMINANCE; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_IA88: // 8-bit luminance and alpha data - Channels = 2; - Format = IL_LUMINANCE_ALPHA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_A8: // 8-bit alpha data - Channels = 1; - Format = IL_ALPHA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_ARGB8888: - Channels = 4; - Format = IL_BGRA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_ABGR8888: - Channels = 4; - Format = IL_RGBA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_RGB565: - Channels = 3; - Format = IL_RGB; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGR565: - Channels = 3; - Format = IL_BGR; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGRA5551: - Channels = 4; - Format = IL_BGRA; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGRX5551: // Unused alpha channel - Channels = 3; - Format = IL_BGR; - Type = IL_UNSIGNED_BYTE; - break; - case IMAGE_FORMAT_BGRA4444: - Channels = 4; - Format = IL_BGRA; - Type = IL_UNSIGNED_BYTE; - break; - - default: - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - - if (!ilTexImage(Head.Width, Head.Height, Head.Depth, Channels, Format, Type, NULL)) - return IL_FALSE; - // The origin should be in the upper left. - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - // Create any mipmaps. - VtfInitFacesMipmaps(iCurImage, NumFaces, &Head); - - // Create our animation chain - BaseImage = Image = iCurImage; // Top-level image - for (Frame = 1; Frame < Head.Frames; Frame++) { - Image->Next = ilNewImageFull(Head.Width, Head.Height, Head.Depth, Channels, Format, Type, NULL); - if (Image->Next == NULL) - return IL_FALSE; - Image = Image->Next; - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - - // Create our faces and mipmaps for each frame. - VtfInitFacesMipmaps(Image, NumFaces, &Head); - } - - // We want to put the smallest mipmap at the end, but it is first in the file, so we count backwards. - for (Mipmap = Head.MipmapCount - 1; Mipmap >= 0; Mipmap--) { - // Frames are in the normal order. - for (Frame = 0; Frame < Head.Frames; Frame++) { - // @TODO: Cubemap faces are always in the same order? - for (Face = 0; Face < NumFaces; Face++) { - //@TODO: Would probably be quicker to do the linked list traversal manually here. - ilBindImage(CurName); - ilActiveImage(Frame); - ilActiveFace(Face); - ilActiveMipmap(Mipmap); - Image = iCurImage; - - switch (Head.HighResImageFormat) - { - // DXT1 compression - case IMAGE_FORMAT_DXT1: - case IMAGE_FORMAT_DXT1_ONEBITALPHA: - // The block size is 8. - SizeOfData = IL_MAX(Image->Width * Image->Height * Image->Depth / 2, 8); - CompData = ialloc(SizeOfData); // Gives a 6:1 compression ratio (or 8:1 for DXT1 with alpha) - if (CompData == NULL) - return IL_FALSE; - iread(CompData, 1, SizeOfData); - // Keep a copy of the DXTC data if the user wants it. - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = SizeOfData; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT5; - CompData = NULL; - } - bVtf = DecompressDXT1(Image, CompData); - break; - - // DXT3 compression - case IMAGE_FORMAT_DXT3: - // The block size is 16. - SizeOfData = IL_MAX(Image->Width * Image->Height * Image->Depth, 16); - CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio - if (CompData == NULL) - return IL_FALSE; - iread(CompData, 1, SizeOfData); - // Keep a copy of the DXTC data if the user wants it. - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = SizeOfData; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT3; - CompData = NULL; - } - bVtf = DecompressDXT3(Image, CompData); - break; - - // DXT5 compression - case IMAGE_FORMAT_DXT5: - // The block size is 16. - SizeOfData = IL_MAX(Image->Width * Image->Height * Image->Depth, 16); - CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio - if (CompData == NULL) - return IL_FALSE; - iread(CompData, 1, SizeOfData); - // Keep a copy of the DXTC data if the user wants it. - if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { - Image->DxtcSize = SizeOfData; - Image->DxtcData = CompData; - Image->DxtcFormat = IL_DXT5; - CompData = NULL; - } - bVtf = DecompressDXT5(Image, CompData); - break; - - // Uncompressed BGR(A) data (24-bit and 32-bit) - case IMAGE_FORMAT_BGR888: - case IMAGE_FORMAT_BGRA8888: - // Uncompressed RGB(A) data (24-bit and 32-bit) - case IMAGE_FORMAT_RGB888: - case IMAGE_FORMAT_RGBA8888: - // Uncompressed 16-bit shorts - case IMAGE_FORMAT_RGBA16161616: - // Luminance data only - case IMAGE_FORMAT_I8: - // Luminance and alpha data - case IMAGE_FORMAT_IA88: - // Alpha data only - case IMAGE_FORMAT_A8: - // We will ignore the part about the bluescreen right now. - // I could not find any information about it. - case IMAGE_FORMAT_RGB888_BLUESCREEN: - case IMAGE_FORMAT_BGR888_BLUESCREEN: - // Just copy the data over - no compression. - if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) - bVtf = IL_FALSE; - else - bVtf = IL_TRUE; - break; - - // Uncompressed 24-bit data with an unused alpha channel (we discard it) - case IMAGE_FORMAT_BGRX8888: - SizeOfData = Image->Width * Image->Height * Image->Depth * 3; - Temp = CompData = ialloc(SizeOfData / 3 * 4); // Not compressed data - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData / 3 * 4) != SizeOfData / 3 * 4) { - bVtf = IL_FALSE; - break; - } - for (k = 0; k < SizeOfData; k += 3) { - Image->Data[k] = Temp[0]; - Image->Data[k+1] = Temp[1]; - Image->Data[k+2] = Temp[2]; - Temp += 4; - } - - break; - - // Uncompressed 16-bit floats (must be converted to 32-bit) - case IMAGE_FORMAT_RGBA16161616F: - SizeOfData = Image->Width * Image->Height * Image->Depth * Image->Bpp * 2; - CompData = ialloc(SizeOfData); // Not compressed data - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - bVtf = IL_FALSE; - break; - } - bVtf = iConvFloat16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, SizeOfData / 2); - break; - - // Uncompressed 32-bit ARGB and ABGR data. DevIL does not handle this - // internally, so we have to swap values. - case IMAGE_FORMAT_ARGB8888: - case IMAGE_FORMAT_ABGR8888: - if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) { - bVtf = IL_FALSE; - break; - } - else { - bVtf = IL_TRUE; - } - // Swap the data - for (k = 0; k < Image->SizeOfData; k += 4) { - SwapVal = Image->Data[k]; - Image->Data[k] = Image->Data[k+3]; - Image->Data[k+3] = SwapVal; - SwapVal = Image->Data[k+1]; - Image->Data[k+1] = Image->Data[k+2]; - Image->Data[k+2] = SwapVal; - } - break; - - // Uncompressed 16-bit RGB and BGR data. We have to expand this to 24-bit, since - // DevIL does not handle this internally. - // The data is in the file as: gggbbbbb rrrrrrggg - case IMAGE_FORMAT_RGB565: - case IMAGE_FORMAT_BGR565: - SizeOfData = Image->Width * Image->Height * Image->Depth * 2; - Data16Bit = CompData = ialloc(SizeOfData); // Not compressed data - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - bVtf = IL_FALSE; - break; - } - for (k = 0; k < Image->SizeOfData; k += 3) { - Image->Data[k] = (Data16Bit[0] & 0x1F) << 3; - Image->Data[k+1] = ((Data16Bit[1] & 0x07) << 5) | ((Data16Bit[0] & 0xE0) >> 3); - Image->Data[k+2] = Data16Bit[1] & 0xF8; - Data16Bit += 2; - } - break; - - // Uncompressed 16-bit BGRA data (1-bit alpha). We have to expand this to 32-bit, - // since DevIL does not handle this internally. - // Something seems strange with this one, but this is how VTFEdit outputs. - // The data is in the file as: gggbbbbb arrrrrgg - case IMAGE_FORMAT_BGRA5551: - SizeOfData = Image->Width * Image->Height * Image->Depth * 2; - Data16Bit = CompData = ialloc(SizeOfData); // Not compressed data - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - bVtf = IL_FALSE; - break; - } - for (k = 0; k < Image->SizeOfData; k += 4) { - Image->Data[k] = (Data16Bit[0] & 0x1F) << 3; - Image->Data[k+1] = ((Data16Bit[0] & 0xE0) >> 2) | ((Data16Bit[1] & 0x03) << 6); - Image->Data[k+2] = (Data16Bit[1] & 0x7C) << 1; - // 1-bit alpha is either off or on. - Image->Data[k+3] = ((Data16Bit[0] & 0x80) == 0x80) ? 0xFF : 0x00; - Data16Bit += 2; - } - break; - - // Same as above, but the alpha channel is unused. - case IMAGE_FORMAT_BGRX5551: - SizeOfData = Image->Width * Image->Height * Image->Depth * 2; - Data16Bit = CompData = ialloc(SizeOfData); // Not compressed data - if (iread(CompData, 1, SizeOfData) != SizeOfData) { - bVtf = IL_FALSE; - break; - } - for (k = 0; k < Image->SizeOfData; k += 3) { - Image->Data[k] = (Data16Bit[0] & 0x1F) << 3; - Image->Data[k+1] = ((Data16Bit[0] & 0xE0) >> 2) | ((Data16Bit[1] & 0x03) << 6); - Image->Data[k+2] = (Data16Bit[1] & 0x7C) << 1; - Data16Bit += 2; - } - break; - - // Data is reduced to a 4-bits per channel format. - case IMAGE_FORMAT_BGRA4444: - SizeOfData = Image->Width * Image->Height * Image->Depth * 4; - Temp = CompData = ialloc(SizeOfData / 2); // Not compressed data - if (CompData == NULL) - return IL_FALSE; - if (iread(CompData, 1, SizeOfData / 2) != SizeOfData / 2) { - bVtf = IL_FALSE; - break; - } - for (k = 0; k < SizeOfData; k += 4) { - // We double the data here. - Image->Data[k] = (Temp[0] & 0x0F) << 4 | (Temp[0] & 0x0F); - Image->Data[k+1] = (Temp[0] & 0xF0) >> 4 | (Temp[0] & 0xF0); - Image->Data[k+2] = (Temp[1] & 0x0F) << 4 | (Temp[1] & 0x0F); - Image->Data[k+3] = (Temp[1] & 0xF0) >> 4 | (Temp[1] & 0xF0); - Temp += 2; - } - break; - } - - ifree(CompData); - CompData = NULL; - if (bVtf == IL_FALSE) //@TODO: Do we need to do any cleanup here? - return IL_FALSE; - } - } - } - - ilBindImage(CurName); // Set to parent image first. - return ilFixImage(); -} - - -ILuint GetFaceFlag(ILuint FaceNum) -{ - switch (FaceNum) - { - case 0: - return IL_CUBEMAP_POSITIVEX; - case 1: - return IL_CUBEMAP_NEGATIVEX; - case 2: - return IL_CUBEMAP_POSITIVEY; - case 3: - return IL_CUBEMAP_NEGATIVEY; - case 4: - return IL_CUBEMAP_POSITIVEZ; - case 5: - return IL_CUBEMAP_NEGATIVEZ; - case 6: - return IL_SPHEREMAP; - } - - return IL_SPHEREMAP; // Should never reach here! -} - - -ILboolean VtfInitFacesMipmaps(ILimage *BaseImage, ILuint NumFaces, VTFHEAD *Header) -{ - ILimage *Image; - ILuint Face; - - // Initialize mipmaps under the base image. - VtfInitMipmaps(BaseImage, Header); - Image = BaseImage; - - // We have an environment map. - if (NumFaces != 1) { - Image->CubeFlags = IL_CUBEMAP_POSITIVEX; - } - - for (Face = 1; Face < NumFaces; Face++) { - Image->Faces = ilNewImageFull(Image->Width, Image->Height, Image->Depth, Image->Bpp, Image->Format, Image->Type, NULL); - if (Image->Faces == NULL) - return IL_FALSE; - Image = Image->Faces; - - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - // Set the flags that tell which face this is. - Image->CubeFlags = GetFaceFlag(Face); - - // Now we can initialize the mipmaps under each face. - VtfInitMipmaps(Image, Header); - } - - return IL_TRUE; -} - - -ILboolean VtfInitMipmaps(ILimage *BaseImage, VTFHEAD *Header) -{ - ILimage *Image; - ILuint Width, Height, Depth, Mipmap; - - Image = BaseImage; - Width = BaseImage->Width; Height = BaseImage->Height; Depth = BaseImage->Depth; - - for (Mipmap = 1; Mipmap < Header->MipmapCount; Mipmap++) { - // 1 is the smallest dimension possible. - Width = (Width >> 1) == 0 ? 1 : (Width >> 1); - Height = (Height >> 1) == 0 ? 1 : (Height >> 1); - Depth = (Depth >> 1) == 0 ? 1 : (Depth >> 1); - - Image->Mipmaps = ilNewImageFull(Width, Height, Depth, BaseImage->Bpp, BaseImage->Format, BaseImage->Type, NULL); - if (Image->Mipmaps == NULL) - return IL_FALSE; - Image = Image->Mipmaps; - - // ilNewImage does not set these. - Image->Format = BaseImage->Format; - Image->Type = BaseImage->Type; - // The origin should be in the upper left. - Image->Origin = IL_ORIGIN_UPPER_LEFT; - } - - return IL_TRUE; -} - - - -ILboolean CheckDimensions() -{ - if ((ilNextPower2(iCurImage->Width) != iCurImage->Width) || (ilNextPower2(iCurImage->Height) != iCurImage->Height)) { - ilSetError(IL_BAD_DIMENSIONS); - return IL_FALSE; - } - return IL_TRUE; -} - -//! Writes a Vtf file -ILboolean ilSaveVtf(const ILstring FileName) -{ - ILHANDLE VtfFile; - ILuint VtfSize; - - if (!CheckDimensions()) - return IL_FALSE; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - VtfFile = iopenw(FileName); - if (VtfFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - VtfSize = ilSaveVtfF(VtfFile); - iclosew(VtfFile); - - if (VtfSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a .vtf to an already-opened file -ILuint ilSaveVtfF(ILHANDLE File) -{ - ILuint Pos; - if (!CheckDimensions()) - return 0; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveVtfInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a .vtf to a memory "lump" -ILuint ilSaveVtfL(void *Lump, ILuint Size) -{ - ILuint Pos; - if (!CheckDimensions()) - return 0; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveVtfInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// Internal function used to save the Vtf. -ILboolean iSaveVtfInternal() -{ - ILimage *TempImage = iCurImage; - ILubyte *TempData, *CompData; - ILuint Format, i, CompSize; - ILenum Compression; - - // Find out if the user has specified to use DXT compression. - Compression = ilGetInteger(IL_VTF_COMP); - - //@TODO: Other formats - if (Compression == IL_DXT_NO_COMP) { - switch (TempImage->Format) - { - case IL_RGB: - Format = IMAGE_FORMAT_RGB888; - break; - case IL_RGBA: - Format = IMAGE_FORMAT_RGBA8888; - break; - case IL_BGR: - Format = IMAGE_FORMAT_BGR888; - break; - case IL_BGRA: - Format = IMAGE_FORMAT_BGRA8888; - break; - case IL_LUMINANCE: - Format = IMAGE_FORMAT_I8; - break; - case IL_ALPHA: - Format = IMAGE_FORMAT_A8; - break; - case IL_LUMINANCE_ALPHA: - Format = IMAGE_FORMAT_IA88; - break; - //case IL_COLOUR_INDEX: - default: - Format = IMAGE_FORMAT_BGRA8888; - TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - } - - //@TODO: When we have the half format available internally, also use IMAGE_FORMAT_RGBA16161616F. - if (TempImage->Format == IL_RGBA && TempImage->Type == IL_UNSIGNED_SHORT) { - Format = IMAGE_FORMAT_RGBA16161616; - } - else if (TempImage->Type != IL_UNSIGNED_BYTE) { //@TODO: Any possibility for shorts, etc. to be used? - TempImage = iConvertImage(iCurImage, Format, IL_UNSIGNED_BYTE); - if (TempImage == NULL) - return IL_FALSE; - } - } - else { // We are using DXT compression. - switch (Compression) - { - case IL_DXT1: - Format = IMAGE_FORMAT_DXT1_ONEBITALPHA;//IMAGE_FORMAT_DXT1; - break; - case IL_DXT3: - Format = IMAGE_FORMAT_DXT3; - break; - case IL_DXT5: - Format = IMAGE_FORMAT_DXT5; - break; - default: // Should never reach this point. - ilSetError(IL_INTERNAL_ERROR); - Format = IMAGE_FORMAT_DXT5; - } - } - - if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - ilCloseImage(TempImage); - return IL_FALSE; - } - } else { - TempData = TempImage->Data; - } - - // Write the file signature. - iwrite("VTF", 1, 4); - // Write the file version - currently using 7.2 specs. - SaveLittleUInt(7); - SaveLittleUInt(2); - // Write the header size. - SaveLittleUInt(80); - // Now we write the width and height of the image. - SaveLittleUShort(TempImage->Width); - SaveLittleUShort(TempImage->Height); - //@TODO: This is supposed to be the flags used. What should we use here? Let users specify? - SaveLittleUInt(0); - // Number of frames in the animation. - @TODO: Change to use animations. - SaveLittleUShort(1); - // First frame in the animation - SaveLittleUShort(0); - // Padding - SaveLittleUInt(0); - // Reflectivity (3 floats) - @TODO: Use what values? User specified? - SaveLittleFloat(0.0f); - SaveLittleFloat(0.0f); - SaveLittleFloat(0.0f); - // Padding - SaveLittleUInt(0); - // Bumpmap scale - SaveLittleFloat(0.0f); - // Image format - SaveLittleUInt(Format); - // Mipmap count - @TODO: Use mipmaps - iputc(1); - // Low resolution image format - @TODO: Create low resolution image. - SaveLittleUInt(0xFFFFFFFF); - // Low resolution image width and height - iputc(0); - iputc(0); - // Depth of the image - @TODO: Support for volumetric images. - SaveLittleUShort(1); - - // Write final padding for the header (out to 80 bytes). - for (i = 0; i < 15; i++) { - iputc(0); - } - - if (Compression == IL_DXT_NO_COMP) { - // We just write the image data directly. - if (iwrite(TempImage->Data, TempImage->SizeOfData, 1) != 1) - return IL_FALSE; - } - else { // Do DXT compression here and write. - // We have to find out how much we are writing first. - CompSize = ilGetDXTCData(NULL, 0, Compression); - if (CompSize == 0) { - ilSetError(IL_INTERNAL_ERROR); - if (TempData != TempImage->Data) - ifree(TempData); - return IL_FALSE; - } - CompData = (ILubyte*)ialloc(CompSize); - if (CompData == NULL) { - if (TempData != TempImage->Data) - ifree(TempData); - return IL_FALSE; - } - - // DXT compress the data. - CompSize = ilGetDXTCData(CompData, CompSize, Compression); - if (CompSize == 0) { - ilSetError(IL_INTERNAL_ERROR); - if (TempData != TempImage->Data) - ifree(TempData); - return IL_FALSE; - } - // Finally write the data. - if (iwrite(CompData, CompSize, 1) != 1) { - ifree(CompData); - if (TempData != TempImage->Data) - ifree(TempData); - return IL_FALSE; - } - } - - if (TempData != TempImage->Data) - ifree(TempData); - if (TempImage != iCurImage) - ilCloseImage(TempImage); - - return IL_TRUE; -} - - -#endif//IL_NO_VTF diff --git a/DevIL/src-IL/src/il_vtf.cpp b/DevIL/src-IL/src/il_vtf.cpp new file mode 100644 index 00000000..c49a614b --- /dev/null +++ b/DevIL/src-IL/src/il_vtf.cpp @@ -0,0 +1,953 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_vtf.c +// +// Description: Reads from and writes to a Valve Texture Format (.vtf) file. +// These are used in Valve's Source games. VTF specs available +// from http://developer.valvesoftware.com/wiki/VTF. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_VTF +#include "il_vtf.h" +#include "il_dds.h" + + +//@TODO: Get rid of these globals. +//static VTFHEAD Head; + + +//! Checks if the file specified in FileName is a valid VTF file. +ILboolean ilIsValidVtf(ILconst_string FileName) +{ + ILHANDLE VtfFile; + ILboolean bVtf = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("vtf"))) { + ilSetError(IL_INVALID_EXTENSION); + return bVtf; + } + + VtfFile = iopenr(FileName); + if (VtfFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bVtf; + } + + bVtf = ilIsValidVtfF(VtfFile); + icloser(VtfFile); + + return bVtf; +} + + +//! Checks if the ILHANDLE contains a valid VTF file at the current position. +ILboolean ilIsValidVtfF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidVtf(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid VTF lump. +ILboolean ilIsValidVtfL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidVtf(); +} + + +// Internal function used to get the VTF header from the current file. +ILboolean iGetVtfHead(VTFHEAD *Header) +{ + iread(Header->Signature, 1, 4); + Header->Version[0] = GetLittleUInt(); + Header->Version[1] = GetLittleUInt(); + Header->HeaderSize = GetLittleUInt(); + Header->Width = GetLittleUShort(); + Header->Height = GetLittleUShort(); + Header->Flags = GetLittleUInt(); + Header->Frames = GetLittleUShort(); + Header->FirstFrame = GetLittleUShort(); + iseek(4, IL_SEEK_CUR); // Padding + Header->Reflectivity[0] = GetLittleFloat(); + Header->Reflectivity[1] = GetLittleFloat(); + Header->Reflectivity[2] = GetLittleFloat(); + iseek(4, IL_SEEK_CUR); // Padding + Header->BumpmapScale = GetLittleFloat(); + Header->HighResImageFormat = GetLittleUInt(); + Header->MipmapCount = (ILubyte)igetc(); + Header->LowResImageFormat = GetLittleInt(); + Header->LowResImageWidth = (ILubyte)igetc(); + Header->LowResImageHeight = (ILubyte)igetc(); +//@TODO: This is a hack for the moment. + if (Header->HeaderSize == 64) { + Header->Depth = igetc(); + if (Header->Depth == 0) + Header->Depth = 1; + } + else { + Header->Depth = GetLittleUShort(); + iseek(Header->HeaderSize - sizeof(VTFHEAD), IL_SEEK_CUR); + } + + return IL_TRUE; +} + + +// Internal function to get the header and check it. +ILboolean iIsValidVtf(void) +{ + VTFHEAD Header; + + if (!iGetVtfHead(&Header)) + return IL_FALSE; + iseek(-(ILint)sizeof(VTFHEAD), IL_SEEK_CUR); + + return iCheckVtf(&Header); +} + + +//@TODO: Add more checks. +// Should we check for Frames, MipmapCount and Depth != 0? + +// Internal function used to check if the HEADER is a valid VTF header. +ILboolean iCheckVtf(VTFHEAD *Header) +{ + // The file signature is "VTF\0". + if ((Header->Signature[0] != 'V') || (Header->Signature[1] != 'T') || (Header->Signature[2] != 'F') + || (Header->Signature[3] != 0)) + return IL_FALSE; + // Are there other versions available yet? + if (Header->Version[0] != 7) + return IL_FALSE; + // We have 7.0 through 7.4 as of 12/27/2008. + if (Header->Version[1] > 4) + return IL_FALSE; + // May change in future version of the specifications. + // 80 is through version 7.2, and 96/104 are through 7.4. + // This must be 16-byte aligned, but something is outputting headers with 104. + if ((Header->HeaderSize != 80) && (Header->HeaderSize != 96) && (Header->HeaderSize != 104) + && (Header->HeaderSize != 64)) + return IL_FALSE; + + // 0 is an invalid dimension + if (Header->Width == 0 || Header->Height == 0) + return IL_FALSE; + // Width and Height must be powers of 2. + if ((ilNextPower2(Header->Width) != Header->Width) || (ilNextPower2(Header->Height) != Header->Height)) + return IL_FALSE; + // It looks like width and height of zero are valid - i.e. no low res image. + if (Header->LowResImageWidth != 0 && Header->LowResImageHeight != 0) { + if ((ilNextPower2(Header->LowResImageWidth) != Header->LowResImageWidth) + || (ilNextPower2(Header->LowResImageHeight) != Header->LowResImageHeight)) + return IL_FALSE; + } + // In addition, the LowResImage has to have dimensions no greater than 16. + if ((Header->LowResImageWidth > 16) || (Header->LowResImageHeight > 16)) + //|| (Header->LowResImageWidth == 0) || (Header->LowResImageHeight == 0)) + // It looks like width and height of zero are valid. + return IL_FALSE; + // And the LowResImage has to have dimensions less than or equal to the main image. + if ((Header->LowResImageWidth > Header->Width) || (Header->LowResImageHeight > Header->Height)) + return IL_FALSE; + // The LowResImage must be in DXT1 format, or if it does not exist, it is denoted by all bits set. + if (Header->LowResImageFormat != IMAGE_FORMAT_DXT1 && Header->LowResImageFormat != 0xFFFFFFFF) + return IL_FALSE; + + return IL_TRUE; +} + + +//! Reads a VTF file +ILboolean ilLoadVtf(ILconst_string FileName) +{ + ILHANDLE VtfFile; + ILboolean bVtf = IL_FALSE; + + VtfFile = iopenr(FileName); + if (VtfFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bVtf; + } + + bVtf = ilLoadVtfF(VtfFile); + icloser(VtfFile); + + return bVtf; +} + + +//! Reads an already-opened VTF file +ILboolean ilLoadVtfF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadVtfInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a VTF +ILboolean ilLoadVtfL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadVtfInternal(); +} + + +// Internal function used to load the VTF. +ILboolean iLoadVtfInternal(void) +{ + ILboolean bVtf = IL_TRUE; + ILimage *Image, *BaseImage; + ILenum Format, Type; + ILint Frame, Face, Mipmap; + ILuint SizeOfData, Channels, k; + ILubyte *CompData = NULL, SwapVal, *Data16Bit, *Temp, NumFaces; + VTFHEAD Head; + ILuint CurName; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + CurName = ilGetCurName(); + + if (!iGetVtfHead(&Head)) + return IL_FALSE; + if (!iCheckVtf(&Head)) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (Head.Flags & TEXTUREFLAGS_ENVMAP) { + // If we have a spherical map in addition to the 6 sides of the cubemap, FirstFrame's bits + // are all set. The only place I found out about this was VTFLib. + NumFaces = Head.FirstFrame == 0xFFFF ? 6 : 7; + } + else + NumFaces = 1; // This is not an environmental map. + + // Skip the low resolution image. This is just a thumbnail. + // The block size is 8, and the compression ratio is 6:1. + SizeOfData = IL_MAX(Head.LowResImageWidth * Head.LowResImageHeight / 2, 8); + if (Head.LowResImageWidth == 0 && Head.LowResImageHeight == 0) + SizeOfData = 0; // No low resolution image present. + iseek(SizeOfData, IL_SEEK_CUR); + + //@TODO: Make this a helper function that set channels, bpc and format. + switch (Head.HighResImageFormat) + { + case IMAGE_FORMAT_DXT1: //@TODO: Should we make DXT1 channels = 3? + case IMAGE_FORMAT_DXT1_ONEBITALPHA: + case IMAGE_FORMAT_DXT3: + case IMAGE_FORMAT_DXT5: + Channels = 4; + Format = IL_RGBA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGR888: + case IMAGE_FORMAT_BGR888_BLUESCREEN: + Channels = 3; + Format = IL_BGR; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGRA8888: + Channels = 4; + Format = IL_BGRA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGRX8888: + Channels = 3; + Format = IL_BGR; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_RGB888: + case IMAGE_FORMAT_RGB888_BLUESCREEN: + Channels = 3; + Format = IL_RGB; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_RGBA8888: + Channels = 4; + Format = IL_RGBA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_RGBA16161616: // 16-bit shorts + Channels = 4; + Format = IL_RGBA; + Type = IL_UNSIGNED_SHORT; + break; + case IMAGE_FORMAT_RGBA16161616F: // 16-bit floats + Channels = 4; + Format = IL_RGBA; + Type = IL_FLOAT; + break; + case IMAGE_FORMAT_I8: // 8-bit luminance data + Channels = 1; + Format = IL_LUMINANCE; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_IA88: // 8-bit luminance and alpha data + Channels = 2; + Format = IL_LUMINANCE_ALPHA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_A8: // 8-bit alpha data + Channels = 1; + Format = IL_ALPHA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_ARGB8888: + Channels = 4; + Format = IL_BGRA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_ABGR8888: + Channels = 4; + Format = IL_RGBA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_RGB565: + Channels = 3; + Format = IL_RGB; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGR565: + Channels = 3; + Format = IL_BGR; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGRA5551: + Channels = 4; + Format = IL_BGRA; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGRX5551: // Unused alpha channel + Channels = 3; + Format = IL_BGR; + Type = IL_UNSIGNED_BYTE; + break; + case IMAGE_FORMAT_BGRA4444: + Channels = 4; + Format = IL_BGRA; + Type = IL_UNSIGNED_BYTE; + break; + + default: + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + + if (!ilTexImage(Head.Width, Head.Height, Head.Depth, Channels, Format, Type, NULL)) + return IL_FALSE; + // The origin should be in the upper left. + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + // Create any mipmaps. + VtfInitFacesMipmaps(iCurImage, NumFaces, &Head); + + // Create our animation chain + BaseImage = Image = iCurImage; // Top-level image + for (Frame = 1; Frame < Head.Frames; Frame++) { + Image->Next = ilNewImageFull(Head.Width, Head.Height, Head.Depth, Channels, Format, Type, NULL); + if (Image->Next == NULL) + return IL_FALSE; + Image = Image->Next; + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + + // Create our faces and mipmaps for each frame. + VtfInitFacesMipmaps(Image, NumFaces, &Head); + } + + // We want to put the smallest mipmap at the end, but it is first in the file, so we count backwards. + for (Mipmap = Head.MipmapCount - 1; Mipmap >= 0; Mipmap--) { + // Frames are in the normal order. + for (Frame = 0; Frame < Head.Frames; Frame++) { + // @TODO: Cubemap faces are always in the same order? + for (Face = 0; Face < NumFaces; Face++) { + //@TODO: Would probably be quicker to do the linked list traversal manually here. + ilBindImage(CurName); + ilActiveImage(Frame); + ilActiveFace(Face); + ilActiveMipmap(Mipmap); + Image = iCurImage; + + switch (Head.HighResImageFormat) + { + // DXT1 compression + case IMAGE_FORMAT_DXT1: + case IMAGE_FORMAT_DXT1_ONEBITALPHA: + // The block size is 8. + SizeOfData = IL_MAX(Image->Width * Image->Height * Image->Depth / 2, 8); + CompData = ialloc(SizeOfData); // Gives a 6:1 compression ratio (or 8:1 for DXT1 with alpha) + if (CompData == NULL) + return IL_FALSE; + iread(CompData, 1, SizeOfData); + // Keep a copy of the DXTC data if the user wants it. + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = SizeOfData; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT5; + CompData = NULL; + } + bVtf = DecompressDXT1(Image, CompData); + break; + + // DXT3 compression + case IMAGE_FORMAT_DXT3: + // The block size is 16. + SizeOfData = IL_MAX(Image->Width * Image->Height * Image->Depth, 16); + CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio + if (CompData == NULL) + return IL_FALSE; + iread(CompData, 1, SizeOfData); + // Keep a copy of the DXTC data if the user wants it. + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = SizeOfData; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT3; + CompData = NULL; + } + bVtf = DecompressDXT3(Image, CompData); + break; + + // DXT5 compression + case IMAGE_FORMAT_DXT5: + // The block size is 16. + SizeOfData = IL_MAX(Image->Width * Image->Height * Image->Depth, 16); + CompData = ialloc(SizeOfData); // Gives a 4:1 compression ratio + if (CompData == NULL) + return IL_FALSE; + iread(CompData, 1, SizeOfData); + // Keep a copy of the DXTC data if the user wants it. + if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { + Image->DxtcSize = SizeOfData; + Image->DxtcData = CompData; + Image->DxtcFormat = IL_DXT5; + CompData = NULL; + } + bVtf = DecompressDXT5(Image, CompData); + break; + + // Uncompressed BGR(A) data (24-bit and 32-bit) + case IMAGE_FORMAT_BGR888: + case IMAGE_FORMAT_BGRA8888: + // Uncompressed RGB(A) data (24-bit and 32-bit) + case IMAGE_FORMAT_RGB888: + case IMAGE_FORMAT_RGBA8888: + // Uncompressed 16-bit shorts + case IMAGE_FORMAT_RGBA16161616: + // Luminance data only + case IMAGE_FORMAT_I8: + // Luminance and alpha data + case IMAGE_FORMAT_IA88: + // Alpha data only + case IMAGE_FORMAT_A8: + // We will ignore the part about the bluescreen right now. + // I could not find any information about it. + case IMAGE_FORMAT_RGB888_BLUESCREEN: + case IMAGE_FORMAT_BGR888_BLUESCREEN: + // Just copy the data over - no compression. + if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) + bVtf = IL_FALSE; + else + bVtf = IL_TRUE; + break; + + // Uncompressed 24-bit data with an unused alpha channel (we discard it) + case IMAGE_FORMAT_BGRX8888: + SizeOfData = Image->Width * Image->Height * Image->Depth * 3; + Temp = CompData = ialloc(SizeOfData / 3 * 4); // Not compressed data + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData / 3 * 4) != SizeOfData / 3 * 4) { + bVtf = IL_FALSE; + break; + } + for (k = 0; k < SizeOfData; k += 3) { + Image->Data[k] = Temp[0]; + Image->Data[k+1] = Temp[1]; + Image->Data[k+2] = Temp[2]; + Temp += 4; + } + + break; + + // Uncompressed 16-bit floats (must be converted to 32-bit) + case IMAGE_FORMAT_RGBA16161616F: + SizeOfData = Image->Width * Image->Height * Image->Depth * Image->Bpp * 2; + CompData = ialloc(SizeOfData); // Not compressed data + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + bVtf = IL_FALSE; + break; + } + bVtf = iConvFloat16ToFloat32((ILuint*)Image->Data, (ILushort*)CompData, SizeOfData / 2); + break; + + // Uncompressed 32-bit ARGB and ABGR data. DevIL does not handle this + // internally, so we have to swap values. + case IMAGE_FORMAT_ARGB8888: + case IMAGE_FORMAT_ABGR8888: + if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) { + bVtf = IL_FALSE; + break; + } + else { + bVtf = IL_TRUE; + } + // Swap the data + for (k = 0; k < Image->SizeOfData; k += 4) { + SwapVal = Image->Data[k]; + Image->Data[k] = Image->Data[k+3]; + Image->Data[k+3] = SwapVal; + SwapVal = Image->Data[k+1]; + Image->Data[k+1] = Image->Data[k+2]; + Image->Data[k+2] = SwapVal; + } + break; + + // Uncompressed 16-bit RGB and BGR data. We have to expand this to 24-bit, since + // DevIL does not handle this internally. + // The data is in the file as: gggbbbbb rrrrrrggg + case IMAGE_FORMAT_RGB565: + case IMAGE_FORMAT_BGR565: + SizeOfData = Image->Width * Image->Height * Image->Depth * 2; + Data16Bit = CompData = ialloc(SizeOfData); // Not compressed data + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + bVtf = IL_FALSE; + break; + } + for (k = 0; k < Image->SizeOfData; k += 3) { + Image->Data[k] = (Data16Bit[0] & 0x1F) << 3; + Image->Data[k+1] = ((Data16Bit[1] & 0x07) << 5) | ((Data16Bit[0] & 0xE0) >> 3); + Image->Data[k+2] = Data16Bit[1] & 0xF8; + Data16Bit += 2; + } + break; + + // Uncompressed 16-bit BGRA data (1-bit alpha). We have to expand this to 32-bit, + // since DevIL does not handle this internally. + // Something seems strange with this one, but this is how VTFEdit outputs. + // The data is in the file as: gggbbbbb arrrrrgg + case IMAGE_FORMAT_BGRA5551: + SizeOfData = Image->Width * Image->Height * Image->Depth * 2; + Data16Bit = CompData = ialloc(SizeOfData); // Not compressed data + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + bVtf = IL_FALSE; + break; + } + for (k = 0; k < Image->SizeOfData; k += 4) { + Image->Data[k] = (Data16Bit[0] & 0x1F) << 3; + Image->Data[k+1] = ((Data16Bit[0] & 0xE0) >> 2) | ((Data16Bit[1] & 0x03) << 6); + Image->Data[k+2] = (Data16Bit[1] & 0x7C) << 1; + // 1-bit alpha is either off or on. + Image->Data[k+3] = ((Data16Bit[0] & 0x80) == 0x80) ? 0xFF : 0x00; + Data16Bit += 2; + } + break; + + // Same as above, but the alpha channel is unused. + case IMAGE_FORMAT_BGRX5551: + SizeOfData = Image->Width * Image->Height * Image->Depth * 2; + Data16Bit = CompData = ialloc(SizeOfData); // Not compressed data + if (iread(CompData, 1, SizeOfData) != SizeOfData) { + bVtf = IL_FALSE; + break; + } + for (k = 0; k < Image->SizeOfData; k += 3) { + Image->Data[k] = (Data16Bit[0] & 0x1F) << 3; + Image->Data[k+1] = ((Data16Bit[0] & 0xE0) >> 2) | ((Data16Bit[1] & 0x03) << 6); + Image->Data[k+2] = (Data16Bit[1] & 0x7C) << 1; + Data16Bit += 2; + } + break; + + // Data is reduced to a 4-bits per channel format. + case IMAGE_FORMAT_BGRA4444: + SizeOfData = Image->Width * Image->Height * Image->Depth * 4; + Temp = CompData = ialloc(SizeOfData / 2); // Not compressed data + if (CompData == NULL) + return IL_FALSE; + if (iread(CompData, 1, SizeOfData / 2) != SizeOfData / 2) { + bVtf = IL_FALSE; + break; + } + for (k = 0; k < SizeOfData; k += 4) { + // We double the data here. + Image->Data[k] = (Temp[0] & 0x0F) << 4 | (Temp[0] & 0x0F); + Image->Data[k+1] = (Temp[0] & 0xF0) >> 4 | (Temp[0] & 0xF0); + Image->Data[k+2] = (Temp[1] & 0x0F) << 4 | (Temp[1] & 0x0F); + Image->Data[k+3] = (Temp[1] & 0xF0) >> 4 | (Temp[1] & 0xF0); + Temp += 2; + } + break; + } + + ifree(CompData); + CompData = NULL; + if (bVtf == IL_FALSE) //@TODO: Do we need to do any cleanup here? + return IL_FALSE; + } + } + } + + ilBindImage(CurName); // Set to parent image first. + return ilFixImage(); +} + + +ILuint GetFaceFlag(ILuint FaceNum) +{ + switch (FaceNum) + { + case 0: + return IL_CUBEMAP_POSITIVEX; + case 1: + return IL_CUBEMAP_NEGATIVEX; + case 2: + return IL_CUBEMAP_POSITIVEY; + case 3: + return IL_CUBEMAP_NEGATIVEY; + case 4: + return IL_CUBEMAP_POSITIVEZ; + case 5: + return IL_CUBEMAP_NEGATIVEZ; + case 6: + return IL_SPHEREMAP; + } + + return IL_SPHEREMAP; // Should never reach here! +} + + +ILboolean VtfInitFacesMipmaps(ILimage *BaseImage, ILuint NumFaces, VTFHEAD *Header) +{ + ILimage *Image; + ILuint Face; + + // Initialize mipmaps under the base image. + VtfInitMipmaps(BaseImage, Header); + Image = BaseImage; + + // We have an environment map. + if (NumFaces != 1) { + Image->CubeFlags = IL_CUBEMAP_POSITIVEX; + } + + for (Face = 1; Face < NumFaces; Face++) { + Image->Faces = ilNewImageFull(Image->Width, Image->Height, Image->Depth, Image->Bpp, Image->Format, Image->Type, NULL); + if (Image->Faces == NULL) + return IL_FALSE; + Image = Image->Faces; + + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + // Set the flags that tell which face this is. + Image->CubeFlags = GetFaceFlag(Face); + + // Now we can initialize the mipmaps under each face. + VtfInitMipmaps(Image, Header); + } + + return IL_TRUE; +} + + +ILboolean VtfInitMipmaps(ILimage *BaseImage, VTFHEAD *Header) +{ + ILimage *Image; + ILuint Width, Height, Depth, Mipmap; + + Image = BaseImage; + Width = BaseImage->Width; Height = BaseImage->Height; Depth = BaseImage->Depth; + + for (Mipmap = 1; Mipmap < Header->MipmapCount; Mipmap++) { + // 1 is the smallest dimension possible. + Width = (Width >> 1) == 0 ? 1 : (Width >> 1); + Height = (Height >> 1) == 0 ? 1 : (Height >> 1); + Depth = (Depth >> 1) == 0 ? 1 : (Depth >> 1); + + Image->Mipmaps = ilNewImageFull(Width, Height, Depth, BaseImage->Bpp, BaseImage->Format, BaseImage->Type, NULL); + if (Image->Mipmaps == NULL) + return IL_FALSE; + Image = Image->Mipmaps; + + // ilNewImage does not set these. + Image->Format = BaseImage->Format; + Image->Type = BaseImage->Type; + // The origin should be in the upper left. + Image->Origin = IL_ORIGIN_UPPER_LEFT; + } + + return IL_TRUE; +} + + + +ILboolean CheckDimensions() +{ + if ((ilNextPower2(iCurImage->Width) != iCurImage->Width) || (ilNextPower2(iCurImage->Height) != iCurImage->Height)) { + ilSetError(IL_BAD_DIMENSIONS); + return IL_FALSE; + } + return IL_TRUE; +} + +//! Writes a Vtf file +ILboolean ilSaveVtf(const ILstring FileName) +{ + ILHANDLE VtfFile; + ILuint VtfSize; + + if (!CheckDimensions()) + return IL_FALSE; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + VtfFile = iopenw(FileName); + if (VtfFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + VtfSize = ilSaveVtfF(VtfFile); + iclosew(VtfFile); + + if (VtfSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a .vtf to an already-opened file +ILuint ilSaveVtfF(ILHANDLE File) +{ + ILuint Pos; + if (!CheckDimensions()) + return 0; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveVtfInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a .vtf to a memory "lump" +ILuint ilSaveVtfL(void *Lump, ILuint Size) +{ + ILuint Pos; + if (!CheckDimensions()) + return 0; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveVtfInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// Internal function used to save the Vtf. +ILboolean iSaveVtfInternal() +{ + ILimage *TempImage = iCurImage; + ILubyte *TempData, *CompData; + ILuint Format, i, CompSize; + ILenum Compression; + + // Find out if the user has specified to use DXT compression. + Compression = ilGetInteger(IL_VTF_COMP); + + //@TODO: Other formats + if (Compression == IL_DXT_NO_COMP) { + switch (TempImage->Format) + { + case IL_RGB: + Format = IMAGE_FORMAT_RGB888; + break; + case IL_RGBA: + Format = IMAGE_FORMAT_RGBA8888; + break; + case IL_BGR: + Format = IMAGE_FORMAT_BGR888; + break; + case IL_BGRA: + Format = IMAGE_FORMAT_BGRA8888; + break; + case IL_LUMINANCE: + Format = IMAGE_FORMAT_I8; + break; + case IL_ALPHA: + Format = IMAGE_FORMAT_A8; + break; + case IL_LUMINANCE_ALPHA: + Format = IMAGE_FORMAT_IA88; + break; + //case IL_COLOUR_INDEX: + default: + Format = IMAGE_FORMAT_BGRA8888; + TempImage = iConvertImage(iCurImage, IL_BGRA, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + } + + //@TODO: When we have the half format available internally, also use IMAGE_FORMAT_RGBA16161616F. + if (TempImage->Format == IL_RGBA && TempImage->Type == IL_UNSIGNED_SHORT) { + Format = IMAGE_FORMAT_RGBA16161616; + } + else if (TempImage->Type != IL_UNSIGNED_BYTE) { //@TODO: Any possibility for shorts, etc. to be used? + TempImage = iConvertImage(iCurImage, Format, IL_UNSIGNED_BYTE); + if (TempImage == NULL) + return IL_FALSE; + } + } + else { // We are using DXT compression. + switch (Compression) + { + case IL_DXT1: + Format = IMAGE_FORMAT_DXT1_ONEBITALPHA;//IMAGE_FORMAT_DXT1; + break; + case IL_DXT3: + Format = IMAGE_FORMAT_DXT3; + break; + case IL_DXT5: + Format = IMAGE_FORMAT_DXT5; + break; + default: // Should never reach this point. + ilSetError(IL_INTERNAL_ERROR); + Format = IMAGE_FORMAT_DXT5; + } + } + + if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + ilCloseImage(TempImage); + return IL_FALSE; + } + } else { + TempData = TempImage->Data; + } + + // Write the file signature. + iwrite("VTF", 1, 4); + // Write the file version - currently using 7.2 specs. + SaveLittleUInt(7); + SaveLittleUInt(2); + // Write the header size. + SaveLittleUInt(80); + // Now we write the width and height of the image. + SaveLittleUShort(TempImage->Width); + SaveLittleUShort(TempImage->Height); + //@TODO: This is supposed to be the flags used. What should we use here? Let users specify? + SaveLittleUInt(0); + // Number of frames in the animation. - @TODO: Change to use animations. + SaveLittleUShort(1); + // First frame in the animation + SaveLittleUShort(0); + // Padding + SaveLittleUInt(0); + // Reflectivity (3 floats) - @TODO: Use what values? User specified? + SaveLittleFloat(0.0f); + SaveLittleFloat(0.0f); + SaveLittleFloat(0.0f); + // Padding + SaveLittleUInt(0); + // Bumpmap scale + SaveLittleFloat(0.0f); + // Image format + SaveLittleUInt(Format); + // Mipmap count - @TODO: Use mipmaps + iputc(1); + // Low resolution image format - @TODO: Create low resolution image. + SaveLittleUInt(0xFFFFFFFF); + // Low resolution image width and height + iputc(0); + iputc(0); + // Depth of the image - @TODO: Support for volumetric images. + SaveLittleUShort(1); + + // Write final padding for the header (out to 80 bytes). + for (i = 0; i < 15; i++) { + iputc(0); + } + + if (Compression == IL_DXT_NO_COMP) { + // We just write the image data directly. + if (iwrite(TempImage->Data, TempImage->SizeOfData, 1) != 1) + return IL_FALSE; + } + else { // Do DXT compression here and write. + // We have to find out how much we are writing first. + CompSize = ilGetDXTCData(NULL, 0, Compression); + if (CompSize == 0) { + ilSetError(IL_INTERNAL_ERROR); + if (TempData != TempImage->Data) + ifree(TempData); + return IL_FALSE; + } + CompData = (ILubyte*)ialloc(CompSize); + if (CompData == NULL) { + if (TempData != TempImage->Data) + ifree(TempData); + return IL_FALSE; + } + + // DXT compress the data. + CompSize = ilGetDXTCData(CompData, CompSize, Compression); + if (CompSize == 0) { + ilSetError(IL_INTERNAL_ERROR); + if (TempData != TempImage->Data) + ifree(TempData); + return IL_FALSE; + } + // Finally write the data. + if (iwrite(CompData, CompSize, 1) != 1) { + ifree(CompData); + if (TempData != TempImage->Data) + ifree(TempData); + return IL_FALSE; + } + } + + if (TempData != TempImage->Data) + ifree(TempData); + if (TempImage != iCurImage) + ilCloseImage(TempImage); + + return IL_TRUE; +} + + +#endif//IL_NO_VTF diff --git a/DevIL/src-IL/src/il_wal.c b/DevIL/src-IL/src/il_wal.c deleted file mode 100644 index 67f8117c..00000000 --- a/DevIL/src-IL/src/il_wal.c +++ /dev/null @@ -1,168 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_wal.c -// -// Description: Loads a Quake .wal texture. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_WAL -#include "il_q2pal.h" - - -typedef struct WALHEAD -{ - ILbyte FileName[32]; // Image name - ILuint Width; // Width of first image - ILuint Height; // Height of first image - ILuint Offsets[4]; // Offsets to image data - ILbyte AnimName[32]; // Name of next frame - ILuint Flags; // ?? - ILuint Contents; // ?? - ILuint Value; // ?? -} WALHEAD; - -ILboolean iLoadWalInternal(void); - - -//! Reads a .wal file -ILboolean ilLoadWal(ILconst_string FileName) -{ - ILHANDLE WalFile; - ILboolean bWal = IL_FALSE; - - WalFile = iopenr(FileName); - if (WalFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bWal; - } - - bWal = ilLoadWalF(WalFile); - icloser(WalFile); - - return bWal; -} - - -//! Reads an already-opened .wal file -ILboolean ilLoadWalF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadWalInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .wal file -ILboolean ilLoadWalL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadWalInternal(); -} - - -ILboolean iLoadWalInternal() -{ - WALHEAD Header; - ILimage *Mipmaps[3], *CurImage; - ILuint i, NewW, NewH; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - CurImage = iCurImage; - - - // Read header - iread(&Header.FileName, 1, 32); - Header.Width = GetLittleUInt(); - Header.Height = GetLittleUInt(); - - for (i = 0; i < 4; i++) - Header.Offsets[i] = GetLittleUInt(); - - iread(Header.AnimName, 1, 32); - Header.Flags = GetLittleUInt(); - Header.Contents = GetLittleUInt(); - Header.Value = GetLittleUInt(); - - if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - - for (i = 0; i < 3; i++) { - Mipmaps[i] = (ILimage*)icalloc(sizeof(ILimage), 1); - if (Mipmaps[i] == NULL) - goto cleanup_error; - Mipmaps[i]->Pal.Palette = (ILubyte*)ialloc(768); - if (Mipmaps[i]->Pal.Palette == NULL) - goto cleanup_error; - memcpy(Mipmaps[i]->Pal.Palette, ilDefaultQ2Pal, 768); - Mipmaps[i]->Pal.PalType = IL_PAL_RGB24; - } - - NewW = Header.Width; - NewH = Header.Height; - for (i = 0; i < 3; i++) { - NewW /= 2; - NewH /= 2; - iCurImage = Mipmaps[i]; - if (!ilTexImage(NewW, NewH, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) - goto cleanup_error; - // Don't set until now so ilTexImage won't get rid of the palette. - Mipmaps[i]->Pal.PalSize = 768; - Mipmaps[i]->Origin = IL_ORIGIN_UPPER_LEFT; - } - - iCurImage = CurImage; - ilCloseImage(iCurImage->Mipmaps); - iCurImage->Mipmaps = Mipmaps[0]; - Mipmaps[0]->Mipmaps = Mipmaps[1]; - Mipmaps[1]->Mipmaps = Mipmaps[2]; - - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) - ifree(iCurImage->Pal.Palette); - iCurImage->Pal.Palette = (ILubyte*)ialloc(768); - if (iCurImage->Pal.Palette == NULL) - goto cleanup_error; - - iCurImage->Pal.PalSize = 768; - iCurImage->Pal.PalType = IL_PAL_RGB24; - memcpy(iCurImage->Pal.Palette, ilDefaultQ2Pal, 768); - - iseek(Header.Offsets[0], IL_SEEK_SET); - if (iread(iCurImage->Data, Header.Width * Header.Height, 1) != 1) - goto cleanup_error; - - for (i = 0; i < 3; i++) { - iseek(Header.Offsets[i+1], IL_SEEK_SET); - if (iread(Mipmaps[i]->Data, Mipmaps[i]->Width * Mipmaps[i]->Height, 1) != 1) - goto cleanup_error; - } - - // Fixes all images, even mipmaps. - return ilFixImage(); - -cleanup_error: - for (i = 0; i < 3; i++) { - ilCloseImage(Mipmaps[i]); - } - return IL_FALSE; -} - - -#endif//IL_NO_WAL diff --git a/DevIL/src-IL/src/il_wal.cpp b/DevIL/src-IL/src/il_wal.cpp new file mode 100644 index 00000000..67f8117c --- /dev/null +++ b/DevIL/src-IL/src/il_wal.cpp @@ -0,0 +1,168 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_wal.c +// +// Description: Loads a Quake .wal texture. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_WAL +#include "il_q2pal.h" + + +typedef struct WALHEAD +{ + ILbyte FileName[32]; // Image name + ILuint Width; // Width of first image + ILuint Height; // Height of first image + ILuint Offsets[4]; // Offsets to image data + ILbyte AnimName[32]; // Name of next frame + ILuint Flags; // ?? + ILuint Contents; // ?? + ILuint Value; // ?? +} WALHEAD; + +ILboolean iLoadWalInternal(void); + + +//! Reads a .wal file +ILboolean ilLoadWal(ILconst_string FileName) +{ + ILHANDLE WalFile; + ILboolean bWal = IL_FALSE; + + WalFile = iopenr(FileName); + if (WalFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bWal; + } + + bWal = ilLoadWalF(WalFile); + icloser(WalFile); + + return bWal; +} + + +//! Reads an already-opened .wal file +ILboolean ilLoadWalF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadWalInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .wal file +ILboolean ilLoadWalL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadWalInternal(); +} + + +ILboolean iLoadWalInternal() +{ + WALHEAD Header; + ILimage *Mipmaps[3], *CurImage; + ILuint i, NewW, NewH; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + CurImage = iCurImage; + + + // Read header + iread(&Header.FileName, 1, 32); + Header.Width = GetLittleUInt(); + Header.Height = GetLittleUInt(); + + for (i = 0; i < 4; i++) + Header.Offsets[i] = GetLittleUInt(); + + iread(Header.AnimName, 1, 32); + Header.Flags = GetLittleUInt(); + Header.Contents = GetLittleUInt(); + Header.Value = GetLittleUInt(); + + if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + + for (i = 0; i < 3; i++) { + Mipmaps[i] = (ILimage*)icalloc(sizeof(ILimage), 1); + if (Mipmaps[i] == NULL) + goto cleanup_error; + Mipmaps[i]->Pal.Palette = (ILubyte*)ialloc(768); + if (Mipmaps[i]->Pal.Palette == NULL) + goto cleanup_error; + memcpy(Mipmaps[i]->Pal.Palette, ilDefaultQ2Pal, 768); + Mipmaps[i]->Pal.PalType = IL_PAL_RGB24; + } + + NewW = Header.Width; + NewH = Header.Height; + for (i = 0; i < 3; i++) { + NewW /= 2; + NewH /= 2; + iCurImage = Mipmaps[i]; + if (!ilTexImage(NewW, NewH, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) + goto cleanup_error; + // Don't set until now so ilTexImage won't get rid of the palette. + Mipmaps[i]->Pal.PalSize = 768; + Mipmaps[i]->Origin = IL_ORIGIN_UPPER_LEFT; + } + + iCurImage = CurImage; + ilCloseImage(iCurImage->Mipmaps); + iCurImage->Mipmaps = Mipmaps[0]; + Mipmaps[0]->Mipmaps = Mipmaps[1]; + Mipmaps[1]->Mipmaps = Mipmaps[2]; + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE) + ifree(iCurImage->Pal.Palette); + iCurImage->Pal.Palette = (ILubyte*)ialloc(768); + if (iCurImage->Pal.Palette == NULL) + goto cleanup_error; + + iCurImage->Pal.PalSize = 768; + iCurImage->Pal.PalType = IL_PAL_RGB24; + memcpy(iCurImage->Pal.Palette, ilDefaultQ2Pal, 768); + + iseek(Header.Offsets[0], IL_SEEK_SET); + if (iread(iCurImage->Data, Header.Width * Header.Height, 1) != 1) + goto cleanup_error; + + for (i = 0; i < 3; i++) { + iseek(Header.Offsets[i+1], IL_SEEK_SET); + if (iread(Mipmaps[i]->Data, Mipmaps[i]->Width * Mipmaps[i]->Height, 1) != 1) + goto cleanup_error; + } + + // Fixes all images, even mipmaps. + return ilFixImage(); + +cleanup_error: + for (i = 0; i < 3; i++) { + ilCloseImage(Mipmaps[i]); + } + return IL_FALSE; +} + + +#endif//IL_NO_WAL diff --git a/DevIL/src-IL/src/il_wbmp.c b/DevIL/src-IL/src/il_wbmp.c deleted file mode 100755 index 27cf285e..00000000 --- a/DevIL/src-IL/src/il_wbmp.c +++ /dev/null @@ -1,274 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 03/07/2009 -// -// Filename: src-IL/src/il_wbmp.c -// -// Description: Reads from a Wireless Bitmap (.wbmp) file. Specs available from -// http://www.ibm.com/developerworks/wireless/library/wi-wbmp/ -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_WBMP -#include "il_bits.h" - - -ILboolean iLoadWbmpInternal(void); -ILuint WbmpGetMultibyte(void); -ILboolean iSaveWbmpInternal(void); - -// Reads a .wbmp file -ILboolean ilLoadWbmp(ILconst_string FileName) -{ - ILHANDLE WbmpFile; - ILboolean bWbmp = IL_FALSE; - - WbmpFile = iopenr(FileName); - if (WbmpFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bWbmp; - } - - iSetInputFile(WbmpFile); - - bWbmp = ilLoadWbmpF(WbmpFile); - - icloser(WbmpFile); - - return bWbmp; -} - - -//! Reads an already-opened .wbmp file -ILboolean ilLoadWbmpF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadWbmpInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a .wbmp -ILboolean ilLoadWbmpL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadWbmpInternal(); -} - - -ILboolean iLoadWbmpInternal(void) -{ - ILuint Width, Height, BitPadding, i; - BITFILE *File; - ILubyte Padding[8]; - - if (iCurImage == NULL) { - ilSetError(IL_ILLEGAL_OPERATION); - return IL_FALSE; - } - - if (igetc() != 0 || igetc() != 0) { // The first two bytes have to be 0 (the "header") - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - Width = WbmpGetMultibyte(); // Next follows the width and height. - Height = WbmpGetMultibyte(); - - if (Width == 0 || Height == 0) { // Must have at least some height and width. - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - if (!ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) - return IL_FALSE; - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Always has origin in the upper left. - - BitPadding = (8 - (Width % 8)) % 8; // Has to be aligned on a byte boundary. The rest is padding. - File = bfile(iGetFile()); - if (File == NULL) - return IL_FALSE; //@TODO: Error? - - //@TODO: Do this without bread? Would be faster, since we would not have to do - // the second loop. - - // Reads the bits - for (i = 0; i < iCurImage->Height; i++) { - bread(&iCurImage->Data[iCurImage->Width * i], 1, iCurImage->Width, File); - //bseek(File, BitPadding, IL_SEEK_CUR); //@TODO: This function does not work correctly. - bread(Padding, 1, BitPadding, File); // Skip padding bits. - } - // Converts bit value of 1 to white and leaves 0 at 0 (2-colour images only). - for (i = 0; i < iCurImage->SizeOfData; i++) { - if (iCurImage->Data[i] == 1) - iCurImage->Data[i] = 0xFF; // White - } - - bclose(File); - - return IL_TRUE; -} - - -ILuint WbmpGetMultibyte() -{ - ILuint Val = 0, i; - ILubyte Cur; - - for (i = 0; i < 5; i++) { // Should not be more than 5 bytes. - Cur = igetc(); - Val = (Val << 7) | (Cur & 0x7F); // Drop the MSB of Cur. - if (!(Cur & 0x80)) { // Check the MSB and break if 0. - break; - } - } - - return Val; -} - - -ILboolean WbmpPutMultibyte(ILuint Val) -{ - ILint i, NumBytes = 0; - ILuint MultiVal = Val; - - do { - MultiVal >>= 7; - NumBytes++; - } while (MultiVal != 0); - - for (i = NumBytes - 1; i >= 0; i--) { - MultiVal = (Val >> (i * 7)) & 0x7F; - if (i != 0) - MultiVal |= 0x80; - iputc(MultiVal); - } - - return IL_TRUE; -} - - -//! Writes a Wbmp file -ILboolean ilSaveWbmp(const ILstring FileName) -{ - ILHANDLE WbmpFile; - ILuint WbmpSize; - - if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { - if (iFileExists(FileName)) { - ilSetError(IL_FILE_ALREADY_EXISTS); - return IL_FALSE; - } - } - - WbmpFile = iopenw(FileName); - if (WbmpFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return IL_FALSE; - } - - WbmpSize = ilSaveWbmpF(WbmpFile); - iclosew(WbmpFile); - - if (WbmpSize == 0) - return IL_FALSE; - return IL_TRUE; -} - - -//! Writes a .wbmp to an already-opened file -ILuint ilSaveWbmpF(ILHANDLE File) -{ - ILuint Pos; - iSetOutputFile(File); - Pos = itellw(); - if (iSaveWbmpInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -//! Writes a .wbmp to a memory "lump" -ILuint ilSaveWbmpL(void *Lump, ILuint Size) -{ - ILuint Pos; - iSetOutputLump(Lump, Size); - Pos = itellw(); - if (iSaveWbmpInternal() == IL_FALSE) - return 0; // Error occurred - return itellw() - Pos; // Return the number of bytes written. -} - - -// In il_quantizer.c -ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols); -// In il_neuquant.c -ILimage *iNeuQuant(ILimage *Image, ILuint NumCols); - - -// Internal function used to save the Wbmp. -ILboolean iSaveWbmpInternal() -{ - ILimage *TempImage = NULL; - ILuint i, j; - ILint k; - ILubyte Val; - ILubyte *TempData; - - iputc(0); // First two header values - iputc(0); // must be 0. - - WbmpPutMultibyte(iCurImage->Width); // Write the width - WbmpPutMultibyte(iCurImage->Height); // and the height. - - //TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE); - if (iGetInt(IL_QUANTIZATION_MODE) == IL_NEU_QUANT) - TempImage = iNeuQuant(iCurImage, 2); - else // Assume IL_WU_QUANT otherwise. - TempImage = iQuantizeImage(iCurImage, 2); - - if (TempImage == NULL) - return IL_FALSE; - - if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { - TempData = iGetFlipped(TempImage); - if (TempData == NULL) { - ilCloseImage(TempImage); - return IL_FALSE; - } - } else { - TempData = TempImage->Data; - } - - for (i = 0; i < TempImage->Height; i++) { - for (j = 0; j < TempImage->Width; j += 8) { - Val = 0; - for (k = 0; k < 8; k++) { - if (j + k < TempImage->Width) { - //Val |= ((TempData[TempImage->Width * i + j + k] > 0x7F) ? (0x80 >> k) : 0x00); - Val |= ((TempData[TempImage->Width * i + j + k] == 1) ? (0x80 >> k) : 0x00); - } - } - iputc(Val); - } - } - - if (TempData != TempImage->Data) - ifree(TempData); - ilCloseImage(TempImage); - - return IL_TRUE; -} - -#endif//IL_NO_WBMP - diff --git a/DevIL/src-IL/src/il_wbmp.cpp b/DevIL/src-IL/src/il_wbmp.cpp new file mode 100755 index 00000000..27cf285e --- /dev/null +++ b/DevIL/src-IL/src/il_wbmp.cpp @@ -0,0 +1,274 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 03/07/2009 +// +// Filename: src-IL/src/il_wbmp.c +// +// Description: Reads from a Wireless Bitmap (.wbmp) file. Specs available from +// http://www.ibm.com/developerworks/wireless/library/wi-wbmp/ +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_WBMP +#include "il_bits.h" + + +ILboolean iLoadWbmpInternal(void); +ILuint WbmpGetMultibyte(void); +ILboolean iSaveWbmpInternal(void); + +// Reads a .wbmp file +ILboolean ilLoadWbmp(ILconst_string FileName) +{ + ILHANDLE WbmpFile; + ILboolean bWbmp = IL_FALSE; + + WbmpFile = iopenr(FileName); + if (WbmpFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bWbmp; + } + + iSetInputFile(WbmpFile); + + bWbmp = ilLoadWbmpF(WbmpFile); + + icloser(WbmpFile); + + return bWbmp; +} + + +//! Reads an already-opened .wbmp file +ILboolean ilLoadWbmpF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadWbmpInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a .wbmp +ILboolean ilLoadWbmpL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadWbmpInternal(); +} + + +ILboolean iLoadWbmpInternal(void) +{ + ILuint Width, Height, BitPadding, i; + BITFILE *File; + ILubyte Padding[8]; + + if (iCurImage == NULL) { + ilSetError(IL_ILLEGAL_OPERATION); + return IL_FALSE; + } + + if (igetc() != 0 || igetc() != 0) { // The first two bytes have to be 0 (the "header") + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + Width = WbmpGetMultibyte(); // Next follows the width and height. + Height = WbmpGetMultibyte(); + + if (Width == 0 || Height == 0) { // Must have at least some height and width. + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + if (!ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) + return IL_FALSE; + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Always has origin in the upper left. + + BitPadding = (8 - (Width % 8)) % 8; // Has to be aligned on a byte boundary. The rest is padding. + File = bfile(iGetFile()); + if (File == NULL) + return IL_FALSE; //@TODO: Error? + + //@TODO: Do this without bread? Would be faster, since we would not have to do + // the second loop. + + // Reads the bits + for (i = 0; i < iCurImage->Height; i++) { + bread(&iCurImage->Data[iCurImage->Width * i], 1, iCurImage->Width, File); + //bseek(File, BitPadding, IL_SEEK_CUR); //@TODO: This function does not work correctly. + bread(Padding, 1, BitPadding, File); // Skip padding bits. + } + // Converts bit value of 1 to white and leaves 0 at 0 (2-colour images only). + for (i = 0; i < iCurImage->SizeOfData; i++) { + if (iCurImage->Data[i] == 1) + iCurImage->Data[i] = 0xFF; // White + } + + bclose(File); + + return IL_TRUE; +} + + +ILuint WbmpGetMultibyte() +{ + ILuint Val = 0, i; + ILubyte Cur; + + for (i = 0; i < 5; i++) { // Should not be more than 5 bytes. + Cur = igetc(); + Val = (Val << 7) | (Cur & 0x7F); // Drop the MSB of Cur. + if (!(Cur & 0x80)) { // Check the MSB and break if 0. + break; + } + } + + return Val; +} + + +ILboolean WbmpPutMultibyte(ILuint Val) +{ + ILint i, NumBytes = 0; + ILuint MultiVal = Val; + + do { + MultiVal >>= 7; + NumBytes++; + } while (MultiVal != 0); + + for (i = NumBytes - 1; i >= 0; i--) { + MultiVal = (Val >> (i * 7)) & 0x7F; + if (i != 0) + MultiVal |= 0x80; + iputc(MultiVal); + } + + return IL_TRUE; +} + + +//! Writes a Wbmp file +ILboolean ilSaveWbmp(const ILstring FileName) +{ + ILHANDLE WbmpFile; + ILuint WbmpSize; + + if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) { + if (iFileExists(FileName)) { + ilSetError(IL_FILE_ALREADY_EXISTS); + return IL_FALSE; + } + } + + WbmpFile = iopenw(FileName); + if (WbmpFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return IL_FALSE; + } + + WbmpSize = ilSaveWbmpF(WbmpFile); + iclosew(WbmpFile); + + if (WbmpSize == 0) + return IL_FALSE; + return IL_TRUE; +} + + +//! Writes a .wbmp to an already-opened file +ILuint ilSaveWbmpF(ILHANDLE File) +{ + ILuint Pos; + iSetOutputFile(File); + Pos = itellw(); + if (iSaveWbmpInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +//! Writes a .wbmp to a memory "lump" +ILuint ilSaveWbmpL(void *Lump, ILuint Size) +{ + ILuint Pos; + iSetOutputLump(Lump, Size); + Pos = itellw(); + if (iSaveWbmpInternal() == IL_FALSE) + return 0; // Error occurred + return itellw() - Pos; // Return the number of bytes written. +} + + +// In il_quantizer.c +ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols); +// In il_neuquant.c +ILimage *iNeuQuant(ILimage *Image, ILuint NumCols); + + +// Internal function used to save the Wbmp. +ILboolean iSaveWbmpInternal() +{ + ILimage *TempImage = NULL; + ILuint i, j; + ILint k; + ILubyte Val; + ILubyte *TempData; + + iputc(0); // First two header values + iputc(0); // must be 0. + + WbmpPutMultibyte(iCurImage->Width); // Write the width + WbmpPutMultibyte(iCurImage->Height); // and the height. + + //TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE); + if (iGetInt(IL_QUANTIZATION_MODE) == IL_NEU_QUANT) + TempImage = iNeuQuant(iCurImage, 2); + else // Assume IL_WU_QUANT otherwise. + TempImage = iQuantizeImage(iCurImage, 2); + + if (TempImage == NULL) + return IL_FALSE; + + if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) { + TempData = iGetFlipped(TempImage); + if (TempData == NULL) { + ilCloseImage(TempImage); + return IL_FALSE; + } + } else { + TempData = TempImage->Data; + } + + for (i = 0; i < TempImage->Height; i++) { + for (j = 0; j < TempImage->Width; j += 8) { + Val = 0; + for (k = 0; k < 8; k++) { + if (j + k < TempImage->Width) { + //Val |= ((TempData[TempImage->Width * i + j + k] > 0x7F) ? (0x80 >> k) : 0x00); + Val |= ((TempData[TempImage->Width * i + j + k] == 1) ? (0x80 >> k) : 0x00); + } + } + iputc(Val); + } + } + + if (TempData != TempImage->Data) + ifree(TempData); + ilCloseImage(TempImage); + + return IL_TRUE; +} + +#endif//IL_NO_WBMP + diff --git a/DevIL/src-IL/src/il_wdp.c b/DevIL/src-IL/src/il_wdp.c deleted file mode 100644 index fa78211c..00000000 --- a/DevIL/src-IL/src/il_wdp.c +++ /dev/null @@ -1,429 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Last modified: 02/09/2009 -// -// Filename: src-IL/src/il_wdp.c -// -// Description: Reads a Microsoft HD Photo (.wdp or .hdp) -// Based very much on the Microsoft HD Photo Device Porting Kit 1.0 -// available at -// http://www.microsoft.com/downloads/details.aspx?FamilyID=285eeffd-d86c-48c3-ab93-3abd5ee7f1ce&displaylang=en. -// -// Note: The license that the Device Porting Kit is under is not very clear. -// Commentary on the license can be found at http://en.wikipedia.org/wiki/HD_Photo. -// Lots of this code is taken from the examples in the DPK and from code -// within the DPK itself. For this reason, this file is not under the LGPL -// license, unlike the rest of DevIL. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_WDP -#include -#include "il_wdp.h" - -#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) - #if defined(_MSC_VER) || defined(__BORLANDC__) - #ifndef _DEBUG - #pragma comment(lib, "wmplib.lib") - #else - #pragma comment(lib, "wmplib-d.lib") - #endif - #endif -#endif - - -//! Reads a WDP file -ILboolean ilLoadWdp(ILconst_string FileName) -{ - ILHANDLE WdpFile; - ILboolean bWdp = IL_FALSE; - - WdpFile = iopenr(FileName); - if (WdpFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bWdp; - } - - bWdp = ilLoadWdpF(WdpFile); - icloser(WdpFile); - - return bWdp; -} - - -//! Reads an already-opened WDP file -ILboolean ilLoadWdpF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadWdpInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains a WDP -ILboolean ilLoadWdpL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iLoadWdpInternal(); -} - -//@TODO: Put in ilPKImageEncode_WritePixels_DevIL? -ERR WriteDevILHeader(PKImageEncode* pIE) -{ - struct WMPStream* pS = pIE->pStream; - - if (IsEqualGUID(&GUID_PKPixelFormat24bppRGB, &pIE->guidPixFormat) || IsEqualGUID(&GUID_PKPixelFormat24bppBGR, &pIE->guidPixFormat)) - { - pIE->cbPixel = 3; - } - else if (IsEqualGUID(&GUID_PKPixelFormat32bppBGRA, &pIE->guidPixFormat) - || IsEqualGUID(&GUID_PKPixelFormat32bppBGR, &pIE->guidPixFormat) - || IsEqualGUID(&GUID_PKPixelFormat32bppPBGRA, &pIE->guidPixFormat)) - { - pIE->cbPixel = 4; - } - else if (IsEqualGUID(&GUID_PKPixelFormat8bppGray, &pIE->guidPixFormat)) - { - pIE->cbPixel = 1; - } - else if (IsEqualGUID(&GUID_PKPixelFormat16bppGray, &pIE->guidPixFormat)) - { - pIE->cbPixel = 2; - } - else if (IsEqualGUID(&GUID_PKPixelFormat128bppRGBAFloat, &pIE->guidPixFormat)) - { - pIE->cbPixel = 16;//4; - } - - - pIE->offPixel = pIE->offStart; - pIE->fHeaderDone = !IL_FALSE; - - return WMP_errSuccess; -} - -ERR ilPKImageEncode_WritePixels_DevIL(PKImageEncode* pIE, U32 cLine, U8* pbPixel, U32 cbStride) -{ - ERR err = WMP_errSuccess; - - struct WMPStream* pS = pIE->pStream; - size_t cbLineM = 0, cbLineS = 0; - I32 i = 0; - static U8 pPadding[4] = {0}; - - // header - if (!pIE->fHeaderDone) - { - // WriteBMPHeader() also inits this object - Call(WriteDevILHeader(pIE)); - } - - // body - // calculate line size in memory and in stream - cbLineM = pIE->cbPixel * pIE->uWidth; - cbLineS = (cbLineM + 3) / 4 * 4; - - //FailIf(pRect->X < 0 || pID->uWidth <= pRect->X, WMP_errInvalidParameter); - //FailIf(pRect->Y < 0 || pID->uHeight <= pRect->Y, WMP_errInvalidParameter); - //FailIf(pRect->Width < 0 || pID->uWidth < pRect->X + pRect->Width, WMP_errInvalidParameter); - //FailIf(pRect->Height < 0 || pID->uHeight < pRect->Y + pRect->Height, WMP_errInvalidParameter); - FailIf(cbStride < cbLineM, WMP_errInvalidParameter); - - for (i = cLine - 1; 0 <= i; --i) - { - size_t offM = cbStride * i; - size_t offS = cbLineS * (pIE->uHeight - (pIE->idxCurrentLine + i + 1)); - - Call(pS->SetPos(pS, pIE->offPixel + offS)); - Call(pS->Write(pS, pbPixel + offM, cbLineM)); - } - Call(pS->Write(pS, pPadding, (cbLineS - cbLineM))); - pIE->idxCurrentLine += cLine; - -Cleanup: - return err; -} - - -ERR PKImageEncode_Create_DevIL( - PKImageEncode** ppIE) -{ - ERR err = WMP_errSuccess; - PKImageEncode* pIE = NULL; - - Call(PKImageEncode_Create(ppIE)); - - pIE = *ppIE; - pIE->WritePixels = ilPKImageEncode_WritePixels_DevIL; - -Cleanup: - return err; -} - - -ERR iWmpDecAppCreateEncoderFromExt( - PKCodecFactory* pCFactory, - const char* szExt, - PKImageEncode** ppIE) -{ - ERR err = WMP_errSuccess; - const PKIID* pIID = NULL; - - // get encod PKIID - Call(GetImageEncodeIID(szExt, &pIID)); - - // Create encoder - //Call(PKCodecFactory_CreateCodec(pIID, ppIE)); - - Call(PKImageEncode_Create_DevIL(ppIE)); - -Cleanup: - return err; -} - - -ERR iCloseWS_File(struct WMPStream** ppWS) -{ - ERR err = WMP_errSuccess; - /*struct WMPStream* pWS = *ppWS; - - fclose(pWS->state.file.pFile); - Call(WMPFree((void**)ppWS)); - -Cleanup:*/ - return err; -} - -Bool iEOSWS_File(struct WMPStream* pWS) -{ - //return feof(pWS->state.file.pFile); - return ieof(); -} - -ERR iReadWS_File(struct WMPStream* pWS, void* pv, size_t cb) -{ - // For some reason, the WDP images load just fine, but it tries to read too much, - // so IL_FILE_READ_ERROR is set. So we get rid of the error. - if (iread(pv, 1, (ILuint)cb) != cb) - ilGetError(); - return WMP_errSuccess; -} - -ERR iWriteWS_File(struct WMPStream* pWS, const void* pv, size_t cb) -{ - ERR err = WMP_errSuccess; - - if (0 != cb) { - FailIf(1 != iwrite(pv, (ILuint)cb, 1), WMP_errFileIO); - } - -Cleanup: - return err; -} - -ERR iSetPosWS_File(struct WMPStream* pWS, size_t offPos) -{ - ERR err = WMP_errSuccess; - - //FailIf(0 != fseek(pWS->state.file.pFile, (long)offPos, SEEK_SET), WMP_errFileIO); - FailIf(0 != iseek((ILuint)offPos, IL_SEEK_SET), WMP_errFileIO); - -Cleanup: - return err; -} - -ERR iGetPosWS_File(struct WMPStream* pWS, size_t* poffPos) -{ - ERR err = WMP_errSuccess; - long lOff = 0; - - //FailIf(-1 == (lOff = ftell(pWS->state.file.pFile)), WMP_errFileIO); - lOff = itell(); - *poffPos = (size_t)lOff; - -Cleanup: - return err; -} - -ERR ilCreateWS_File(struct WMPStream** ppWS, const char* szFilename, const char* szMode) -{ - ERR err = WMP_errSuccess; - struct WMPStream* pWS = NULL; - - *ppWS = icalloc(1, sizeof(**ppWS)); - if (*ppWS == NULL) - return WMP_errOutOfMemory; - pWS = *ppWS; - - pWS->Close = iCloseWS_File; - pWS->EOS = iEOSWS_File; - - pWS->Read = iReadWS_File; - pWS->Write = iWriteWS_File; - //pWS->GetLine = GetLineWS_File; - - pWS->SetPos = iSetPosWS_File; - pWS->GetPos = iGetPosWS_File; - - //pWS->state.file.pFile = fopen(szFilename, szMode); - pWS->state.file.pFile = NULL; - //FailIf(NULL == pWS->state.file.pFile, WMP_errFileIO); - -Cleanup: - return err; -} - - -ERR ilPKCodecFactory_CreateDecoderFromFile(PKImageDecode** ppDecoder) -{ - ERR err = WMP_errSuccess; - - char *pExt = ".wdp"; // We are loading a WDP file, so we have to tell the library that with this extension. - PKIID* pIID = NULL; - - struct WMPStream* pStream = NULL; - PKImageDecode* pDecoder = NULL; - - // get decode PKIID - Call(GetImageDecodeIID(pExt, &pIID)); - - // create stream - Call(ilCreateWS_File(&pStream, NULL, "rb")); - - // Create decoder - Call(PKCodecFactory_CreateCodec(pIID, ppDecoder)); - pDecoder = *ppDecoder; - - // attach stream to decoder - Call(pDecoder->Initialize(pDecoder, pStream)); - pDecoder->fStreamOwner = !0; - -Cleanup: - return err; -} - - -ERR ilPKCreateFactory(PKFactory** ppFactory, U32 uVersion) -{ - ERR err = WMP_errSuccess; - PKFactory* pFactory = NULL; - - Call(PKAlloc(ppFactory, sizeof(**ppFactory))); - pFactory = *ppFactory; - - pFactory->CreateStream = PKCreateFactory_CreateStream; - - pFactory->CreateStreamFromFilename = ilCreateWS_File; - pFactory->CreateStreamFromMemory = CreateWS_Memory; - - pFactory->Release = PKCreateFactory_Release; - -Cleanup: - return err; -} - -ILboolean iLoadWdpInternal(/*ILconst_string FileName*/) -{ - ERR err = WMP_errSuccess; - PKFactory* pFactory = NULL; - PKCodecFactory* pCodecFactory = NULL; - PKImageDecode* pDecoder = NULL; - PKPixelInfo PI; - PKPixelFormatGUID guidPixFormat; - PKFormatConverter* pConverter = NULL; - U32 cFrame = 0, i = 0; - PKRect Rect; - struct WMPStream* pEncodeStream = NULL; - PKImageEncode* pEncoder = NULL; - - //Call(PKCreateFactory(&pFactory, PK_SDK_VERSION)); - //Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); - //Call(pCodecFactory->CreateDecoderFromFile(FileName, &pDecoder)); - Call(ilPKCreateFactory(&pFactory, PK_SDK_VERSION)); - Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); - Call(ilPKCodecFactory_CreateDecoderFromFile(&pDecoder)); - - //guidPixFormat = GUID_PKPixelFormat24bppRGB; - guidPixFormat = GUID_PKPixelFormat32bppBGRA; - //guidPixFormat = GUID_PKPixelFormat8bppGray; - //guidPixFormat = GUID_PKPixelFormat16bppGray; - - // Color transcoding - if (IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat8bppGray) || IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat16bppGray)){ // ** => Y transcoding - pDecoder->guidPixFormat = guidPixFormat; - pDecoder->WMP.wmiI.cfColorFormat = Y_ONLY; - } - else if(IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat24bppRGB) && pDecoder->WMP.wmiI.cfColorFormat == CMYK){ // CMYK = > RGB - pDecoder->WMP.wmiI.cfColorFormat = CF_RGB; - pDecoder->guidPixFormat = guidPixFormat; - pDecoder->WMP.wmiI.bRGB = 1; //RGB - } - - PI.pGUIDPixFmt = &guidPixFormat; - PixelFormatLookup(&PI, LOOKUP_FORWARD); - - pDecoder->WMP.wmiSCP.bfBitstreamFormat = 0; - pDecoder->WMP.wmiSCP.uAlphaMode = 0; - pDecoder->WMP.wmiSCP.sbSubband = SB_ALL; - pDecoder->WMP.bIgnoreOverlap = FALSE; - - pDecoder->WMP.wmiI.cfColorFormat = PI.cfColorFormat; - - pDecoder->WMP.wmiI.bdBitDepth = PI.bdBitDepth; - pDecoder->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; - - //==== Validate thumbnail decode parameters ===== - pDecoder->WMP.wmiI.cThumbnailWidth = pDecoder->WMP.wmiI.cWidth; - pDecoder->WMP.wmiI.cThumbnailHeight = pDecoder->WMP.wmiI.cHeight; - pDecoder->WMP.wmiI.bSkipFlexbits = FALSE; - - pCodecFactory->CreateFormatConverter(&pConverter); - pConverter->Initialize(pConverter, pDecoder, NULL, guidPixFormat); - - // Right now, we are just assuming one frame. - // @TODO: Deal with multiple frames. - //pDecoder->GetFrameCount(pDecoder, &cFrame); - //pDecoder->SelectFrame(pDecoder, 1); - - if (!ilTexImage(pDecoder->uWidth, pDecoder->uHeight, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) - goto Cleanup; - //ilTexImage(pDecoder->uWidth, pDecoder->uHeight, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, Data); - - pFactory->CreateStreamFromMemory(&pEncodeStream, iCurImage->Data, iCurImage->SizeOfData); - iWmpDecAppCreateEncoderFromExt(pCodecFactory, ".wdp", &pEncoder); - pEncoder->Initialize(pEncoder, pEncodeStream, ".wdp", 0); - - pEncoder->pStream->GetPos(pEncoder->pStream, &pEncoder->offStart); - - // Set the region that we want to be the whole image. - Rect.X = 0; Rect.Y = 0; Rect.Height = pDecoder->uHeight; Rect.Width = pDecoder->uWidth; - pEncoder->SetPixelFormat(pEncoder, guidPixFormat); - pEncoder->SetSize(pEncoder, Rect.Width, Rect.Height); - pEncoder->WriteSource = PKImageEncode_Transcode; - pEncoder->WriteSource(pEncoder, pConverter, &Rect); - - -Cleanup: - // Release everything all at the end. - PKImageDecode_Release(&pDecoder); - if (pEncoder) - PKImageEncode_Release(&pEncoder); - PKCreateCodecFactory_Release(&pCodecFactory); - PKCreateFactory_Release(&pFactory); - PKFormatConverter_Release(&pConverter); - - if (err != WMP_errSuccess) - return IL_FALSE; - return IL_TRUE; -} - -#endif//IL_NO_WDP diff --git a/DevIL/src-IL/src/il_wdp.cpp b/DevIL/src-IL/src/il_wdp.cpp new file mode 100644 index 00000000..fa78211c --- /dev/null +++ b/DevIL/src-IL/src/il_wdp.cpp @@ -0,0 +1,429 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Last modified: 02/09/2009 +// +// Filename: src-IL/src/il_wdp.c +// +// Description: Reads a Microsoft HD Photo (.wdp or .hdp) +// Based very much on the Microsoft HD Photo Device Porting Kit 1.0 +// available at +// http://www.microsoft.com/downloads/details.aspx?FamilyID=285eeffd-d86c-48c3-ab93-3abd5ee7f1ce&displaylang=en. +// +// Note: The license that the Device Porting Kit is under is not very clear. +// Commentary on the license can be found at http://en.wikipedia.org/wiki/HD_Photo. +// Lots of this code is taken from the examples in the DPK and from code +// within the DPK itself. For this reason, this file is not under the LGPL +// license, unlike the rest of DevIL. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_WDP +#include +#include "il_wdp.h" + +#if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS) + #if defined(_MSC_VER) || defined(__BORLANDC__) + #ifndef _DEBUG + #pragma comment(lib, "wmplib.lib") + #else + #pragma comment(lib, "wmplib-d.lib") + #endif + #endif +#endif + + +//! Reads a WDP file +ILboolean ilLoadWdp(ILconst_string FileName) +{ + ILHANDLE WdpFile; + ILboolean bWdp = IL_FALSE; + + WdpFile = iopenr(FileName); + if (WdpFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bWdp; + } + + bWdp = ilLoadWdpF(WdpFile); + icloser(WdpFile); + + return bWdp; +} + + +//! Reads an already-opened WDP file +ILboolean ilLoadWdpF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadWdpInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains a WDP +ILboolean ilLoadWdpL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iLoadWdpInternal(); +} + +//@TODO: Put in ilPKImageEncode_WritePixels_DevIL? +ERR WriteDevILHeader(PKImageEncode* pIE) +{ + struct WMPStream* pS = pIE->pStream; + + if (IsEqualGUID(&GUID_PKPixelFormat24bppRGB, &pIE->guidPixFormat) || IsEqualGUID(&GUID_PKPixelFormat24bppBGR, &pIE->guidPixFormat)) + { + pIE->cbPixel = 3; + } + else if (IsEqualGUID(&GUID_PKPixelFormat32bppBGRA, &pIE->guidPixFormat) + || IsEqualGUID(&GUID_PKPixelFormat32bppBGR, &pIE->guidPixFormat) + || IsEqualGUID(&GUID_PKPixelFormat32bppPBGRA, &pIE->guidPixFormat)) + { + pIE->cbPixel = 4; + } + else if (IsEqualGUID(&GUID_PKPixelFormat8bppGray, &pIE->guidPixFormat)) + { + pIE->cbPixel = 1; + } + else if (IsEqualGUID(&GUID_PKPixelFormat16bppGray, &pIE->guidPixFormat)) + { + pIE->cbPixel = 2; + } + else if (IsEqualGUID(&GUID_PKPixelFormat128bppRGBAFloat, &pIE->guidPixFormat)) + { + pIE->cbPixel = 16;//4; + } + + + pIE->offPixel = pIE->offStart; + pIE->fHeaderDone = !IL_FALSE; + + return WMP_errSuccess; +} + +ERR ilPKImageEncode_WritePixels_DevIL(PKImageEncode* pIE, U32 cLine, U8* pbPixel, U32 cbStride) +{ + ERR err = WMP_errSuccess; + + struct WMPStream* pS = pIE->pStream; + size_t cbLineM = 0, cbLineS = 0; + I32 i = 0; + static U8 pPadding[4] = {0}; + + // header + if (!pIE->fHeaderDone) + { + // WriteBMPHeader() also inits this object + Call(WriteDevILHeader(pIE)); + } + + // body + // calculate line size in memory and in stream + cbLineM = pIE->cbPixel * pIE->uWidth; + cbLineS = (cbLineM + 3) / 4 * 4; + + //FailIf(pRect->X < 0 || pID->uWidth <= pRect->X, WMP_errInvalidParameter); + //FailIf(pRect->Y < 0 || pID->uHeight <= pRect->Y, WMP_errInvalidParameter); + //FailIf(pRect->Width < 0 || pID->uWidth < pRect->X + pRect->Width, WMP_errInvalidParameter); + //FailIf(pRect->Height < 0 || pID->uHeight < pRect->Y + pRect->Height, WMP_errInvalidParameter); + FailIf(cbStride < cbLineM, WMP_errInvalidParameter); + + for (i = cLine - 1; 0 <= i; --i) + { + size_t offM = cbStride * i; + size_t offS = cbLineS * (pIE->uHeight - (pIE->idxCurrentLine + i + 1)); + + Call(pS->SetPos(pS, pIE->offPixel + offS)); + Call(pS->Write(pS, pbPixel + offM, cbLineM)); + } + Call(pS->Write(pS, pPadding, (cbLineS - cbLineM))); + pIE->idxCurrentLine += cLine; + +Cleanup: + return err; +} + + +ERR PKImageEncode_Create_DevIL( + PKImageEncode** ppIE) +{ + ERR err = WMP_errSuccess; + PKImageEncode* pIE = NULL; + + Call(PKImageEncode_Create(ppIE)); + + pIE = *ppIE; + pIE->WritePixels = ilPKImageEncode_WritePixels_DevIL; + +Cleanup: + return err; +} + + +ERR iWmpDecAppCreateEncoderFromExt( + PKCodecFactory* pCFactory, + const char* szExt, + PKImageEncode** ppIE) +{ + ERR err = WMP_errSuccess; + const PKIID* pIID = NULL; + + // get encod PKIID + Call(GetImageEncodeIID(szExt, &pIID)); + + // Create encoder + //Call(PKCodecFactory_CreateCodec(pIID, ppIE)); + + Call(PKImageEncode_Create_DevIL(ppIE)); + +Cleanup: + return err; +} + + +ERR iCloseWS_File(struct WMPStream** ppWS) +{ + ERR err = WMP_errSuccess; + /*struct WMPStream* pWS = *ppWS; + + fclose(pWS->state.file.pFile); + Call(WMPFree((void**)ppWS)); + +Cleanup:*/ + return err; +} + +Bool iEOSWS_File(struct WMPStream* pWS) +{ + //return feof(pWS->state.file.pFile); + return ieof(); +} + +ERR iReadWS_File(struct WMPStream* pWS, void* pv, size_t cb) +{ + // For some reason, the WDP images load just fine, but it tries to read too much, + // so IL_FILE_READ_ERROR is set. So we get rid of the error. + if (iread(pv, 1, (ILuint)cb) != cb) + ilGetError(); + return WMP_errSuccess; +} + +ERR iWriteWS_File(struct WMPStream* pWS, const void* pv, size_t cb) +{ + ERR err = WMP_errSuccess; + + if (0 != cb) { + FailIf(1 != iwrite(pv, (ILuint)cb, 1), WMP_errFileIO); + } + +Cleanup: + return err; +} + +ERR iSetPosWS_File(struct WMPStream* pWS, size_t offPos) +{ + ERR err = WMP_errSuccess; + + //FailIf(0 != fseek(pWS->state.file.pFile, (long)offPos, SEEK_SET), WMP_errFileIO); + FailIf(0 != iseek((ILuint)offPos, IL_SEEK_SET), WMP_errFileIO); + +Cleanup: + return err; +} + +ERR iGetPosWS_File(struct WMPStream* pWS, size_t* poffPos) +{ + ERR err = WMP_errSuccess; + long lOff = 0; + + //FailIf(-1 == (lOff = ftell(pWS->state.file.pFile)), WMP_errFileIO); + lOff = itell(); + *poffPos = (size_t)lOff; + +Cleanup: + return err; +} + +ERR ilCreateWS_File(struct WMPStream** ppWS, const char* szFilename, const char* szMode) +{ + ERR err = WMP_errSuccess; + struct WMPStream* pWS = NULL; + + *ppWS = icalloc(1, sizeof(**ppWS)); + if (*ppWS == NULL) + return WMP_errOutOfMemory; + pWS = *ppWS; + + pWS->Close = iCloseWS_File; + pWS->EOS = iEOSWS_File; + + pWS->Read = iReadWS_File; + pWS->Write = iWriteWS_File; + //pWS->GetLine = GetLineWS_File; + + pWS->SetPos = iSetPosWS_File; + pWS->GetPos = iGetPosWS_File; + + //pWS->state.file.pFile = fopen(szFilename, szMode); + pWS->state.file.pFile = NULL; + //FailIf(NULL == pWS->state.file.pFile, WMP_errFileIO); + +Cleanup: + return err; +} + + +ERR ilPKCodecFactory_CreateDecoderFromFile(PKImageDecode** ppDecoder) +{ + ERR err = WMP_errSuccess; + + char *pExt = ".wdp"; // We are loading a WDP file, so we have to tell the library that with this extension. + PKIID* pIID = NULL; + + struct WMPStream* pStream = NULL; + PKImageDecode* pDecoder = NULL; + + // get decode PKIID + Call(GetImageDecodeIID(pExt, &pIID)); + + // create stream + Call(ilCreateWS_File(&pStream, NULL, "rb")); + + // Create decoder + Call(PKCodecFactory_CreateCodec(pIID, ppDecoder)); + pDecoder = *ppDecoder; + + // attach stream to decoder + Call(pDecoder->Initialize(pDecoder, pStream)); + pDecoder->fStreamOwner = !0; + +Cleanup: + return err; +} + + +ERR ilPKCreateFactory(PKFactory** ppFactory, U32 uVersion) +{ + ERR err = WMP_errSuccess; + PKFactory* pFactory = NULL; + + Call(PKAlloc(ppFactory, sizeof(**ppFactory))); + pFactory = *ppFactory; + + pFactory->CreateStream = PKCreateFactory_CreateStream; + + pFactory->CreateStreamFromFilename = ilCreateWS_File; + pFactory->CreateStreamFromMemory = CreateWS_Memory; + + pFactory->Release = PKCreateFactory_Release; + +Cleanup: + return err; +} + +ILboolean iLoadWdpInternal(/*ILconst_string FileName*/) +{ + ERR err = WMP_errSuccess; + PKFactory* pFactory = NULL; + PKCodecFactory* pCodecFactory = NULL; + PKImageDecode* pDecoder = NULL; + PKPixelInfo PI; + PKPixelFormatGUID guidPixFormat; + PKFormatConverter* pConverter = NULL; + U32 cFrame = 0, i = 0; + PKRect Rect; + struct WMPStream* pEncodeStream = NULL; + PKImageEncode* pEncoder = NULL; + + //Call(PKCreateFactory(&pFactory, PK_SDK_VERSION)); + //Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); + //Call(pCodecFactory->CreateDecoderFromFile(FileName, &pDecoder)); + Call(ilPKCreateFactory(&pFactory, PK_SDK_VERSION)); + Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); + Call(ilPKCodecFactory_CreateDecoderFromFile(&pDecoder)); + + //guidPixFormat = GUID_PKPixelFormat24bppRGB; + guidPixFormat = GUID_PKPixelFormat32bppBGRA; + //guidPixFormat = GUID_PKPixelFormat8bppGray; + //guidPixFormat = GUID_PKPixelFormat16bppGray; + + // Color transcoding + if (IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat8bppGray) || IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat16bppGray)){ // ** => Y transcoding + pDecoder->guidPixFormat = guidPixFormat; + pDecoder->WMP.wmiI.cfColorFormat = Y_ONLY; + } + else if(IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat24bppRGB) && pDecoder->WMP.wmiI.cfColorFormat == CMYK){ // CMYK = > RGB + pDecoder->WMP.wmiI.cfColorFormat = CF_RGB; + pDecoder->guidPixFormat = guidPixFormat; + pDecoder->WMP.wmiI.bRGB = 1; //RGB + } + + PI.pGUIDPixFmt = &guidPixFormat; + PixelFormatLookup(&PI, LOOKUP_FORWARD); + + pDecoder->WMP.wmiSCP.bfBitstreamFormat = 0; + pDecoder->WMP.wmiSCP.uAlphaMode = 0; + pDecoder->WMP.wmiSCP.sbSubband = SB_ALL; + pDecoder->WMP.bIgnoreOverlap = FALSE; + + pDecoder->WMP.wmiI.cfColorFormat = PI.cfColorFormat; + + pDecoder->WMP.wmiI.bdBitDepth = PI.bdBitDepth; + pDecoder->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; + + //==== Validate thumbnail decode parameters ===== + pDecoder->WMP.wmiI.cThumbnailWidth = pDecoder->WMP.wmiI.cWidth; + pDecoder->WMP.wmiI.cThumbnailHeight = pDecoder->WMP.wmiI.cHeight; + pDecoder->WMP.wmiI.bSkipFlexbits = FALSE; + + pCodecFactory->CreateFormatConverter(&pConverter); + pConverter->Initialize(pConverter, pDecoder, NULL, guidPixFormat); + + // Right now, we are just assuming one frame. + // @TODO: Deal with multiple frames. + //pDecoder->GetFrameCount(pDecoder, &cFrame); + //pDecoder->SelectFrame(pDecoder, 1); + + if (!ilTexImage(pDecoder->uWidth, pDecoder->uHeight, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) + goto Cleanup; + //ilTexImage(pDecoder->uWidth, pDecoder->uHeight, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, Data); + + pFactory->CreateStreamFromMemory(&pEncodeStream, iCurImage->Data, iCurImage->SizeOfData); + iWmpDecAppCreateEncoderFromExt(pCodecFactory, ".wdp", &pEncoder); + pEncoder->Initialize(pEncoder, pEncodeStream, ".wdp", 0); + + pEncoder->pStream->GetPos(pEncoder->pStream, &pEncoder->offStart); + + // Set the region that we want to be the whole image. + Rect.X = 0; Rect.Y = 0; Rect.Height = pDecoder->uHeight; Rect.Width = pDecoder->uWidth; + pEncoder->SetPixelFormat(pEncoder, guidPixFormat); + pEncoder->SetSize(pEncoder, Rect.Width, Rect.Height); + pEncoder->WriteSource = PKImageEncode_Transcode; + pEncoder->WriteSource(pEncoder, pConverter, &Rect); + + +Cleanup: + // Release everything all at the end. + PKImageDecode_Release(&pDecoder); + if (pEncoder) + PKImageEncode_Release(&pEncoder); + PKCreateCodecFactory_Release(&pCodecFactory); + PKCreateFactory_Release(&pFactory); + PKFormatConverter_Release(&pConverter); + + if (err != WMP_errSuccess) + return IL_FALSE; + return IL_TRUE; +} + +#endif//IL_NO_WDP diff --git a/DevIL/src-IL/src/il_xpm.c b/DevIL/src-IL/src/il_xpm.c deleted file mode 100644 index 9ca847a4..00000000 --- a/DevIL/src-IL/src/il_xpm.c +++ /dev/null @@ -1,655 +0,0 @@ -//----------------------------------------------------------------------------- -// -// ImageLib Sources -// Copyright (C) 2000-2009 by Denton Woods -// Last modified: 01/04/2009 -// -// Filename: src-IL/src/il_xpm.c -// -// Description: Reads from an .xpm file. -// -//----------------------------------------------------------------------------- - - -#include "il_internal.h" -#ifndef IL_NO_XPM -#include - - -//If this is defined, only xpm files with 1 char/pixel -//can be loaded. They load somewhat faster then, though -//(not much). -//#define XPM_DONT_USE_HASHTABLE - -ILboolean iIsValidXpm(void); -ILboolean iLoadXpmInternal(void); -ILint XpmGetsInternal(ILubyte *Buffer, ILint MaxLen); - -//! Checks if the file specified in FileName is a valid XPM file. -ILboolean ilIsValidXpm(ILconst_string FileName) -{ - ILHANDLE XpmFile; - ILboolean bXpm = IL_FALSE; - - if (!iCheckExtension(FileName, IL_TEXT("xpm"))) { - ilSetError(IL_INVALID_EXTENSION); - return bXpm; - } - - XpmFile = iopenr(FileName); - if (XpmFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bXpm; - } - - bXpm = ilIsValidXpmF(XpmFile); - icloser(XpmFile); - - return bXpm; -} - - -//! Checks if the ILHANDLE contains a valid XPM file at the current position. -ILboolean ilIsValidXpmF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iIsValidXpm(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Checks if Lump is a valid XPM lump. -ILboolean ilIsValidXpmL(const void *Lump, ILuint Size) -{ - iSetInputLump(Lump, Size); - return iIsValidXpm(); -} - - -// Internal function to get the header and check it. -ILboolean iIsValidXpm(void) -{ - ILubyte Buffer[10]; - ILuint Pos = itell(); - - XpmGetsInternal(Buffer, 10); - iseek(Pos, IL_SEEK_SET); // Restore position - - if (strncmp("/* XPM */", (char*)Buffer, strlen("/* XPM */"))) - return IL_FALSE; - return IL_TRUE; -} - - -// Reads an .xpm file -ILboolean ilLoadXpm(ILconst_string FileName) -{ - ILHANDLE XpmFile; - ILboolean bXpm = IL_FALSE; - - XpmFile = iopenr(FileName); - if (XpmFile == NULL) { - ilSetError(IL_COULD_NOT_OPEN_FILE); - return bXpm; - } - - iSetInputFile(XpmFile); - bXpm = ilLoadXpmF(XpmFile); - icloser(XpmFile); - - return bXpm; -} - - -//! Reads an already-opened .xpm file -ILboolean ilLoadXpmF(ILHANDLE File) -{ - ILuint FirstPos; - ILboolean bRet; - - iSetInputFile(File); - FirstPos = itell(); - bRet = iLoadXpmInternal(); - iseek(FirstPos, IL_SEEK_SET); - - return bRet; -} - - -//! Reads from a memory "lump" that contains an .xpm -ILboolean ilLoadXpmL(const void *Lump, ILuint Size) - { - iSetInputLump(Lump, Size); - return iLoadXpmInternal(); -} - - -typedef ILubyte XpmPixel[4]; - -#define XPM_MAX_CHAR_PER_PIXEL 2 - - -#ifndef XPM_DONT_USE_HASHTABLE - -//The following hash table code was inspired by the xpm -//loading code of xv, one of the best image viewers of X11 - -//For xpm files with more than one character/pixel, it is -//impractical to use a simple lookup table for the -//character-to-color mapping (because the table requires -//2^(chars/pixel) entries, this is quite big). -//Because of that, a hash table is used for the mapping. -//The hash table has 257 entries, and collisions are -//resolved by chaining. - -//257 is the smallest prime > 256 -#define XPM_HASH_LEN 257 - -typedef struct XPMHASHENTRY -{ - ILubyte ColourName[XPM_MAX_CHAR_PER_PIXEL]; - XpmPixel ColourValue; - struct XPMHASHENTRY *Next; -} XPMHASHENTRY; - - -static ILuint XpmHash(const ILubyte* name, int len) -{ - ILint i, sum; - for (sum = i = 0; i < len; ++i) - sum += name[i]; - return sum % XPM_HASH_LEN; -} - - -XPMHASHENTRY** XpmCreateHashTable() -{ - XPMHASHENTRY** Table = - (XPMHASHENTRY**)ialloc(XPM_HASH_LEN*sizeof(XPMHASHENTRY*)); - if (Table != NULL) - memset(Table, 0, XPM_HASH_LEN*sizeof(XPMHASHENTRY*)); - return Table; -} - - -void XpmDestroyHashTable(XPMHASHENTRY **Table) -{ - ILint i; - XPMHASHENTRY* Entry; - - for (i = 0; i < XPM_HASH_LEN; ++i) { - while (Table[i] != NULL) { - Entry = Table[i]->Next; - ifree(Table[i]); - Table[i] = Entry; - } - } - - ifree(Table); -} - - -void XpmInsertEntry(XPMHASHENTRY **Table, const ILubyte* Name, int Len, XpmPixel Colour) -{ - XPMHASHENTRY* NewEntry; - ILuint Index; - Index = XpmHash(Name, Len); - - NewEntry = (XPMHASHENTRY*)ialloc(sizeof(XPMHASHENTRY)); - if (NewEntry != NULL) { - NewEntry->Next = Table[Index]; - memcpy(NewEntry->ColourName, Name, Len); - memcpy(NewEntry->ColourValue, Colour, sizeof(Colour)); - Table[Index] = NewEntry; - } -} - - -void XpmGetEntry(XPMHASHENTRY **Table, const ILubyte* Name, int Len, XpmPixel Colour) -{ - XPMHASHENTRY* Entry; - ILuint Index; - - Index = XpmHash(Name, Len); - Entry = Table[Index]; - while (Entry != NULL && strncmp((char*)(Entry->ColourName), (char*)Name, Len) != 0) - Entry = Entry->Next; - - if (Entry != NULL) - memcpy(Colour, Entry->ColourValue, sizeof(Colour)); -} - -#endif //XPM_DONT_USE_HASHTABLE - - -ILint XpmGetsInternal(ILubyte *Buffer, ILint MaxLen) -{ - ILint i = 0, Current; - - if (ieof()) - return IL_EOF; - - while ((Current = igetc()) != IL_EOF && i < MaxLen - 1) { - if (Current == IL_EOF) - return 0; - if (Current == '\n') //unix line ending - break; - - if (Current == '\r') { //dos/mac line ending - Current = igetc(); - if (Current == '\n') //dos line ending - break; - - if (Current == IL_EOF) - break; - - Buffer[i++] = (ILubyte)Current; - continue; - } - Buffer[i++] = (ILubyte)Current; - } - - Buffer[i++] = 0; - - return i; -} - - -ILint XpmGets(ILubyte *Buffer, ILint MaxLen) -{ - ILint Size, i, j; - ILboolean NotComment = IL_FALSE, InsideComment = IL_FALSE; - - do { - Size = XpmGetsInternal(Buffer, MaxLen); - if (Size == IL_EOF) - return IL_EOF; - - //skip leading whitespace (sometimes there's whitespace - //before a comment or before the pixel data) - - for(i = 0; i < Size && isspace(Buffer[i]); ++i) ; - Size = Size - i; - for(j = 0; j < Size; ++j) - Buffer[j] = Buffer[j + i]; - - if (Size == 0) - continue; - - if (Buffer[0] == '/' && Buffer[1] == '*') { - for (i = 2; i < Size; i++) { - if (Buffer[i] == '*' && Buffer[i+1] == '/') { - break; - } - } - if (i >= Size) - InsideComment = IL_TRUE; - } - else if (InsideComment) { - for (i = 0; i < Size; i++) { - if (Buffer[i] == '*' && Buffer[i+1] == '/') { - break; - } - } - if (i < Size) - InsideComment = IL_FALSE; - } - else { - NotComment = IL_TRUE; - } - } while (!NotComment); - - return Size; -} - - -ILint XpmGetInt(ILubyte *Buffer, ILint Size, ILint *Position) -{ - char Buff[1024]; - ILint i, j; - ILboolean IsInNum = IL_FALSE; - - for (i = *Position, j = 0; i < Size; i++) { - if (isdigit(Buffer[i])) { - IsInNum = IL_TRUE; - Buff[j++] = Buffer[i]; - } - else { - if (IsInNum) { - Buff[j] = 0; - *Position = i; - return atoi(Buff); - } - } - } - - return -1; -} - - -ILboolean XpmPredefCol(char *Buff, XpmPixel *Colour) -{ - ILint len; - ILint val = 128; - - if (!stricmp(Buff, "none")) { - (*Colour)[0] = 0; - (*Colour)[1] = 0; - (*Colour)[2] = 0; - (*Colour)[3] = 0; - return IL_TRUE; - } - - (*Colour)[3] = 255; - - if (!stricmp(Buff, "black")) { - (*Colour)[0] = 0; - (*Colour)[1] = 0; - (*Colour)[2] = 0; - return IL_TRUE; - } - if (!stricmp(Buff, "white")) { - (*Colour)[0] = 255; - (*Colour)[1] = 255; - (*Colour)[2] = 255; - return IL_TRUE; - } - if (!stricmp(Buff, "red")) { - (*Colour)[0] = 255; - (*Colour)[1] = 0; - (*Colour)[2] = 0; - return IL_TRUE; - } - if (!stricmp(Buff, "green")) { - (*Colour)[0] = 0; - (*Colour)[1] = 255; - (*Colour)[2] = 0; - return IL_TRUE; - } - if (!stricmp(Buff, "blue")) { - (*Colour)[0] = 0; - (*Colour)[1] = 0; - (*Colour)[2] = 255; - return IL_TRUE; - } - if (!stricmp(Buff, "yellow")) { - (*Colour)[0] = 255; - (*Colour)[1] = 255; - (*Colour)[2] = 0; - return IL_TRUE; - } - if (!stricmp(Buff, "cyan")) { - (*Colour)[0] = 0; - (*Colour)[1] = 255; - (*Colour)[2] = 255; - return IL_TRUE; - } - if (!stricmp(Buff, "gray")) { - (*Colour)[0] = 128; - (*Colour)[1] = 128; - (*Colour)[2] = 128; - return IL_TRUE; - } - - //check for grayXXX codes (added 20040218) - len = ilCharStrLen(Buff); - if (len >= 4) { - if (Buff[0] == 'g' || Buff[0] == 'G' - || Buff[1] == 'r' || Buff[1] == 'R' - || Buff[2] == 'a' || Buff[2] == 'A' - || Buff[3] == 'y' || Buff[3] == 'Y') { - if (isdigit(Buff[4])) { // isdigit returns false on '\0' - val = Buff[4] - '0'; - if (isdigit(Buff[5])) { - val = val*10 + Buff[5] - '0'; - if (isdigit(Buff[6])) - val = val*10 + Buff[6] - '0'; - } - val = (255*val)/100; - } - (*Colour)[0] = (ILubyte)val; - (*Colour)[1] = (ILubyte)val; - (*Colour)[2] = (ILubyte)val; - return IL_TRUE; - } - } - - - // Unknown colour string, so use black - // (changed 20040218) - (*Colour)[0] = 0; - (*Colour)[1] = 0; - (*Colour)[2] = 0; - - return IL_FALSE; -} - - -#ifndef XPM_DONT_USE_HASHTABLE -ILboolean XpmGetColour(ILubyte *Buffer, ILint Size, int Len, XPMHASHENTRY **Table) -#else -ILboolean XpmGetColour(ILubyte *Buffer, ILint Size, int Len, XpmPixel* Colours) -#endif -{ - ILint i = 0, j, strLen = 0; - ILubyte ColBuff[3]; - char Buff[1024]; - - XpmPixel Colour; - ILubyte Name[XPM_MAX_CHAR_PER_PIXEL]; - - for ( ; i < Size; i++) { - if (Buffer[i] == '\"') - break; - } - i++; // Skip the quotes. - - if (i >= Size) - return IL_FALSE; - - // Get the characters. - for (j = 0; j < Len; ++j) { - Name[j] = Buffer[i++]; - } - - // Skip to the colour definition. - for ( ; i < Size; i++) { - if (Buffer[i] == 'c') - break; - } - i++; // Skip the 'c'. - - if (i >= Size || Buffer[i] != ' ') { // no 'c' found...assume black -#ifndef XPM_DONT_USE_HASHTABLE - memset(Colour, 0, sizeof(Colour)); - Colour[3] = 255; - XpmInsertEntry(Table, Name, Len, Colour); -#else - memset(Colours[Name[0]], 0, sizeof(Colour)); - Colours[Name[0]][3] = 255; -#endif - return IL_TRUE; - } - - for ( ; i < Size; i++) { - if (Buffer[i] != ' ') - break; - } - - if (i >= Size) - return IL_FALSE; - - if (Buffer[i] == '#') { - // colour string may 4 digits/color or 1 digit/color - // (added 20040218) TODO: is isxdigit() ANSI??? - ++i; - while (i + strLen < Size && isxdigit(Buffer[i + strLen])) - ++strLen; - - for (j = 0; j < 3; j++) { - if (strLen >= 10) { // 4 digits - ColBuff[0] = Buffer[i + j*4]; - ColBuff[1] = Buffer[i + j*4 + 1]; - } - else if (strLen >= 8) { // 3 digits - ColBuff[0] = Buffer[i + j*3]; - ColBuff[1] = Buffer[i + j*3 + 1]; - } - else if (strLen >= 6) { // 2 digits - ColBuff[0] = Buffer[i + j*2]; - ColBuff[1] = Buffer[i + j*2 + 1]; - } - else if(j < strLen) { // 1 digit, strLen >= 1 - ColBuff[0] = Buffer[i + j]; - ColBuff[1] = 0; - } - - ColBuff[2] = 0; // add terminating '\0' char - Colour[j] = (ILubyte)strtol((char*)ColBuff, NULL, 16); - } - Colour[3] = 255; // Full alpha. - } - else { - for (j = 0; i < Size; i++) { - if (!isalnum(Buffer[i])) - break; - Buff[j++] = Buffer[i]; - } - Buff[j] = 0; - - if (i >= Size) - return IL_FALSE; - - if (!XpmPredefCol(Buff, &Colour)) - - return IL_FALSE; - } - - -#ifndef XPM_DONT_USE_HASHTABLE - XpmInsertEntry(Table, Name, Len, Colour); -#else - memcpy(Colours[Name[0]], Colour, sizeof(Colour)); -#endif - return IL_TRUE; -} - - -ILboolean iLoadXpmInternal() -{ -#define BUFFER_SIZE 2000 - ILubyte Buffer[BUFFER_SIZE], *Data; - ILint Size, Pos, Width, Height, NumColours, i, x, y; - - ILint CharsPerPixel; - -#ifndef XPM_DONT_USE_HASHTABLE - XPMHASHENTRY **HashTable; -#else - XpmPixel *Colours; - ILint Offset; -#endif - - Size = XpmGetsInternal(Buffer, BUFFER_SIZE); - if (strncmp("/* XPM */", (char*)Buffer, strlen("/* XPM */"))) { - ilSetError(IL_INVALID_FILE_HEADER); - return IL_FALSE; - } - - Size = XpmGets(Buffer, BUFFER_SIZE); - // @TODO: Actually check the variable name here. - - Size = XpmGets(Buffer, BUFFER_SIZE); - Pos = 0; - Width = XpmGetInt(Buffer, Size, &Pos); - Height = XpmGetInt(Buffer, Size, &Pos); - NumColours = XpmGetInt(Buffer, Size, &Pos); - - CharsPerPixel = XpmGetInt(Buffer, Size, &Pos); - -#ifdef XPM_DONT_USE_HASHTABLE - if (CharsPerPixel != 1) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } -#endif - - if (CharsPerPixel > XPM_MAX_CHAR_PER_PIXEL - || Width*CharsPerPixel > BUFFER_SIZE) { - ilSetError(IL_FORMAT_NOT_SUPPORTED); - return IL_FALSE; - } - -#ifndef XPM_DONT_USE_HASHTABLE - HashTable = XpmCreateHashTable(); - if (HashTable == NULL) - return IL_FALSE; -#else - Colours = ialloc(256 * sizeof(XpmPixel)); - if (Colours == NULL) - return IL_FALSE; -#endif - - for (i = 0; i < NumColours; i++) { - Size = XpmGets(Buffer, BUFFER_SIZE); -#ifndef XPM_DONT_USE_HASHTABLE - if (!XpmGetColour(Buffer, Size, CharsPerPixel, HashTable)) { - XpmDestroyHashTable(HashTable); -#else - if (!XpmGetColour(Buffer, Size, CharsPerPixel, Colours)) { - ifree(Colours); -#endif - return IL_FALSE; - } - } - - if (!ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { -#ifndef XPM_DONT_USE_HASHTABLE - XpmDestroyHashTable(HashTable); -#else - ifree(Colours); -#endif - return IL_FALSE; - } - - Data = iCurImage->Data; - - for (y = 0; y < Height; y++) { - Size = XpmGets(Buffer, BUFFER_SIZE); - for (x = 0; x < Width; x++) { -#ifndef XPM_DONT_USE_HASHTABLE - XpmGetEntry(HashTable, &Buffer[1 + x*CharsPerPixel], CharsPerPixel, &Data[(x << 2)]); -#else - Offset = (x << 2); - Data[Offset + 0] = Colours[Buffer[x + 1]][0]; - Data[Offset + 1] = Colours[Buffer[x + 1]][1]; - Data[Offset + 2] = Colours[Buffer[x + 1]][2]; - Data[Offset + 3] = Colours[Buffer[x + 1]][3]; -#endif - } - - Data += iCurImage->Bps; - } - - //added 20040218 - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - - -#ifndef XPM_DONT_USE_HASHTABLE - XpmDestroyHashTable(HashTable); -#else - ifree(Colours); -#endif - return IL_TRUE; - -#undef BUFFER_SIZE -} - -#endif//IL_NO_XPM - diff --git a/DevIL/src-IL/src/il_xpm.cpp b/DevIL/src-IL/src/il_xpm.cpp new file mode 100644 index 00000000..9ca847a4 --- /dev/null +++ b/DevIL/src-IL/src/il_xpm.cpp @@ -0,0 +1,655 @@ +//----------------------------------------------------------------------------- +// +// ImageLib Sources +// Copyright (C) 2000-2009 by Denton Woods +// Last modified: 01/04/2009 +// +// Filename: src-IL/src/il_xpm.c +// +// Description: Reads from an .xpm file. +// +//----------------------------------------------------------------------------- + + +#include "il_internal.h" +#ifndef IL_NO_XPM +#include + + +//If this is defined, only xpm files with 1 char/pixel +//can be loaded. They load somewhat faster then, though +//(not much). +//#define XPM_DONT_USE_HASHTABLE + +ILboolean iIsValidXpm(void); +ILboolean iLoadXpmInternal(void); +ILint XpmGetsInternal(ILubyte *Buffer, ILint MaxLen); + +//! Checks if the file specified in FileName is a valid XPM file. +ILboolean ilIsValidXpm(ILconst_string FileName) +{ + ILHANDLE XpmFile; + ILboolean bXpm = IL_FALSE; + + if (!iCheckExtension(FileName, IL_TEXT("xpm"))) { + ilSetError(IL_INVALID_EXTENSION); + return bXpm; + } + + XpmFile = iopenr(FileName); + if (XpmFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bXpm; + } + + bXpm = ilIsValidXpmF(XpmFile); + icloser(XpmFile); + + return bXpm; +} + + +//! Checks if the ILHANDLE contains a valid XPM file at the current position. +ILboolean ilIsValidXpmF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iIsValidXpm(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Checks if Lump is a valid XPM lump. +ILboolean ilIsValidXpmL(const void *Lump, ILuint Size) +{ + iSetInputLump(Lump, Size); + return iIsValidXpm(); +} + + +// Internal function to get the header and check it. +ILboolean iIsValidXpm(void) +{ + ILubyte Buffer[10]; + ILuint Pos = itell(); + + XpmGetsInternal(Buffer, 10); + iseek(Pos, IL_SEEK_SET); // Restore position + + if (strncmp("/* XPM */", (char*)Buffer, strlen("/* XPM */"))) + return IL_FALSE; + return IL_TRUE; +} + + +// Reads an .xpm file +ILboolean ilLoadXpm(ILconst_string FileName) +{ + ILHANDLE XpmFile; + ILboolean bXpm = IL_FALSE; + + XpmFile = iopenr(FileName); + if (XpmFile == NULL) { + ilSetError(IL_COULD_NOT_OPEN_FILE); + return bXpm; + } + + iSetInputFile(XpmFile); + bXpm = ilLoadXpmF(XpmFile); + icloser(XpmFile); + + return bXpm; +} + + +//! Reads an already-opened .xpm file +ILboolean ilLoadXpmF(ILHANDLE File) +{ + ILuint FirstPos; + ILboolean bRet; + + iSetInputFile(File); + FirstPos = itell(); + bRet = iLoadXpmInternal(); + iseek(FirstPos, IL_SEEK_SET); + + return bRet; +} + + +//! Reads from a memory "lump" that contains an .xpm +ILboolean ilLoadXpmL(const void *Lump, ILuint Size) + { + iSetInputLump(Lump, Size); + return iLoadXpmInternal(); +} + + +typedef ILubyte XpmPixel[4]; + +#define XPM_MAX_CHAR_PER_PIXEL 2 + + +#ifndef XPM_DONT_USE_HASHTABLE + +//The following hash table code was inspired by the xpm +//loading code of xv, one of the best image viewers of X11 + +//For xpm files with more than one character/pixel, it is +//impractical to use a simple lookup table for the +//character-to-color mapping (because the table requires +//2^(chars/pixel) entries, this is quite big). +//Because of that, a hash table is used for the mapping. +//The hash table has 257 entries, and collisions are +//resolved by chaining. + +//257 is the smallest prime > 256 +#define XPM_HASH_LEN 257 + +typedef struct XPMHASHENTRY +{ + ILubyte ColourName[XPM_MAX_CHAR_PER_PIXEL]; + XpmPixel ColourValue; + struct XPMHASHENTRY *Next; +} XPMHASHENTRY; + + +static ILuint XpmHash(const ILubyte* name, int len) +{ + ILint i, sum; + for (sum = i = 0; i < len; ++i) + sum += name[i]; + return sum % XPM_HASH_LEN; +} + + +XPMHASHENTRY** XpmCreateHashTable() +{ + XPMHASHENTRY** Table = + (XPMHASHENTRY**)ialloc(XPM_HASH_LEN*sizeof(XPMHASHENTRY*)); + if (Table != NULL) + memset(Table, 0, XPM_HASH_LEN*sizeof(XPMHASHENTRY*)); + return Table; +} + + +void XpmDestroyHashTable(XPMHASHENTRY **Table) +{ + ILint i; + XPMHASHENTRY* Entry; + + for (i = 0; i < XPM_HASH_LEN; ++i) { + while (Table[i] != NULL) { + Entry = Table[i]->Next; + ifree(Table[i]); + Table[i] = Entry; + } + } + + ifree(Table); +} + + +void XpmInsertEntry(XPMHASHENTRY **Table, const ILubyte* Name, int Len, XpmPixel Colour) +{ + XPMHASHENTRY* NewEntry; + ILuint Index; + Index = XpmHash(Name, Len); + + NewEntry = (XPMHASHENTRY*)ialloc(sizeof(XPMHASHENTRY)); + if (NewEntry != NULL) { + NewEntry->Next = Table[Index]; + memcpy(NewEntry->ColourName, Name, Len); + memcpy(NewEntry->ColourValue, Colour, sizeof(Colour)); + Table[Index] = NewEntry; + } +} + + +void XpmGetEntry(XPMHASHENTRY **Table, const ILubyte* Name, int Len, XpmPixel Colour) +{ + XPMHASHENTRY* Entry; + ILuint Index; + + Index = XpmHash(Name, Len); + Entry = Table[Index]; + while (Entry != NULL && strncmp((char*)(Entry->ColourName), (char*)Name, Len) != 0) + Entry = Entry->Next; + + if (Entry != NULL) + memcpy(Colour, Entry->ColourValue, sizeof(Colour)); +} + +#endif //XPM_DONT_USE_HASHTABLE + + +ILint XpmGetsInternal(ILubyte *Buffer, ILint MaxLen) +{ + ILint i = 0, Current; + + if (ieof()) + return IL_EOF; + + while ((Current = igetc()) != IL_EOF && i < MaxLen - 1) { + if (Current == IL_EOF) + return 0; + if (Current == '\n') //unix line ending + break; + + if (Current == '\r') { //dos/mac line ending + Current = igetc(); + if (Current == '\n') //dos line ending + break; + + if (Current == IL_EOF) + break; + + Buffer[i++] = (ILubyte)Current; + continue; + } + Buffer[i++] = (ILubyte)Current; + } + + Buffer[i++] = 0; + + return i; +} + + +ILint XpmGets(ILubyte *Buffer, ILint MaxLen) +{ + ILint Size, i, j; + ILboolean NotComment = IL_FALSE, InsideComment = IL_FALSE; + + do { + Size = XpmGetsInternal(Buffer, MaxLen); + if (Size == IL_EOF) + return IL_EOF; + + //skip leading whitespace (sometimes there's whitespace + //before a comment or before the pixel data) + + for(i = 0; i < Size && isspace(Buffer[i]); ++i) ; + Size = Size - i; + for(j = 0; j < Size; ++j) + Buffer[j] = Buffer[j + i]; + + if (Size == 0) + continue; + + if (Buffer[0] == '/' && Buffer[1] == '*') { + for (i = 2; i < Size; i++) { + if (Buffer[i] == '*' && Buffer[i+1] == '/') { + break; + } + } + if (i >= Size) + InsideComment = IL_TRUE; + } + else if (InsideComment) { + for (i = 0; i < Size; i++) { + if (Buffer[i] == '*' && Buffer[i+1] == '/') { + break; + } + } + if (i < Size) + InsideComment = IL_FALSE; + } + else { + NotComment = IL_TRUE; + } + } while (!NotComment); + + return Size; +} + + +ILint XpmGetInt(ILubyte *Buffer, ILint Size, ILint *Position) +{ + char Buff[1024]; + ILint i, j; + ILboolean IsInNum = IL_FALSE; + + for (i = *Position, j = 0; i < Size; i++) { + if (isdigit(Buffer[i])) { + IsInNum = IL_TRUE; + Buff[j++] = Buffer[i]; + } + else { + if (IsInNum) { + Buff[j] = 0; + *Position = i; + return atoi(Buff); + } + } + } + + return -1; +} + + +ILboolean XpmPredefCol(char *Buff, XpmPixel *Colour) +{ + ILint len; + ILint val = 128; + + if (!stricmp(Buff, "none")) { + (*Colour)[0] = 0; + (*Colour)[1] = 0; + (*Colour)[2] = 0; + (*Colour)[3] = 0; + return IL_TRUE; + } + + (*Colour)[3] = 255; + + if (!stricmp(Buff, "black")) { + (*Colour)[0] = 0; + (*Colour)[1] = 0; + (*Colour)[2] = 0; + return IL_TRUE; + } + if (!stricmp(Buff, "white")) { + (*Colour)[0] = 255; + (*Colour)[1] = 255; + (*Colour)[2] = 255; + return IL_TRUE; + } + if (!stricmp(Buff, "red")) { + (*Colour)[0] = 255; + (*Colour)[1] = 0; + (*Colour)[2] = 0; + return IL_TRUE; + } + if (!stricmp(Buff, "green")) { + (*Colour)[0] = 0; + (*Colour)[1] = 255; + (*Colour)[2] = 0; + return IL_TRUE; + } + if (!stricmp(Buff, "blue")) { + (*Colour)[0] = 0; + (*Colour)[1] = 0; + (*Colour)[2] = 255; + return IL_TRUE; + } + if (!stricmp(Buff, "yellow")) { + (*Colour)[0] = 255; + (*Colour)[1] = 255; + (*Colour)[2] = 0; + return IL_TRUE; + } + if (!stricmp(Buff, "cyan")) { + (*Colour)[0] = 0; + (*Colour)[1] = 255; + (*Colour)[2] = 255; + return IL_TRUE; + } + if (!stricmp(Buff, "gray")) { + (*Colour)[0] = 128; + (*Colour)[1] = 128; + (*Colour)[2] = 128; + return IL_TRUE; + } + + //check for grayXXX codes (added 20040218) + len = ilCharStrLen(Buff); + if (len >= 4) { + if (Buff[0] == 'g' || Buff[0] == 'G' + || Buff[1] == 'r' || Buff[1] == 'R' + || Buff[2] == 'a' || Buff[2] == 'A' + || Buff[3] == 'y' || Buff[3] == 'Y') { + if (isdigit(Buff[4])) { // isdigit returns false on '\0' + val = Buff[4] - '0'; + if (isdigit(Buff[5])) { + val = val*10 + Buff[5] - '0'; + if (isdigit(Buff[6])) + val = val*10 + Buff[6] - '0'; + } + val = (255*val)/100; + } + (*Colour)[0] = (ILubyte)val; + (*Colour)[1] = (ILubyte)val; + (*Colour)[2] = (ILubyte)val; + return IL_TRUE; + } + } + + + // Unknown colour string, so use black + // (changed 20040218) + (*Colour)[0] = 0; + (*Colour)[1] = 0; + (*Colour)[2] = 0; + + return IL_FALSE; +} + + +#ifndef XPM_DONT_USE_HASHTABLE +ILboolean XpmGetColour(ILubyte *Buffer, ILint Size, int Len, XPMHASHENTRY **Table) +#else +ILboolean XpmGetColour(ILubyte *Buffer, ILint Size, int Len, XpmPixel* Colours) +#endif +{ + ILint i = 0, j, strLen = 0; + ILubyte ColBuff[3]; + char Buff[1024]; + + XpmPixel Colour; + ILubyte Name[XPM_MAX_CHAR_PER_PIXEL]; + + for ( ; i < Size; i++) { + if (Buffer[i] == '\"') + break; + } + i++; // Skip the quotes. + + if (i >= Size) + return IL_FALSE; + + // Get the characters. + for (j = 0; j < Len; ++j) { + Name[j] = Buffer[i++]; + } + + // Skip to the colour definition. + for ( ; i < Size; i++) { + if (Buffer[i] == 'c') + break; + } + i++; // Skip the 'c'. + + if (i >= Size || Buffer[i] != ' ') { // no 'c' found...assume black +#ifndef XPM_DONT_USE_HASHTABLE + memset(Colour, 0, sizeof(Colour)); + Colour[3] = 255; + XpmInsertEntry(Table, Name, Len, Colour); +#else + memset(Colours[Name[0]], 0, sizeof(Colour)); + Colours[Name[0]][3] = 255; +#endif + return IL_TRUE; + } + + for ( ; i < Size; i++) { + if (Buffer[i] != ' ') + break; + } + + if (i >= Size) + return IL_FALSE; + + if (Buffer[i] == '#') { + // colour string may 4 digits/color or 1 digit/color + // (added 20040218) TODO: is isxdigit() ANSI??? + ++i; + while (i + strLen < Size && isxdigit(Buffer[i + strLen])) + ++strLen; + + for (j = 0; j < 3; j++) { + if (strLen >= 10) { // 4 digits + ColBuff[0] = Buffer[i + j*4]; + ColBuff[1] = Buffer[i + j*4 + 1]; + } + else if (strLen >= 8) { // 3 digits + ColBuff[0] = Buffer[i + j*3]; + ColBuff[1] = Buffer[i + j*3 + 1]; + } + else if (strLen >= 6) { // 2 digits + ColBuff[0] = Buffer[i + j*2]; + ColBuff[1] = Buffer[i + j*2 + 1]; + } + else if(j < strLen) { // 1 digit, strLen >= 1 + ColBuff[0] = Buffer[i + j]; + ColBuff[1] = 0; + } + + ColBuff[2] = 0; // add terminating '\0' char + Colour[j] = (ILubyte)strtol((char*)ColBuff, NULL, 16); + } + Colour[3] = 255; // Full alpha. + } + else { + for (j = 0; i < Size; i++) { + if (!isalnum(Buffer[i])) + break; + Buff[j++] = Buffer[i]; + } + Buff[j] = 0; + + if (i >= Size) + return IL_FALSE; + + if (!XpmPredefCol(Buff, &Colour)) + + return IL_FALSE; + } + + +#ifndef XPM_DONT_USE_HASHTABLE + XpmInsertEntry(Table, Name, Len, Colour); +#else + memcpy(Colours[Name[0]], Colour, sizeof(Colour)); +#endif + return IL_TRUE; +} + + +ILboolean iLoadXpmInternal() +{ +#define BUFFER_SIZE 2000 + ILubyte Buffer[BUFFER_SIZE], *Data; + ILint Size, Pos, Width, Height, NumColours, i, x, y; + + ILint CharsPerPixel; + +#ifndef XPM_DONT_USE_HASHTABLE + XPMHASHENTRY **HashTable; +#else + XpmPixel *Colours; + ILint Offset; +#endif + + Size = XpmGetsInternal(Buffer, BUFFER_SIZE); + if (strncmp("/* XPM */", (char*)Buffer, strlen("/* XPM */"))) { + ilSetError(IL_INVALID_FILE_HEADER); + return IL_FALSE; + } + + Size = XpmGets(Buffer, BUFFER_SIZE); + // @TODO: Actually check the variable name here. + + Size = XpmGets(Buffer, BUFFER_SIZE); + Pos = 0; + Width = XpmGetInt(Buffer, Size, &Pos); + Height = XpmGetInt(Buffer, Size, &Pos); + NumColours = XpmGetInt(Buffer, Size, &Pos); + + CharsPerPixel = XpmGetInt(Buffer, Size, &Pos); + +#ifdef XPM_DONT_USE_HASHTABLE + if (CharsPerPixel != 1) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } +#endif + + if (CharsPerPixel > XPM_MAX_CHAR_PER_PIXEL + || Width*CharsPerPixel > BUFFER_SIZE) { + ilSetError(IL_FORMAT_NOT_SUPPORTED); + return IL_FALSE; + } + +#ifndef XPM_DONT_USE_HASHTABLE + HashTable = XpmCreateHashTable(); + if (HashTable == NULL) + return IL_FALSE; +#else + Colours = ialloc(256 * sizeof(XpmPixel)); + if (Colours == NULL) + return IL_FALSE; +#endif + + for (i = 0; i < NumColours; i++) { + Size = XpmGets(Buffer, BUFFER_SIZE); +#ifndef XPM_DONT_USE_HASHTABLE + if (!XpmGetColour(Buffer, Size, CharsPerPixel, HashTable)) { + XpmDestroyHashTable(HashTable); +#else + if (!XpmGetColour(Buffer, Size, CharsPerPixel, Colours)) { + ifree(Colours); +#endif + return IL_FALSE; + } + } + + if (!ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { +#ifndef XPM_DONT_USE_HASHTABLE + XpmDestroyHashTable(HashTable); +#else + ifree(Colours); +#endif + return IL_FALSE; + } + + Data = iCurImage->Data; + + for (y = 0; y < Height; y++) { + Size = XpmGets(Buffer, BUFFER_SIZE); + for (x = 0; x < Width; x++) { +#ifndef XPM_DONT_USE_HASHTABLE + XpmGetEntry(HashTable, &Buffer[1 + x*CharsPerPixel], CharsPerPixel, &Data[(x << 2)]); +#else + Offset = (x << 2); + Data[Offset + 0] = Colours[Buffer[x + 1]][0]; + Data[Offset + 1] = Colours[Buffer[x + 1]][1]; + Data[Offset + 2] = Colours[Buffer[x + 1]][2]; + Data[Offset + 3] = Colours[Buffer[x + 1]][3]; +#endif + } + + Data += iCurImage->Bps; + } + + //added 20040218 + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; + + +#ifndef XPM_DONT_USE_HASHTABLE + XpmDestroyHashTable(HashTable); +#else + ifree(Colours); +#endif + return IL_TRUE; + +#undef BUFFER_SIZE +} + +#endif//IL_NO_XPM + -- cgit v1.2.1