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!2 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     ubyte[] data;
37     data.length = w * h * c;
38     
39     foreach( i, ref d; data ) d = raw[i];
40 
41     return Image!2( ivec2(w,h), DataType.UBYTE, cast(ubyte)(c), data );
42 }
43 
44 ///
45 void imSave( in Image!2 img, string fname )
46 {
47     loadIL();
48 
49     ILenum format, type;
50 
51     switch( img.info.channels )
52     {
53         case 1: format = IL_COLOUR_INDEX; break;
54         case 3: format = IL_RGB; break;
55         case 4: format = IL_RGBA; break;
56         default: throw new ImageException( "Bad image channels count for saving" );
57     }
58 
59     switch( img.info.comp )
60     {
61         case DataType.BYTE:       type = IL_BYTE;           break;
62         case DataType.UBYTE:      type = IL_UNSIGNED_BYTE;  break;
63         case DataType.SHORT:      type = IL_SHORT;          break;
64         case DataType.USHORT:     type = IL_UNSIGNED_SHORT; break;
65         case DataType.INT:        type = IL_INT;            break;
66         case DataType.UINT:       type = IL_UNSIGNED_INT;   break;
67         case DataType.FLOAT:      type = IL_FLOAT;          break;
68         case DataType.DOUBLE:     type = IL_DOUBLE;         break;
69         default:
70             throw new ImageException( "Bad image type for saving (" ~
71                     to!string(img.info.comp) ~
72                     "), please retype image" );
73     }
74 
75     ILuint im;
76     ilGenImages( 1, &im );
77     scope(exit) ilDeleteImages( 1, &im );
78     ilBindImage( im );
79 
80     if( IL_TRUE != ilTexImage( cast(uint)(img.size.w), cast(uint)(img.size.h), 
81                 1, cast(ubyte)(img.info.channels), format, type, cast(void*)img.data.ptr ) )
82         throw new ImageException( "ilTexImage fails: " ~ toDString( iluErrorString(ilGetError()) ) );
83 
84     iluFlipImage();
85     
86     import std..string;
87     if( IL_TRUE != ilSave( IL_JPG, fname.toStringz ) )
88         throw new ImageException( "ilSaveImage fails: " ~ toDString( iluErrorString(ilGetError()) ) );
89 }
90 
91 private void loadIL()
92 {
93     if( DerelictIL.isLoaded ) return;
94 
95     DerelictIL.load();
96     DerelictILU.load();
97     ilInit();
98     iluInit();
99     ilEnable( IL_FILE_OVERWRITE );
100 }