@@ -198,15 +198,52 @@ public:
198198 Premultiplies incoming color data.
199199 */
200200 void premultiply () {
201+ final switch (format) {
202+ case TextureFormat.rgba8Unorm:
203+ ubyte [] dataView = cast (ubyte [])data;
204+ foreach (i; 0 .. data.length/ 4 ) {
205+ size_t offsetPixel = (i* 4 );
206+
207+ float r = (cast (float )dataView[offsetPixel+ 0 ]/ 255.0 ) * (cast (float )dataView[offsetPixel+ 3 ]/ 255.0 );
208+ float g = (cast (float )dataView[offsetPixel+ 1 ]/ 255.0 ) * (cast (float )dataView[offsetPixel+ 3 ]/ 255.0 );
209+ float b = (cast (float )dataView[offsetPixel+ 2 ]/ 255.0 ) * (cast (float )dataView[offsetPixel+ 3 ]/ 255.0 );
210+
211+ dataView[offsetPixel+ 0 ] = cast (ubyte )(r* 255.0 );
212+ dataView[offsetPixel+ 1 ] = cast (ubyte )(g* 255.0 );
213+ dataView[offsetPixel+ 2 ] = cast (ubyte )(b* 255.0 );
214+ }
215+ return ;
216+
217+ case TextureFormat.none:
218+ case TextureFormat.depthStencil:
219+ case TextureFormat.r8:
220+ return ;
221+ }
222+ }
223+
224+ /**
225+ Un-premultiplies incoming color data.
226+ */
227+ void unpremultiply () {
201228 final switch (format) {
202229 case TextureFormat.rgba8Unorm:
203230 ubyte [] dataView = cast (ubyte [])data;
204231 foreach (i; 0 .. data.length/ 4 ) {
205232
206233 size_t offsetPixel = (i* 4 );
207- dataView[offsetPixel+ 0 ] = cast (ubyte )((cast (int )dataView[offsetPixel+ 0 ] * cast (int )dataView[offsetPixel+ 3 ])/ 255 );
208- dataView[offsetPixel+ 1 ] = cast (ubyte )((cast (int )dataView[offsetPixel+ 1 ] * cast (int )dataView[offsetPixel+ 3 ])/ 255 );
209- dataView[offsetPixel+ 2 ] = cast (ubyte )((cast (int )dataView[offsetPixel+ 2 ] * cast (int )dataView[offsetPixel+ 3 ])/ 255 );
234+
235+ // Ensure no divide by zero happens.
236+ if (cast (float )dataView[offsetPixel+ 3 ] == 0 ) {
237+ dataView[offsetPixel.. offsetPixel+ 3 ] = 0 ;
238+ continue ;
239+ }
240+
241+ float r = (cast (float )dataView[offsetPixel+ 0 ]/ 255.0 ) / (cast (float )dataView[offsetPixel+ 3 ]/ 255.0 );
242+ float g = (cast (float )dataView[offsetPixel+ 1 ]/ 255.0 ) / (cast (float )dataView[offsetPixel+ 3 ]/ 255.0 );
243+ float b = (cast (float )dataView[offsetPixel+ 2 ]/ 255.0 ) / (cast (float )dataView[offsetPixel+ 3 ]/ 255.0 );
244+ dataView[offsetPixel+ 0 ] = cast (ubyte )(r* 255.0 );
245+ dataView[offsetPixel+ 1 ] = cast (ubyte )(g* 255.0 );
246+ dataView[offsetPixel+ 2 ] = cast (ubyte )(b* 255.0 );
210247 }
211248 return ;
212249
@@ -217,6 +254,35 @@ public:
217254 }
218255 }
219256
257+ /**
258+ Pads the texture with a 1-pixel wide border.
259+
260+ Params:
261+ thickness = The border thickness to generate.
262+ */
263+ void pad (uint thickness) {
264+ if (data.length == 0 )
265+ return ;
266+
267+ uint totalPad = thickness* 2 ;
268+ ubyte [] newData = nu_malloca! ubyte ((width+ totalPad)* (height+ totalPad)* channels);
269+ newData[0 .. $] = 0 ;
270+
271+ size_t srcStride = width* channels;
272+ size_t dstStride = (width+ totalPad)* channels;
273+ foreach (y; 0 .. height) {
274+ size_t start = (dstStride* (y+ thickness))+ (thickness* channels);
275+ size_t end = start + srcStride;
276+ newData[start.. end] = cast (ubyte [])data[srcStride* y.. (srcStride* y)+ srcStride];
277+ }
278+
279+ // Update the texture
280+ nu_freea(data);
281+ this .data = newData;
282+ this .width = width+ totalPad;
283+ this .height = height+ totalPad;
284+ }
285+
220286 /**
221287 Dumps the image data to the specified file.
222288
0 commit comments