58#include <system_threads.h>
62#include "vrml_parser/Structs.h"
63#include "main/ProdCon.h"
64#include "OpenGL_Utils.h"
66#include "LoadTextures.h"
67#include "../scenegraph/Component_CubeMapTexturing.h"
68#include "../scenegraph/Polyrep.h"
75#include <libFreeWRL.h>
82#include "ImageLoader.h"
84#if !(defined(_ANDROID) || defined(ANDROIDNDK))
101 s_list_t* texture_request_list;
104 s_list_t *texture_list;
108void *LoadTextures_constructor(){
113void LoadTextures_init(
struct tLoadTextures *t)
120 t->prv = LoadTextures_constructor();
122 ppLoadTextures p = (ppLoadTextures)t->prv;
123 p->texture_request_list = NULL;
124 p->loader_waiting =
false;
126 p->texture_list = NULL;
128 p->TextureParsing = FALSE;
135 IMAGETYPE_UNKNOWN = 0,
144static int sniffImageFileHeader(
char *filename) {
162 FILE* fp = fopen(filename,
"rb");
163 rvt=fread(header,20,1,fp);
166 iret = IMAGETYPE_UNKNOWN;
167 if(!strncmp(&header[1],
"PNG",3))
168 iret = IMAGETYPE_PNG;
170 if(!strncmp(header,
"ÿØÿ",3))
171 iret = IMAGETYPE_JPEG;
173 if(!strncmp(header,
"GIF",3))
174 iret = IMAGETYPE_GIF;
176 if(!strncmp(header,
"DDS ",4))
177 iret = IMAGETYPE_DDS;
179 if(!strncmp(header,
"web3dit",7))
180 iret = IMAGETYPE_WEB3DIT;
182 if(!strncmp(header,
"NRRD",4))
183 iret = IMAGETYPE_NRRD;
185 if(!strncmp(header,
"vol",3))
186 iret = IMAGETYPE_VOL;
190static int sniffImageHeader(
char* header) {
205 iret = IMAGETYPE_UNKNOWN;
206 if (!strncmp(&header[1],
"PNG", 3))
207 iret = IMAGETYPE_PNG;
209 if (!strncmp(header,
"ÿØÿ", 3))
210 iret = IMAGETYPE_JPEG;
212 if (!strncmp(header,
"GIF", 3))
213 iret = IMAGETYPE_GIF;
215 if (!strncmp(header,
"DDS ", 4))
216 iret = IMAGETYPE_DDS;
218 if (!strncmp(header,
"web3dit", 7))
219 iret = IMAGETYPE_WEB3DIT;
221 if (!strncmp(header,
"NRRD", 4))
222 iret = IMAGETYPE_NRRD;
224 if (!strncmp(header,
"vol", 3))
225 iret = IMAGETYPE_VOL;
229static int sniffImageChannels_bruteForce(
unsigned char *imageblob,
int width,
int height){
233 int i,ii4,j,jj4, hasAlpha, hasColor, channels;
237 for(i=0;i<height;i++){
243 for(j=0;j<width;j++){
245 hasAlpha = hasAlpha || imageblob[jj4+3] != 255;
246 hasColor = hasColor || imageblob[jj4] != imageblob[jj4+1] || imageblob[jj4+1] != imageblob[jj4+2];
251 for(j=3;j<width*4;j+=4){
252 hasAlpha = hasAlpha || imageblob[ii4 + j] != 255;
255 if(hasAlpha && hasColor)
break;
257 channels = hasColor ? 3 : 1;
258 channels = hasAlpha ? channels + 1 : channels;
269static void texture_dump_entry(textureTableIndexStruct_s *entry)
271 DEBUG_MSG(
"%s\t%p\t%s\n", texst(entry->status), entry, entry->filename);
275void texture_dump_list()
278 DEBUG_MSG(
"TEXTURE: wait queue\n");
279 ppLoadTextures p = (ppLoadTextures)gglobal()->LoadTextures.prv;
280 ml_foreach(p->texture_list, texture_dump_entry(ml_elem(__l)));
281 DEBUG_MSG(
"TEXTURE: end wait queue\n");
285static size_t st(
int k){
288static void texture_swap_B_R(textureTableIndexStruct_s* this_tex)
294 unsigned char R,B,*data;
298 data = this_tex->texdata;
306 ipix = (st(i)*st(y) + st(j))*st(x) + st(k);
307 ibyte = ipix * st(4);
309 B = data[ibyte+st(2)];
311 data[ibyte+st(2)] = R;
321static void texture_load_from_pixelTexture (textureTableIndexStruct_s* this_tex,
struct X3D_PixelTexture *node)
326 unsigned char *texture;
332 iptr = node->image.arr.p;
336 DEBUG_TEX (
"start of texture_load_from_pixelTexture...\n");
350 wid = node->image.whc[0];
351 hei = node->image.whc[1];
352 depth = node->image.whc[2];
354 DEBUG_TEX (
"wid %d hei %d depth %d\n",wid,hei,depth);
356 if ((depth < 0) || (depth >4)) {
357 printf (
"PixelTexture, depth %d out of range, assuming 1\n",(
int) depth);
361 if ((wid*hei) > node->image.arr.n) {
362 printf (
"PixelTexture, not enough data for wid %d hei %d, have %d\n",
363 wid, hei, node->image.arr.n);
376 this_tex->hasAlpha = ((depth == 2) || (depth == 4));
377 this_tex->channels = depth;
379 texture = MALLOC (
unsigned char *, wid*hei*4);
380 this_tex->texdata = texture;
381 this_tex->status = TEX_NEEDSBINDING;
385 for (count = 0; count < (wid*hei); count++) {
388 texture[tctr++] = *iptr & 0xff;
389 texture[tctr++] = *iptr & 0xff;
390 texture[tctr++] = *iptr & 0xff;
391 texture[tctr++] = 0xff;
395 texture[tctr++] = (*iptr>>8) & 0xff;
396 texture[tctr++] = (*iptr>>8) & 0xff;
397 texture[tctr++] = (*iptr>>8) & 0xff;
398 texture[tctr++] = (*iptr>>0) & 0xff;
402 texture[tctr++] = (*iptr>>16) & 0xff;
403 texture[tctr++] = (*iptr>>8) & 0xff;
404 texture[tctr++] = (*iptr>>0) & 0xff;
405 texture[tctr++] = 0xff;
409 texture[tctr++] = (*iptr>>24) & 0xff;
410 texture[tctr++] = (*iptr>>16) & 0xff;
411 texture[tctr++] = (*iptr>>8) & 0xff;
412 texture[tctr++] = (*iptr>>0) & 0xff;
421static void texture_load_blank_Texture(textureTableIndexStruct_s* this_tex,
struct X3D_GeneratedTexture* node)
424 unsigned char* texture;
431 wid = node->size.p[0];
432 hei = node->size.p[1];
443 this_tex->hasAlpha = (depth == 4);
444 this_tex->channels = depth;
446 texture = MALLOC(
unsigned char*, wid * hei * 4);
447 memset(texture, 0, wid * hei * 4);
448 this_tex->texdata = texture;
449 this_tex->status = TEX_NEEDSBINDING;
452 if (texture != NULL) {
454 for (count = 0; count < (wid * hei); count++) {
455 texture[tctr+3] = 0xff;
462static void texture_load_from_pixelTexture3D (textureTableIndexStruct_s* this_tex,
struct X3D_PixelTexture3D *node)
466 int hei,wid,bpp,dep,nvox,nints;
467 unsigned char *texture;
473 iptr = node->image.p;
477 DEBUG_TEX (
"start of texture_load_from_pixelTexture...\n");
480 if (node->image.n < 4) {
481 printf (
"PixelTexture, need at least 3 elements, have %d\n",node->image.n);
495 DEBUG_TEX (
"bpp %d wid %d hei %d dep %d \n",bpp,wid,hei,dep);
497 if ((bpp < 0) || (bpp >4)) {
498 printf (
"PixelTexture, bytes per pixel %d out of range, assuming 1\n",(
int) bpp);
502 nints = (nvox * bpp) / 4;
503 if ((nints + 4) > node->image.n) {
504 printf (
"PixelTexture3D, not enough data for bpp %d wid %d hei %d, dep %d, need %d have %d\n",
505 bpp, wid, hei, dep, nints + 4, node->image.n);
519 this_tex->hasAlpha = ((bpp == 2) || (bpp == 4));
520 this_tex->channels = bpp;
522 texture = MALLOC (
unsigned char *, wid*hei*4*dep);
523 this_tex->texdata = texture;
524 this_tex->status = TEX_NEEDSBINDING;
528 for (count = 0; count < (wid*hei*dep); count++) {
531 texture[tctr++] = *iptr & 0xff;
532 texture[tctr++] = *iptr & 0xff;
533 texture[tctr++] = *iptr & 0xff;
534 texture[tctr++] = 0xff;
538 texture[tctr++] = (*iptr>>8) & 0xff;
539 texture[tctr++] = (*iptr>>8) & 0xff;
540 texture[tctr++] = (*iptr>>8) & 0xff;
541 texture[tctr++] = (*iptr>>0) & 0xff;
545 texture[tctr++] = (*iptr>>16) & 0xff;
546 texture[tctr++] = (*iptr>>8) & 0xff;
547 texture[tctr++] = (*iptr>>0) & 0xff;
548 texture[tctr++] = 0xff;
552 texture[tctr++] = (*iptr>>24) & 0xff;
553 texture[tctr++] = (*iptr>>16) & 0xff;
554 texture[tctr++] = (*iptr>>8) & 0xff;
555 texture[tctr++] = (*iptr>>0) & 0xff;
575 int i,j,k,nx,ny,nz,ishex, iret, totalbytes, ipix, nchan;
581 fp = fopen(fname,
"r");
590 rv=fgets(line,1000,fp);
591 if(strncmp(line,
"x3di3d",6)){
597 if(!strncmp(line,
"x3di3d x",8)) ishex = 1;
598 rvi=fscanf(fp,
"%d %d %d %d",&nchan, &nx,&ny,&nz);
599 totalbytes = 4 * nx * ny * nz;
600 if(totalbytes <= 128 * 128 * 128 * 4){
601 unsigned char *rgbablob;
602 rgbablob = malloc(nx * ny * nz * 4);
603 memset(rgbablob,0,nx*ny*nz*4);
609 unsigned char pixel[4],*
rgba;
611 rvi=fscanf(fp,
"%x",&pixint);
613 rvi=fscanf(fp,
"%d",&pixint);
615 pixel[0] = (pixint >> 0) & 0xff;
616 pixel[1] = (pixint >> 8) & 0xff;
617 pixel[2] = (pixint >> 16) & 0xff;
618 pixel[3] = (pixint >> 24) & 0xff;
620 ipix = (i*nz +j)*ny +k;
621 rgba = &rgbablob[ipix*4];
626 case 3:
rgba[0] = pixel[2];
rgba[1] = pixel[1];
rgba[2] = pixel[2];
rgba[3] = 255;
628 case 4:
rgba[0] = pixel[3];
rgba[1] = pixel[2];
rgba[2] = pixel[1];
rgba[3] = pixel[0];
break;
636 tti->channels = nchan;
640 tti->texdata = rgbablob;
659 int i,j,k,nx,ny,nz, ipix, nchan;
661 unsigned char *rgbablob;
664 fp = fopen(fname,
"w+");
665 nchan = tti->channels;
669 rgbablob = tti->texdata;
671 fprintf(fp,
"x3di3d x\n");
672 fprintf(fp,
"%d %d %d %d",nchan, nx,ny,nz);
678 ipix = (i*nz +j)*ny +k;
679 rgba = &rgbablob[ipix*4];
682 case 1: pixint =
rgba[0];
break;
683 case 2: pixint = (
rgba[0] << 8) +
rgba[3];
break;
684 case 3: pixint = (
rgba[0] << 16) + (
rgba[1] << 8) + (
rgba[2] << 0);
break;
685 case 4: pixint = (
rgba[0] << 24) + (
rgba[1] << 16) + (
rgba[2] << 8) +
rgba[3];
break;
690 case 1: fprintf(fp,
" %#.2x",pixint);
break;
691 case 2: fprintf(fp,
" %#.4x",pixint);
break;
692 case 3: fprintf(fp,
" %#.6x",pixint);
break;
693 case 4: fprintf(fp,
" %#.8x",pixint);
break;
695 fprintf(fp,
" 0x00");
break;
732 int i,j,k,m,nx,ny,nz,nv,nc, iret, totalbytes, ipix, jpix, kpix, nchan;
733 int version, Rmin, Rmax, Nchannelspervalue, Mvaluesperpixel, Dimensions;
734 unsigned int pixint, Pixels[10], iydown;
736 char Geometry, ODescription[200], Type, Componentnames[10], YDirection;
741 fp = fopen(fname,
"r");
747 rv = fgets(line,1000,fp);
748 if(strncmp(line,
"web3dit",7)){
754 rv=fgets(line,1000,fp);
755 sscanf(line,
"%c",&Geometry);
756 rv=fgets(line,1000,fp);
757 sscanf(line,
"%d",&version);
758 rv=fgets(line,1000,fp);
759 sscanf(line,
"%s",ODescription);
760 rv=fgets(line,1000,fp);
761 sscanf(line,
"%c",&Type);
762 rv=fgets(line,1000,fp);
763 sscanf(line,
"%d %d",&Rmin,&Rmax);
765 rv=fgets(line,1000,fp);
766 sscanf(line,
"%d",&Nchannelspervalue);
767 rv=fgets(line,1000,fp);
768 sscanf(line,
"%d",&Mvaluesperpixel);
769 rv=fgets(line,1000,fp);
770 sscanf(line,
"%s",Componentnames);
771 rv=fgets(line,1000,fp);
772 sscanf(line,
"%d",&Dimensions);
773 rv=fgets(line,1000,fp);
774 sscanf(line,
"%d %d %d",&Pixels[0], &Pixels[1], &Pixels[2]);
775 rv=fgets(line,1000,fp);
776 sscanf(line,
"%c",&YDirection);
777 rv=fgets(line,1000,fp);
783 if(Dimensions > 2) nz = Pixels[2];
784 nv = Mvaluesperpixel;
785 nc = Nchannelspervalue;
788 if(YDirection ==
'U') iydown = 0;
790 totalbytes = 4 * nx * ny * nz;
791 if(totalbytes <= 256 * 256 * 256 * 4){
792 unsigned char *rgbablob;
793 rgbablob = malloc(totalbytes);
794 memset(rgbablob,0,totalbytes);
800 unsigned char pixel[4],*
rgba, n;
801 pixel[0] = pixel[1] = pixel[2] = pixel[3] = 0;
808 rvi=fscanf(fp,
"%f",&pixfloat);
811 rvi=fscanf(fp,
"%x",&pixint);
815 rvi=fscanf(fp,
"%d",&pixint);
821 pixel[n] = (
unsigned char)(
unsigned int)((pixfloat - Rmin) / (Rmax - Rmin) * 255.0);
826 pixel[n] = (pixint >> n*8) & 0xff;
835 ipix = (i*ny +j)*nx +k;
836 jpix = (i*ny +(ny-1-j))*nx + k;
837 kpix = iydown ? jpix : ipix;
838 rgba = &rgbablob[kpix*4];
843 case 3:
rgba[0] = pixel[2];
rgba[1] = pixel[1];
rgba[2] = pixel[0];
rgba[3] = 255;
845 case 4:
rgba[0] = pixel[3];
rgba[1] = pixel[2];
rgba[2] = pixel[1];
rgba[3] = pixel[0];
break;
854 tti->channels = nchan;
858 tti->texdata = rgbablob;
861 for(i=0;i<tti->z;i++){
862 for(j=0;j<tti->y;j++){
863 for(k=0;k<tti->x;k++){
867 ipix = (i*tti->y + j)*tti->x + k;
870 memcpy(&pixint,&tti->texdata[kpix*4],4);
871 printf(
"%x ",pixint);
914 int i,j,k,nx,ny,nz, ipix, jpix, kpix, iydown, nchan;
915 int version, Rmin, Rmax, Nchannelspervalue, Mvaluesperpixel, Dimensions;
917 char Geometry, *ODescription, Type, *Componentnames, YDirection;
919 static char *LRGBA [] = {
"L",
"LA",
"RGB",
"RGBA"};
922 fp = fopen(fname,
"w+");
924 unsigned char *rgbablob;
925 nchan = tti->channels;
929 rgbablob = tti->texdata;
930 Dimensions = nz == 1 ? 2 : 3;
934 Nchannelspervalue = nchan;
941 if(nz > 1) Geometry =
'3';
942 Componentnames = LRGBA[nchan -1];
945 iydown = (YDirection ==
'D') ? 1 : 0;
947 fprintf(fp,
"web3dit%c #H 7 byte magic header, means web3d compatible image in text form, 1byte for Geometry sniffing\n",Geometry);
948 fprintf(fp,
"%c #G {C,P,3,2}: image geometry: C: cubemap RHS y-up z/depth/layer/order [+-x,+-y,+-z], top of top +z, bottom of bottom -z P: 360 panorama [L->R, 360/z ], 3: texture3D or Volume [z=depth], 2: texture2D\n",Geometry);
949 fprintf(fp,
"%d #F {1} file version\n",version);
950 fprintf(fp,
"%s #O optional description\n",ODescription);
951 fprintf(fp,
"%c #T {x,i,f} how to read space-delimited value: x as hex, i as int, f as float\n",Type);
952 fprintf(fp,
"%d %d #R range of channel, most useful for normalizing floats\n",Rmin,Rmax);
953 fprintf(fp,
"%d #N channels/components per value ie RGBA as int: 4, RGBA as 4 ints: 1\n",Nchannelspervalue);
954 fprintf(fp,
"%d #M values per pixel ie RGBA as int: 1, RGBA as 4 ints: 4\n",Mvaluesperpixel);
955 fprintf(fp,
"%s #C[N*M] component names and order, choose from: {R,G,B,A,L} ie RGBA, LA, L, RGB\n",Componentnames);
956 fprintf(fp,
"%d #D number of dimensions, 2 for normal 2D image, 3 for 3D image\n",Dimensions);
957 fprintf(fp,
"%d %d %d #P[D] size in pixels in each dimension: x,y,z (use 1 for z if 2D)\n",nx,ny,nz);
958 fprintf(fp,
"%c #Y {U,D} image y-Down or texture y-Up row order\n",YDirection);
959 fprintf(fp,
"#I image values follow with x in inner loop, y-down image direction, z in outer:\n");
966 ipix = (i*ny +j)*nx +k;
967 jpix = (i*ny +(ny-1-j))*nx + k;
968 kpix = iydown ? jpix : ipix;
969 rgba = &rgbablob[kpix*4];
972 case 1: pixint =
rgba[0];
break;
973 case 2: pixint = (
rgba[0] << 8) +
rgba[3];
break;
974 case 3: pixint = (
rgba[0] << 16) + (
rgba[1] << 8) + (
rgba[2] << 0);
break;
975 case 4: pixint = (
rgba[0] << 24) + (
rgba[1] << 16) + (
rgba[2] << 8) +
rgba[3];
break;
980 case 1: fprintf(fp,
" %#.2x",pixint);
break;
981 case 2: fprintf(fp,
" %#.4x",pixint);
break;
982 case 3: fprintf(fp,
" %#.6x",pixint);
break;
983 case 4: fprintf(fp,
" %#.8x",pixint);
break;
985 fprintf(fp,
" 0x00");
break;
1017 int i,j,k,nx,ny,nz, bitsperpixel, bpp, iendian, iret, totalbytes, ipix, nchan;
1019 float sx,sy,sz,tx,ty,tz;
1024 fp = fopen(fname,
"r+b");
1030 rv=fgets(line,1000,fp);
1031 if(strncmp(line,
"vol",3)){
1036 rv=fgets(line,1000,fp);
1037 sscanf(line,
"%d %d %d",&nx,&ny,&nz);
1038 rv=fgets(line,1000,fp);
1039 sscanf(line,
"%f %f %f",&sx,&sy,&sz);
1040 rv=fgets(line,1000,fp);
1041 sscanf(line,
"%f %f %f",&tx,&ty,&tz);
1042 rv=fgets(line,1000,fp);
1043 sscanf(line,
"%d %d",&bitsperpixel,&iendian);
1044 bpp = bitsperpixel / 8;
1046 switch(bitsperpixel){
1047 case 1: nchan = 1;
break;
1049 case 2: nchan = 4;
break;
1051 case 4: nchan = 1;
break;
1053 case 8: nchan = 1;
break;
1055 case 16: nchan = 1;
break;
1057 case 32: nchan = 1;
break;
1063 totalbytes = bpp * nx * ny * nz;
1064 if(totalbytes < 128 * 128 * 128 *4){
1065 unsigned char* blob, *rgbablob;
1069 blob = malloc(totalbytes + 4);
1070 rgbablob = malloc(nx * ny * nz * 4);
1071 memset(rgbablob,0,nx*ny*nz*4);
1073 rvt=fread(blob,totalbytes,1,fp);
1078 unsigned char *pixel,*
rgba;
1079 ipix = (i*ny +j)*nx +k;
1081 pixel = &blob[ipix*bpp];
1082 rgba = &rgbablob[ipix*4];
1084 switch(bitsperpixel){
1090 rgba[0] = pixel[0] >> 4;
1091 rgba[1] = pixel[0] & 0xF;
1092 rgba[2] = pixel[1] >> 4;
1093 rgba[3] = pixel[1] & 0xF;
1104 rgba[0] =
rgba[1] =
rgba[2] = (
unsigned char) *(
unsigned short*)pixel;
1119 if(blob) free(blob);
1120 tti->channels = nchan;
1124 tti->texdata = rgbablob;
1138int isMachineLittleEndian(){
1141 unsigned short int one = 1;
1144 c = (
unsigned char *)&one;
1145 iret = (c[0] == 1) ? TRUE : FALSE;
1158NRRDFIELD_interpretation,
1161const char *fieldname;
1165{
"type:",5,NRRDFIELD_type},
1166{
"dimension:",10,NRRDFIELD_dimension},
1167{
"sizes:",6,NRRDFIELD_sizes},
1168{
"spacings:",9,NRRDFIELD_spacing},
1169{
"encoding:",9,NRRDFIELD_encoding},
1170{
"endian:",7,NRRDFIELD_endian},
1171{
"nchannel:=",10,NRRDFIELD_nchannel},
1172{
"interpretation:=",16,NRRDFIELD_interpretation},
1188const char * stypes[7];
1192} nrrddatatypes [] = {
1193{{
"signed char",
"int8_t",
"int8", NULL,NULL,NULL,NULL}, CDATATYPE_char, 1,
"%hh"},
1194{{
"uchar",
"unsigned char",
"uint8",
"uint8_t", NULL,NULL,NULL}, CDATATYPE_uchar, 1,
"%hhu" },
1195{{
"short",
"short int",
"signed short",
"signed short int",
"int16",
"int16_t", NULL}, CDATATYPE_short, 2,
"%hd" },
1196{{
"ushort",
"unsigned short",
"unsigned short int",
"uint16",
"uint16_t", NULL, NULL}, CDATATYPE_ushort, 2,
"%hu" },
1197{{
"int",
"signed int",
"int32",
"int32_t", NULL, NULL, NULL}, CDATATYPE_int, 4,
"%d"},
1198{{
"uint",
"unsigned int",
"uint32",
"uint32_t", NULL, NULL, NULL}, CDATATYPE_uint, 4,
"%u" },
1199{{
"longlong",
"long long",
"long long int",
"signed long long",
"signed long long int",
"int64",
"int64_t"}, CDATATYPE_longlong, 8,
"%lld"},
1200{{
"ulonglong",
"unsigned long long",
"unsigned long long int",
"uint64",
"uint64_t", NULL, NULL}, CDATATYPE_ulonglong, 8,
"%llu" },
1201{{
"float", NULL,NULL,NULL,NULL, NULL,NULL},CDATATYPE_float,4,
"%f" },
1202{{
"double", NULL,NULL,NULL,NULL, NULL,NULL},CDATATYPE_double,8,
"%lf"},
1203{{NULL,NULL,NULL,NULL, NULL,NULL,NULL},0},
1206NRRDENDIAN_LITTLE = 1,
1210NRRDENCODING_RAW = 1,
1255 fp = fopen(fname,
"r+b");
1257 unsigned long long i,j,k;
1258 int ifieldtype, idatatype;
1260 int idim, ilen, isize[4], iendian, iencoding, ifound,slen,klen, bsize;
1262 char cendian[256], cencoding[256];
1265 unsigned long long nvoxel;
1266 unsigned long long totalbytes;
1267 unsigned char *data;
1268 unsigned char *voxel;
1278 rv=fgets(line,2047,fp);
1279 if(strncmp(line,
"NRRD",4)){
1289 isize[0] = isize[1] = isize[2] = isize[3] = 0;
1295 rv=fgets(line,2047,fp);
1299 if(strlen(line) < 3){
1306 if(!nrrdfields[i].fieldname)
break;
1307 if(!strncmp(line,nrrdfields[i].fieldname,nrrdfields[i].len)){
1308 ifieldtype = nrrdfields[i].fieldtype;
1309 ilen = nrrdfields[i].len;
1314 remainder = &line[ilen];
1316 case NRRDFIELD_type:
1319 if(remainder[0] ==
' ') remainder = &remainder[1];
1322 slen = strlen(remainder);
1325 for(i=0;i<slen;i++){
1326 char c = remainder[slen-1 -i];
1327 if(c ==
'\n' || c ==
'\r' || c ==
' ') klen--;
1334 if(nrrddatatypes[k].itype == 0)
break;
1336 if(nrrddatatypes[k].stypes[j]){
1337 if(!strncmp(remainder,nrrddatatypes[k].stypes[j],klen)){
1339 idatatype = nrrddatatypes[k].itype;
1341 bsize = nrrddatatypes[k].bsize;
1342 fmt = nrrddatatypes[k].fmt;
1351 case NRRDFIELD_dimension:
1352 sscanf(remainder,
"%d",&idim);
1355 case NRRDFIELD_sizes:
1358 sscanf(remainder,
"%d",&isize[0]);
break;
1360 sscanf(remainder,
"%d%d",&isize[0],&isize[1]);
break;
1362 sscanf(remainder,
"%d%d%d",&isize[0],&isize[1],&isize[2]);
break;
1364 sscanf(remainder,
"%d%d%d%d",&isize[0],&isize[1],&isize[2],&isize[3]);
break;
1369 case NRRDFIELD_encoding:
1370 sscanf(remainder,
"%s",cencoding);
1371 if(!strcmp(cencoding,
"raw"))
1372 iencoding = NRRDENCODING_RAW;
1373 else if(!strcmp(cencoding,
"ascii"))
1374 iencoding = NRRDENCODING_ASCII;
1378 case NRRDFIELD_endian:
1379 sscanf(remainder,
"%s",cendian);
1380 if(!strcmp(cendian,
"little"))
1381 iendian = NRRDENDIAN_LITTLE;
1382 else if(!strcmp(cendian,
"big"))
1383 iendian = NRRDENDIAN_BIG;
1386 case NRRDFIELD_nchannel:
1387 sscanf(remainder,
"%d", &nchannel);
1389 case NRRDFIELD_interpretation:
1390 printf(
"nrrd interpretation:=%s",remainder);
1400 printf(
"iendian %d idatatype %d iencoding %d idim %d isizes %d %d %d %d bsize %d\n",
1401 iendian,idatatype,iencoding,idim,isize[0],isize[1],isize[2],isize[3], bsize);
1402 printf(
"machine endian isLittle=%d\n",isMachineLittleEndian());
1403 printf(
"hows that?\n");
1409 for(i=0;i<idim-1;i++){
1410 isize[i] = isize[i+1];
1415 if(idim <3) isize[2] = 1;
1416 if(idim <2) isize[1] = 1;
1422 nvoxel = isize[0] * isize[1] * isize[2];
1423 totalbytes = nvoxel * bsize;
1424 data = MALLOC(
unsigned char *,(
size_t)totalbytes);
1425 memset(data,0,(
size_t)totalbytes);
1426 voxel = MALLOC(
unsigned char *, bsize);
1428 if(iencoding == NRRDENCODING_RAW){
1429 int dataLittleEndian;
1430 size_t nelem_read, element_size = 0L;
1431 element_size = bsize;
1432 nelem_read = fread(data,element_size, (
size_t)nvoxel,fp);
1433 printf(
"num elems read = %llu elemsize %ld bytes requeted = %llu %llu\n",(
unsigned long long)nelem_read,(
long)bsize,bsize*nvoxel,totalbytes);
1435 dataLittleEndian = iendian == NRRDENDIAN_LITTLE ? TRUE : FALSE;
1436 if(isMachineLittleEndian() != dataLittleEndian && bsize > 1){
1438 printf(
"swapping endian\n");
1439 for(i=0;i<nvoxel;i++){
1440 unsigned char * voxel = &data[i*bsize];
1441 for(j=0;j<bsize/2;j++){
1445 voxel[j] = voxel[k];
1450 }
else if(iencoding == NRRDENCODING_ASCII){
1453 for(i=0;i<isize[2];i++){
1455 for(j=0;j<isize[1];j++){
1457 for(k=0;k<isize[0];k++){
1462 rvi=fscanf(fp,fmt,voxel);
1464 memcpy(&data[kvox*bsize],voxel,bsize);
1470 if (nchannel == 1) {
1476 switch (idatatype) {
1477 case CDATATYPE_char:
1481 case CDATATYPE_uchar:
1485 case CDATATYPE_short:
1486 dlo = dhi = (double)*(
short*)(voxel);
1488 case CDATATYPE_ushort:
1489 dlo = dhi = (double)*(
unsigned short*)(voxel);
1490 printf(
"initial range for ushort hi %lf lo %lf\n", dhi, dlo);
1493 dlo = dhi = (double)*(
long*)(voxel);
1495 case CDATATYPE_uint:
1496 dlo = dhi = (double)*(
unsigned long*)(voxel);
1498 case CDATATYPE_longlong:
1499 dlo = dhi = (double)*(
long long*)(voxel);
1501 case CDATATYPE_ulonglong:
1502 dlo = dhi = (double)*(
unsigned long long*)(voxel);
1504 case CDATATYPE_float:
1505 dlo = dhi = (double)*(
float*)(voxel);
1507 case CDATATYPE_double:
1508 dlo = dhi = *(
double*)(voxel);
1514 for (i = 0; i < nvoxel; i++) {
1515 unsigned char* voxel;
1519 voxel = &data[i * bsize];
1520 switch (idatatype) {
1521 case CDATATYPE_char:
1522 dlo = min(dlo, (
double)*(
char*)(voxel));
1523 dhi = max(dhi, (
double)*(
char*)(voxel));
1525 case CDATATYPE_uchar:
1526 dlo = min(dlo, (
double)*(
unsigned char*)(voxel));
1527 dhi = max(dhi, (
double)*(
unsigned char*)(voxel));
1529 case CDATATYPE_short:
1530 dlo = min(dlo, (
double)*(
short*)(voxel));
1531 dhi = max(dhi, (
double)*(
short*)(voxel));
1533 case CDATATYPE_ushort:
1534 dlo = min(dlo, (
double)*(
unsigned short*)(voxel));
1535 dhi = max(dhi, (
double)*(
unsigned short*)(voxel));
1538 dlo = min(dlo, (
double)*(
long*)(voxel));
1539 dhi = max(dhi, (
double)*(
long*)(voxel));
1541 case CDATATYPE_uint:
1542 dlo = min(dlo, (
double)*(
unsigned long*)(voxel));
1543 dhi = max(dhi, (
double)*(
unsigned long*)(voxel));
1545 case CDATATYPE_longlong:
1546 dlo = min(dlo, (
double)*(
unsigned long long*)(voxel));
1547 dhi = max(dhi, (
double)*(
unsigned long long*)(voxel));
1549 case CDATATYPE_ulonglong:
1550 dlo = min(dlo, (
double)*(
unsigned long*)(voxel));
1551 dhi = max(dhi, (
double)*(
unsigned long*)(voxel));
1553 case CDATATYPE_float:
1554 dlo = min(dlo, (
double)*(
float*)(voxel));
1555 dhi = max(dhi, (
double)*(
float*)(voxel));
1557 case CDATATYPE_double:
1558 dlo = min(dlo, (
double)*(
double*)(voxel));
1559 dhi = max(dhi, (
double)*(
double*)(voxel));
1565 d255range = 255.0 / (dhi - dlo);
1566 if (1) printf(
"nrrd image voxel range hi %lf lo %lf 255range scale factor %lf\n", dhi, dlo, d255range);
1569 tti->texdata = MALLOC(
unsigned char *,(
size_t)nvoxel * 4);
1570 tti->channels = nchannel;
1572 tti->hasAlpha = TRUE;
1576 memset(counts,0,256*
sizeof(
int));
1577 for(i=0;i<nvoxel;i++){
1578 unsigned char *voxel;
1580 unsigned char *
rgba = &tti->texdata[i*4];
1584 voxel = &data[i*bsize];
1585 if (nchannel == 1) {
1588 switch (idatatype) {
1589 case CDATATYPE_char:
1590 A = (char)(voxel[0]) + 127;
1592 case CDATATYPE_uchar:
1595 case CDATATYPE_short:
1596 A = (
unsigned char)((*(
short*)voxel) / 255) + 127;
1598 case CDATATYPE_ushort:
1601 unsigned short thisushort;
1602 memcpy(&thisushort, voxel, bsize);
1611 counts[thisushort]++;
1613 A = (
unsigned char)thisushort;
1617 A = (
unsigned char)((*((
long*)voxel)) / 65536 / 255 + 127);
1619 case CDATATYPE_uint:
1620 A = (
unsigned char)((*((
unsigned long*)voxel)) / 65536 / 255);
1622 case CDATATYPE_longlong:
1623 A = (
unsigned char)((*((
long long*)voxel)) / 65536 / 65536 / 255 + 127);
1625 case CDATATYPE_ulonglong:
1626 A = (
unsigned char)((*((
unsigned long long*)voxel)) / 65536 / 65536 / 255);
1645 switch (idatatype) {
1646 case CDATATYPE_char:
1647 A = (
unsigned char)((
int)(voxel[0])) + 127;
1649 case CDATATYPE_uchar:
1652 case CDATATYPE_short:
1653 dtemp = (double)(*(
short*)voxel);
1654 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1656 case CDATATYPE_ushort:
1657 dtemp = (double)(*(
unsigned short*)voxel);
1664 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1669 dtemp = (double)(*(
long*)voxel);
1670 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1672 case CDATATYPE_uint:
1673 dtemp = (double)(*(
unsigned long*)voxel);
1674 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1676 case CDATATYPE_longlong:
1677 dtemp = (double)(*(
long long*)voxel);
1678 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1680 case CDATATYPE_ulonglong:
1681 dtemp = (double)(*(
unsigned long long*)voxel);
1682 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1684 case CDATATYPE_float:
1685 dtemp = (double)(*(
float*)voxel);
1686 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1688 case CDATATYPE_double:
1689 dtemp = (double)(*(
double*)voxel);
1690 A = (
unsigned char)(
unsigned short)(
unsigned int)((dtemp - dlo) * d255range);
1705 if (0)
for (i = 0; i < 256; i++)
1707 printf(
"counts[%ld]=%ld\n", (
long)i, (
long)counts[i]);
1735#if defined(_ANDROID) || defined(ANDROIDNDK)
1737static unsigned char *flipImageVerticallyB(
unsigned char *input,
int height,
int width,
int bpp) {
1739 unsigned char *sourcerow, *destrow;
1740 unsigned char * blob;
1742 rowcount = width * bpp;
1743 blob = MALLOC(
unsigned char*, height * rowcount);
1744 for(i=0;i<height;i++) {
1745 ii = height - 1 - i;
1746 sourcerow = &input[i*rowcount];
1747 destrow = &blob[ii*rowcount];
1748 memcpy(destrow,sourcerow,rowcount);
1753static unsigned char *flipImageVertically(
unsigned char *input,
int height,
int width) {
1754 return flipImageVerticallyB(input,height,width,4);
1756static unsigned char *expandto4bppfromGray(
unsigned char *input,
int height,
int width,
int bpp) {
1757 int i, j, rowcountin, rowcountout;
1758 unsigned char *sourcerow, *destrow;
1759 unsigned char * blob;
1761 rowcountin = width * bpp;
1762 rowcountout = width * 4;
1763 blob = MALLOCV(height * rowcountout);
1764 for (i = 0; i<height; i++) {
1765 sourcerow = &input[i*rowcountin];
1766 destrow = &blob[i*rowcountout];
1767 for (j = 0; j<width; j++) {
1768 unsigned char *op = &destrow[j * 4];
1769 op[0] = op[1] = op[2] = sourcerow[j*bpp];
1770 op[3] = bpp == 1 ? 255 : sourcerow[j*bpp + 1];
1776static unsigned char *expandto4bppfromRGB(
unsigned char *input,
int height,
int width,
int bpp) {
1777 int i, j, rowcountin, rowcountout;
1778 unsigned char *sourcerow, *destrow;
1779 unsigned char * blob;
1781 rowcountin = width * bpp;
1782 rowcountout = width * 4;
1783 blob = MALLOCV(height * rowcountout);
1784 for (i = 0; i<height; i++) {
1785 sourcerow = &input[i*rowcountin];
1786 destrow = &blob[i*rowcountout];
1787 for(j=0;j<width;j++){
1788 memcpy(&destrow[j*4], &sourcerow[j*bpp], bpp);
1789 destrow[j*4 + 3] = 255;
1795static unsigned char *expandto4bpp(
unsigned char *input,
int height,
int width,
int bpp) {
1796 unsigned char * retval = NULL;
1797 if(bpp == 1 || bpp == 2)
1798 retval = expandto4bppfromGray(input, height, width, bpp);
1800 retval = expandto4bppfromRGB(input, height, width, bpp);
1810static img_lib_t ilib = NULL;
1811int loadImage(textureTableIndexStruct_s* tti,
char* fname)
1815 if(!ilib) ierr = img_lib_attach( &ilib );
1816 img.format = IMG_FMT_PKLE_ARGB8888;
1817 img.flags |= IMG_FORMAT;
1818 ierr= img_load_file(ilib, fname, NULL, &img);
1827 tti->texdata = img.access.direct.data;
1829 printf(
"ouch in gdiplus image loader L140 - no image data\n");
1832 int flipvertically = 1;
1834 int i,j,ii,rowcount;
1835 unsigned char *sourcerow, *destrow;
1836 unsigned char * blob;
1837 rowcount = tti->x * 4;
1838 blob = MALLOCV(img.h * rowcount);
1839 for(i=0;i<img.h;i++) {
1840 ii = tti->y - 1 - i;
1841 sourcerow = &tti->texdata[i*rowcount];
1842 destrow = &blob[ii*rowcount];
1843 memcpy(destrow,sourcerow,rowcount);
1845 tti->texdata = blob;
1860char* download_file(
char* filename);
1861void close_openned_file(openned_file_t *file);
1862int load_file_blob(
const char *filename,
char **blob,
int *len);
1864#if defined(ANDROIDNDK)
1865#define HAVE_LIBJPEG_H 1
1866#ifdef HAVE_LIBJPEG_H
1869struct my_error_mgr {
1870 struct jpeg_error_mgr pub;
1871 jmp_buf setjmp_buffer;
1874typedef struct my_error_mgr * my_error_ptr;
1881my_error_exit(j_common_ptr cinfo)
1884 my_error_ptr myerr = (my_error_ptr)cinfo->err;
1891 longjmp(myerr->setjmp_buffer, 1);
1895#define JPEG_SUCCESS 0
1897static int loadImageTexture_jpeg(textureTableIndexStruct_s* this_tex,
char *filename) {
1901 unsigned char *image_data = 0;
1905 struct jpeg_decompress_struct cinfo;
1906 struct my_error_mgr jerr;
1910 unsigned rowcount, columncount;
1916 if ((infile = fopen(filename,
"rb")) == NULL) {
1917 fprintf(stderr,
"can't open %s\n", filename);
1931 cinfo.err = jpeg_std_error(&jerr.pub);
1932 jerr.pub.error_exit = my_error_exit;
1933 if (setjmp(jerr.setjmp_buffer)) {
1935 ConsoleMessage(
"FreeWRL Image problem - could not read %s\n", filename);
1936 jpeg_destroy_compress((j_compress_ptr)&cinfo);
1942 jpeg_create_decompress(&cinfo);
1945 jpeg_stdio_src(&cinfo, infile);
1950 tempInt = jpeg_read_header(&cinfo, TRUE);
1954 (void)jpeg_start_decompress(&cinfo);
1958 row = (JSAMPLE*)MALLOCV(cinfo.output_width *
sizeof(JSAMPLE)*cinfo.output_components);
1960 image_data = (
unsigned char *)MALLOCV(cinfo.output_width *
sizeof(JSAMPLE) * cinfo.output_height * cinfo.output_components);
1962 for (rowcount = 0; rowcount < cinfo.output_height; rowcount++) {
1963 nrows = jpeg_read_scanlines(&cinfo, rowptr, 1);
1968 for (columncount = 0; columncount < cinfo.output_width; columncount++) {
1969 for (dp = 0; dp<cinfo.output_components; dp++) {
1970 image_data[(cinfo.output_height - rowcount - 1)
1971 *cinfo.output_width*cinfo.output_components
1972 + columncount* cinfo.output_components + dp]
1973 = row[columncount*cinfo.output_components + dp];
1978 int iret = JPEG_SUCCESS;
1979 if (jpeg_finish_decompress(&cinfo) != TRUE) {
1980 printf(
"warning: jpeg_finish_decompress error\n");
1992 this_tex->x = (int)cinfo.output_width;
1993 this_tex->y = (int)cinfo.output_height;
1994 this_tex->hasAlpha = 0;
1996 int bpp = cinfo.output_components;
1997 this_tex->channels = bpp;
2000 char *data4bpp = expandto4bpp(image_data,this_tex->y,this_tex->x,bpp);
2002 this_tex->frames = 1;
2003 this_tex->texdata = data4bpp;
2004 FREE_IF_NZ(image_data);
2005 this_tex->filename = filename;
2007 jpeg_destroy_decompress(&cinfo);
2010 return JPEG_SUCCESS;
2017#define HAVE_LIBPNG_H 1
2023#define PNG_SUCCESS 0
2026 const png_byte* data;
2027 const png_size_t size;
2031 const DataHandle data;
2036 const png_uint_32 width;
2037 const png_uint_32 height;
2038 const int color_type;
2040static GLenum get_gl_color_format(
const int png_color_format) {
2045 switch (png_color_format) {
2046 case PNG_COLOR_TYPE_GRAY:
2047 return GL_LUMINANCE;
2048 case PNG_COLOR_TYPE_RGB_ALPHA:
2050 case PNG_COLOR_TYPE_GRAY_ALPHA:
2051 return GL_LUMINANCE_ALPHA;
2052 case PNG_COLOR_TYPE_RGB:
2059static PngInfo read_and_update_info(
const png_structp png_ptr,
const png_infop info_ptr)
2061 png_uint_32 width, height;
2062 int bit_depth, color_type;
2064 png_read_info(png_ptr, info_ptr);
2066 png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
2069 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
2070 png_set_tRNS_to_alpha(png_ptr);
2073 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
2074 png_set_expand_gray_1_2_4_to_8(png_ptr);
2077 if (color_type == PNG_COLOR_TYPE_PALETTE)
2078 png_set_palette_to_rgb(png_ptr);
2082 if (color_type == PNG_COLOR_TYPE_PALETTE || color_type == PNG_COLOR_TYPE_RGB)
2083 png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
2087 png_set_packing(png_ptr);
2088 else if (bit_depth == 16)
2089 png_set_scale_16(png_ptr);
2091 png_read_update_info(png_ptr, info_ptr);
2094 color_type = png_get_color_type(png_ptr, info_ptr);
2096 return (PngInfo) { width, height, color_type };
2098static DataHandle read_entire_png_image(
2099 const png_structp png_ptr,
2100 const png_infop info_ptr,
2101 const png_uint_32 height)
2103 const png_size_t row_size = png_get_rowbytes(png_ptr, info_ptr);
2104 const int data_length = row_size * height;
2105 assert(row_size > 0);
2107 png_byte* raw_image = malloc(data_length);
2108 assert(raw_image != NULL);
2110 png_byte* row_ptrs[height];
2113 for (i = 0; i < height; i++) {
2114 row_ptrs[i] = raw_image + i * row_size;
2117 png_read_image(png_ptr, &row_ptrs[0]);
2119 return (DataHandle) { raw_image, data_length };
2121static void read_png_data_callback(
2122 png_structp png_ptr, png_byte* raw_data, png_size_t read_length) {
2123 ReadDataHandle* handle = png_get_io_ptr(png_ptr);
2124 const png_byte* png_src = handle->data.data + handle->offset;
2126 memcpy(raw_data, png_src, read_length);
2127 handle->offset += read_length;
2130TACTIC_FROM_FILE = 1,
2131TACTIC_FROM_BLOB = 2,
2133static int loadImageTexture_png(textureTableIndexStruct_s* this_tex,
char *filename) {
2137 unsigned char *image_data = 0;
2138 int image_data_isMalloced;
2142 unsigned long image_width = 0;
2143 unsigned long image_height = 0;
2144 unsigned long image_rowbytes = 0;
2145 int image_channels = 0;
2146 int glcolortype = 0;
2147 double display_exponent = 0.0;
2153 tactic= TACTIC_FROM_BLOB;
2156 png_structp png_ptr = png_create_read_struct(
2157 PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
2158 png_infop info_ptr = png_create_info_struct(png_ptr);
2161 if(tactic == TACTIC_FROM_FILE){
2164 fp = fopen(filename,
"rb");
2165 rvt=fread(header, 1, 8, fp);
2166 is_png = !png_sig_cmp(png_data, 0, 8);
2172 fp = fopen(filename,
"rb");
2173 png_init_io(png_ptr, fp);
2174 }
else if(tactic == TACTIC_FROM_BLOB){
2175 if (!load_file_blob(filename, &png_data, &png_data_size)) {
2178 is_png = !png_sig_cmp(png_data, 0, 8);
2183 ReadDataHandle png_data_handle = (ReadDataHandle) { {png_data, png_data_size}, 0 };
2184 png_set_read_fn(png_ptr, &png_data_handle, read_png_data_callback);
2187 if (setjmp(png_jmpbuf(png_ptr)))
2189 png_destroy_read_struct(&png_ptr, &info_ptr,
2191 if (tactic == TACTIC_FROM_FILE) fclose(fp);
2199 const PngInfo png_info = read_and_update_info(png_ptr, info_ptr);
2200 const DataHandle raw_image = read_entire_png_image(
2201 png_ptr, info_ptr, png_info.height);
2203 png_read_end(png_ptr, info_ptr);
2204 this_tex->x = png_info.width;
2205 this_tex->y = png_info.height;
2217 switch (png_info.color_type) {
2218 case PNG_COLOR_TYPE_GRAY: image_channels = 1;
break;
2219 case PNG_COLOR_TYPE_GRAY_ALPHA: image_channels = 2;
break;
2220 case PNG_COLOR_TYPE_RGB: image_channels = 3;
break;
2221 case PNG_COLOR_TYPE_RGB_ALPHA: image_channels = 4;
break;
2225 this_tex->channels = image_channels;
2226 this_tex->hasAlpha = this_tex->channels == 2 || this_tex->channels == 4;
2228 image_data = raw_image.data;
2230 image_data_isMalloced = 0;
2231 if(image_channels < 4){
2232 image_data = expandto4bpp(image_data, this_tex->y, this_tex->x, image_channels);
2233 image_data_isMalloced = 1;
2236 unsigned char *dataflipped = flipImageVerticallyB(image_data, this_tex->y, this_tex->x, bpp);
2237 free(raw_image.data);
2238 if(image_data_isMalloced) free(image_data);
2239 this_tex->frames = 1;
2240 this_tex->texdata = dataflipped;
2241 this_tex->filename = filename;
2242 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2247 if (tactic == TACTIC_FROM_FILE) fclose(fp);
2253#define HAVE_LIBGIF_H 1
2258int getTransparentColor(GifFileType * file)
2262 ExtensionBlock * ext = file->SavedImages[0].ExtensionBlocks;
2264 for (i = 0; i < file->SavedImages[0].ExtensionBlockCount; i++, ext++) {
2266 if (ext->Function == GRAPHICS_EXT_FUNC_CODE) {
2267 if (ext->Bytes[0] & 1)
2268 return ext->Bytes[3];
2278#define GIF_SUCCESS 0
2280static int loadImageTexture_gif(textureTableIndexStruct_s* this_tex,
char *filename) {
2283 int ErrorCode, alpha, iret;
2285 InterlacedOffset[] = { 0, 4, 2, 1 },
2286 InterlacedJumps[] = { 8, 8, 4, 2 };
2287 ColorMapObject *ColorMap;
2288 GifRowType *ScreenBuffer;
2291 GifFileType *GifFile = DGifOpenFileName(filename, &ErrorCode);
2295 if (GifFile->SHeight == 0 || GifFile->SWidth == 0) {
2299 ErrorCode = DGifSlurp(GifFile);
2300 if(ErrorCode != GIF_OK)
2302 alpha = getTransparentColor(GifFile);
2304 ColorMap = (GifFile->Image.ColorMap
2305 ? GifFile->Image.ColorMap
2306 : GifFile->SColorMap);
2307 if (ColorMap == NULL) {
2311 if(GifFile->ImageCount){
2312 unsigned char *pixel;
2313 int i,j,ipix,icolor;
2315 unsigned char * raw = GifFile->SavedImages[0].RasterBits;
2316 int width = GifFile->SavedImages[0].ImageDesc.Width;
2317 int height = GifFile->SavedImages[0].ImageDesc.Height;
2318 GifColorType *Colors = ColorMap->Colors;
2319 unsigned char *
rgba = MALLOCV(width * height * 4);
2320 GifColorType *color;
2322 for(i=0;i<height;i++){
2323 for(j=0;j<width;j++){
2325 pixel = &
rgba[ipix*4];
2327 color = &Colors[icolor];
2328 pixel[0] = color->Red;
2329 pixel[1] = color->Green;
2330 pixel[2] = color->Blue;
2331 pixel[3] = icolor == alpha ? 0 : 255;
2334 this_tex->x = width;
2335 this_tex->y = height;
2336 this_tex->hasAlpha = alpha > -1 ? 1 : 0;
2337 this_tex->channels = 3 + this_tex->hasAlpha;
2338 this_tex->frames = 1;
2340 char *dataflipped = flipImageVerticallyB(
rgba, this_tex->y, this_tex->x, bpp);
2342 this_tex->texdata = dataflipped;
2343 this_tex->filename = filename;
2353static void __reallyloadImageTexture(textureTableIndexStruct_s* this_tex,
char *filename) {
2365 FILE* fp = fopen(filename,
"rb");
2366 rvt=fread(header,20,1,fp);
2370 if(!strncmp(&header[1],
"PNG",3))
2371 loadImageTexture_png(this_tex, filename);
2373#ifdef HAVE_LIBJPEG_H
2374 if(!strncmp(header,
"ÿØÿ",3))
2375 loadImageTexture_jpeg(this_tex, filename);
2378 if(!strncmp(header,
"GIF",3))
2379 loadImageTexture_gif(this_tex, filename);
2387#define STB_IMAGE_IMPLEMENTATION
2388#include "stb_image.h"
2389int textureIsDDS(textureTableIndexStruct_s* this_tex,
char *filename);
2390int texture_load_from_buffer(textureTableIndexStruct_s* this_tex,
char* buffer,
int len) {
2396 int x, y, nchannels;
2397 imtype = sniffImageHeader(buffer);
2402 case IMAGETYPE_JPEG:
2404 stbi_set_flip_vertically_on_load(TRUE);
2405 data = stbi_load_from_memory(buffer, len, &x, &y, &nchannels, 4);
2408 this_tex->channels = nchannels;
2411 this_tex->frames = 1;
2412 this_tex->texdata = data;
2413 this_tex->hasAlpha = nchannels == 2 || nchannels == 4 ? 1 : 0;
2414 this_tex->status = TEX_NEEDSBINDING;
2438 case IMAGETYPE_UNKNOWN:
2451int texture_load_from_file(textureTableIndexStruct_s* this_tex,
char *filename)
2456#if defined(ANDROIDNDK)
2458 char * fname = STRDUP(filename);
2459 imtype = sniffImageFileHeader(fname);
2464 #ifdef HAVE_LIBPNG_H
2465 ret = loadImageTexture_png(this_tex, filename);
2468 case IMAGETYPE_JPEG:
2469 #ifdef HAVE_LIBJPEG_H
2470 ret = loadImageTexture_jpeg(this_tex, filename);
2474 #ifdef HAVE_LIBGIF_H
2475 ret = loadImageTexture_gif(this_tex, filename);
2479 ret = textureIsDDS(this_tex, fname);
break;
2480 case IMAGETYPE_WEB3DIT:
2481 ret = loadImage_web3dit(this_tex,fname);
break;
2482 case IMAGETYPE_NRRD:
2483 ret = loadImage_nrrd(this_tex,fname);
2486 ret = loadImage3DVol(this_tex, fname);
break;
2487 case IMAGETYPE_UNKNOWN:
2523 return this_tex->frames;
2529#if defined(_ANDROID)
2530 unsigned char *image = NULL;
2531 unsigned char *imagePtr;
2534 openned_file_t *myFile = load_file (filename);
2535 bool result = FALSE;
2537 if (myFile->fileData == NULL) {
2548 this_tex->texdata = flipImageVertically(myFile->fileData, myFile->imageHeight, myFile->imageWidth);
2550 this_tex->filename = filename;
2551 this_tex->hasAlpha = myFile->imageAlpha;
2552 this_tex->channels = 4;
2553 this_tex->frames = 1;
2554 this_tex->x = myFile->imageWidth;
2555 this_tex->y = myFile->imageHeight;
2558#ifdef FRONTEND_GETS_FILES
2559 close_openned_file(myFile);
2569#if defined (_MSC_VER)
2573 fname = STRDUP(filename);
2574 imtype = sniffImageFileHeader(fname);
2579 case IMAGETYPE_JPEG:
2581 ret = loadImage(this_tex, fname);
2582 #ifndef GL_ES_VERSION_2_0
2583 texture_swap_B_R(this_tex);
2587 if(imtype == IMAGETYPE_JPEG){
2590 nchan = sniffImageChannels_bruteForce(this_tex->texdata, this_tex->x, this_tex->y);
2592 if(nchan > -1) this_tex->channels = nchan;
2596 ret = textureIsDDS(this_tex, fname);
break;
2597 case IMAGETYPE_WEB3DIT:
2598 ret = loadImage_web3dit(this_tex,fname);
break;
2599 case IMAGETYPE_NRRD:
2600 ret = loadImage_nrrd(this_tex,fname);
break;
2602 ret = loadImage3DVol(this_tex, fname);
break;
2603 case IMAGETYPE_UNKNOWN:
2616#if !defined (_MSC_VER) && !defined(_ANDROID) && !defined(ANDROIDNDK)
2619 Imlib_Load_Error error_return;
2623 fname = STRDUP(filename);
2624 imtype = sniffImageFileHeader(fname);
2629 ret = textureIsDDS(this_tex, fname);
break;
2630 case IMAGETYPE_WEB3DIT:
2631 ret = loadImage_web3dit(this_tex,fname);
break;
2632 case IMAGETYPE_NRRD:
2633 ret = loadImage_nrrd(this_tex,fname);
break;
2635 ret = loadImage3DVol(this_tex, fname);
break;
2637 case IMAGETYPE_JPEG:
2639 case IMAGETYPE_UNKNOWN:
2644 image = imlib_load_image_with_error_return(filename,&error_return);
2645 ret = (error_return == 0);
2649 switch(error_return){
2650 case IMLIB_LOAD_ERROR_NONE: es =
"IMLIB_LOAD_ERROR_NONE";
break;
2651 case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST: es =
"IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST";
break;
2652 case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY: es =
"IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY";
break;
2653 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ: es =
"IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ";
break;
2654 case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT: es =
"IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT";
break;
2655 case IMLIB_LOAD_ERROR_PATH_TOO_LONG: es =
"IMLIB_LOAD_ERROR_PATH_TOO_LONG";
break;
2656 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT: es =
"IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT";
break;
2657 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY: es =
"IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY";
break;
2658 case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE: es =
"IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE";
break;
2659 case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS: es =
"IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS";
break;
2660 case IMLIB_LOAD_ERROR_OUT_OF_MEMORY: es =
"IMLIB_LOAD_ERROR_OUT_OF_MEMORY";
break;
2661 case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS: es =
"IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS";
break;
2662 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE: es =
"IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE";
break;
2663 case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE: es =
"IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE";
break;
2664 case IMLIB_LOAD_ERROR_UNKNOWN:
2666 es =
"IMLIB_LOAD_ERROR_UNKNOWN";
break;
2668 ERROR_MSG(
"imlib load error = %d %s\n",error_return,es);
2669 ERROR_MSG(
"load_texture_from_file: failed to load image: %s\n", filename);
2672 DEBUG_TEX(
"load_texture_from_file: Imlib2 succeeded to load image: %s\n", filename);
2674 imlib_context_set_image(image);
2675 imlib_image_flip_vertical();
2678 this_tex->filename = filename;
2679 this_tex->hasAlpha = (imlib_image_has_alpha() == 1);
2680 this_tex->channels = this_tex->hasAlpha ? 4 : 3;
2681 this_tex->frames = 1;
2682 this_tex->x = imlib_image_get_width();
2683 this_tex->y = imlib_image_get_height();
2685 this_tex->texdata = (
unsigned char *) imlib_image_get_data_for_reading_only();
2689 if(imtype == IMAGETYPE_JPEG)
2692 nchan = sniffImageChannels_bruteForce(this_tex->texdata, this_tex->x, this_tex->y);
2694 if(nchan > -1) this_tex->channels = nchan;
2697 texture_swap_B_R(this_tex);
2719static bool texture_process_entry(textureTableIndexStruct_s *entry)
2721 resource_item_t *res;
2722 resource_type_t restype;
2724 resource_item_t *parentPath = NULL;
2726 DEBUG_TEX(
"textureThread - working on %p (%s)\n"
2727 "which is node %p, nodeType %d status %s, opengltex %u, and frames %d\n",
2728 entry, entry->filename, entry->scenegraphNode, entry->nodeType,
2729 texst(entry->status), entry->OpenGLTexture,
2732 entry->status = TEX_LOADING;
2737 if (!checkNode(entry->scenegraphNode,__FILE__,__LINE__)) {
2738 ConsoleMessage (
"node for texture just deleted...\n");
2743 switch (entry->nodeType) {
2745 case NODE_PixelTexture:
2746 texture_load_from_pixelTexture(entry,(
struct X3D_PixelTexture *)entry->scenegraphNode);
2750 case NODE_GeneratedTexture:
2757 case NODE_PixelTexture3D:
2758 texture_load_from_pixelTexture3D(entry,(
struct X3D_PixelTexture3D *)entry->scenegraphNode);
2763 case NODE_ImageTexture:
2765 parentPath = (resource_item_t *)(((
struct X3D_ImageTexture *)entry->scenegraphNode)->_parentResource);
2766 restype = resm_image;
2769 case NODE_BufferTexture:
2770 restype = resm_image_buffer;
2772 if (tr && tr->buffer->loaded) {
2773 char *address = tr->buffer->address + tr->byteOffset;
2774 int len = tr->byteSize;
2775 texture_load_from_buffer(entry, address, len);
2782 case NODE_ImageTexture3D:
2784 parentPath = (resource_item_t *)(((
struct X3D_ImageTexture3D *)entry->scenegraphNode)->_parentResource);
2785 restype = resm_image;
2788 case NODE_ComposedTexture3D:
2793 case NODE_MovieTexture:
2795 parentPath = (resource_item_t *)(((
struct X3D_MovieTexture *)entry->scenegraphNode)->_parentResource);
2796 entry->status = TEX_NEEDSBINDING;
2797 restype = resm_movie;
2800 case NODE_ImageCubeMapTexture:
2803 restype = resm_image;
2807 printf (
"invalid nodetype given to loadTexture, %s is not valid\n",stringNodeType(entry->nodeType));
2810 entry->status = TEX_NOTFOUND;
2815 res = resource_create_multi(url);
2816 res->type = rest_multi;
2817 res->media_type = restype;
2818 resource_identify(parentPath, res);
2819 res->whereToPlaceData = entry;
2820 res->textureNumber = entry->textureNumber;
2821 resitem_enqueue(ml_new(res));
2847static void texture_process_list_item(s_list_t *item)
2849 bool remove_it = FALSE;
2850 textureTableIndexStruct_s *entry;
2853 if (!item || !item->elem)
2856 entry = ml_elem(item);
2858 DEBUG_TEX(
"texture_process_list: %s\n", entry->filename);
2862 switch (entry->status) {
2866 if (texture_process_entry(entry)) {
2877 entry->status = TEX_NEEDSBINDING;
2895void threadsafe_enqueue_item_signal(s_list_t *item, s_list_t** queue, pthread_mutex_t* queue_lock, pthread_cond_t *queue_nonzero);
2896s_list_t* threadsafe_dequeue_item_wait(s_list_t** queue, pthread_mutex_t *queue_lock, pthread_cond_t *queue_nonzero, BOOL* wait);
2898void texitem_enqueue(s_list_t *item){
2900 ttglobal tg = gglobal();
2901 p = (ppLoadTextures)gglobal()->LoadTextures.prv;
2903 threadsafe_enqueue_item_signal(item, &p->texture_request_list, &tg->threads.mutex_texture_list, &tg->threads.texture_list_condition);
2905s_list_t *texitem_dequeue(){
2907 ttglobal tg = gglobal();
2908 p = (ppLoadTextures)gglobal()->LoadTextures.prv;
2910 return threadsafe_dequeue_item_wait(&p->texture_request_list, &tg->threads.mutex_texture_list, &tg->threads.texture_list_condition, &tg->threads.TextureThreadWaiting);
2913static const int tex_command_exit;
2915void texitem_queue_exit(){
2916 texitem_enqueue(ml_new(&tex_command_exit));
2919void send_texture_to_loader(textureTableIndexStruct_s *entry)
2921 texitem_enqueue(ml_new(entry));
2923textureTableIndexStruct_s *getTableIndex(
int i);
2924void process_res_texitem(resource_item_t *res){
2926 textureTableIndexStruct_s *entry;
2928 textureNumber = res->textureNumber;
2931 entry = getTableIndex(textureNumber);
2933 texitem_enqueue(ml_new(entry));
2941#if !defined(HAVE_PTHREAD_CANCEL)
2942void Texture_thread_exit_handler(
int sig)
2944 ConsoleMessage(
"Texture_thread_exit_handler: No pTheadCancel - textureThread exiting - maybe should cleanup? Should be done but need to check some rainy day");
2951void _textureThread(
void *globalcontext)
2953 ttglobal tg = (ttglobal)globalcontext;
2954 tg->threads.loadThread = pthread_self();
2955 fwl_setCurrentHandle(tg, __FILE__, __LINE__);
2960 p = (ppLoadTextures)tg->LoadTextures.prv;
2963 tg->threads.TextureThreadRunning = TRUE;
2968 s_list_t *item = texitem_dequeue();
2969 elem = ml_elem(item);
2971 if (elem == &tex_command_exit){
2975 if (tg->threads.flushing){
2979 p->TextureParsing = TRUE;
2980 texture_process_list_item(item);
2981 p->TextureParsing = FALSE;
2984 printf(
"Ending texture load thread gracefully\n");
2985 tg->threads.TextureThreadRunning = FALSE;