1 module des.il.io;
2 
3 import des.math.linear.vector;
4 
5 import derelict.devil.il;
6 import derelict.devil.ilu;
7 
8 public import des.il;
9 import des.util.stdext..string;
10 
11 import std..string;
12 
13 import std.conv : to;
14 
15 ///
16 Image imLoad( string fname, bool flip=true )
17 {
18     loadIL();
19 
20     ILuint im;
21     ilGenImages( 1, &im );
22     scope(exit) ilDeleteImages( 1, &im );
23     ilBindImage( im );
24 
25     if( ilLoadImage( fname.toStringz ) == false )
26         throw new ImageException( "'ilLoadImage' fails with '" ~ fname ~ "': " ~ 
27                                     toDString( iluErrorString( ilGetError() ) ) );
28 
29     int w = ilGetInteger( IL_IMAGE_WIDTH );
30     int h = ilGetInteger( IL_IMAGE_HEIGHT );
31     int c = ilGetInteger( IL_IMAGE_BYTES_PER_PIXEL );
32 
33     if( flip ) iluFlipImage();
34 
35     ubyte* raw = ilGetData();
36 
37     return Image( ivec2(w,h), cast(ubyte)(c), DataType.UBYTE, raw[0..w*h*c] );
38 }
39 
40 ///
41 void imSave( in Image img, string fname )
42 {
43     loadIL();
44 
45     ILenum format, type;
46 
47     switch( img.info.comp )
48     {
49         case 1: format = IL_COLOUR_INDEX; break;
50         case 3: format = IL_RGB; break;
51         case 4: format = IL_RGBA; break;
52         default: throw new ImageException( "Bad image channels count for saving" );
53     }
54 
55     switch( img.info.type )
56     {
57         case DataType.BYTE:       type = IL_BYTE;           break;
58         case DataType.UBYTE:      type = IL_UNSIGNED_BYTE;  break;
59         case DataType.SHORT:      type = IL_SHORT;          break;
60         case DataType.USHORT:     type = IL_UNSIGNED_SHORT; break;
61         case DataType.INT:        type = IL_INT;            break;
62         case DataType.UINT:       type = IL_UNSIGNED_INT;   break;
63         case DataType.FLOAT:      type = IL_FLOAT;          break;
64         case DataType.DOUBLE:     type = IL_DOUBLE;         break;
65         default:
66             throw new ImageException( "Bad image type for saving (" ~
67                     to!string(img.info.comp) ~
68                     "), please retype image" );
69     }
70 
71     ILuint im;
72     ilGenImages( 1, &im );
73     scope(exit) ilDeleteImages( 1, &im );
74     ilBindImage( im );
75 
76     auto size = uivec2( redimSize( 2, img.size ) );
77 
78     if( IL_TRUE != ilTexImage( size.w, size.h, 1, cast(ubyte)(img.info.comp), format, type, cast(void*)img.data.ptr ) )
79         throw new ImageException( "ilTexImage fails: " ~ toDString( iluErrorString(ilGetError()) ) );
80 
81     iluFlipImage();
82 
83     import std..string;
84     if( IL_TRUE != ilSaveImage( fname.toStringz ) )
85         throw new ImageException( "ilSaveImage fails: " ~ toDString( iluErrorString(ilGetError()) ) );
86 }
87 
88 private void loadIL()
89 {
90     if( DerelictIL.isLoaded ) return;
91 
92     DerelictIL.load();
93     DerelictILU.load();
94     ilInit();
95     iluInit();
96     ilEnable( IL_FILE_OVERWRITE );
97 }