]> git.mxchange.org Git - simgear.git/blob - simgear/screen/texture.cxx
Add a function to calculate the normalmap from a regular texture.
[simgear.git] / simgear / screen / texture.cxx
1 /*
2  * Texture manipulation routines
3  *
4  * Copyright (c) Mark J. Kilgard, 1997.
5  * Code added in april 2003 by Erik Hofman
6  *
7  * This program is freely distributable without licensing fees 
8  * and is provided without guarantee or warrantee expressed or 
9  * implied. This program is -not- in the public domain.
10  *
11  * $Id$
12  */
13
14 #include <simgear/compiler.h>
15
16 #ifdef WIN32
17 # include <windows.h>
18 #endif
19
20 #include SG_GLU_H
21
22 #include <zlib.h>
23
24 #include "texture.hxx"
25 #include "colours.h"
26
27
28 const char *FILE_OPEN_ERROR = "Unable to open file.";
29 const char *WRONG_COUNT = "Unsupported number of color channels.";
30 const char *NO_TEXTURE = "No texture data resident.";
31 const char *OUT_OF_MEMORY = "Out of memory.";
32
33
34 SGTexture::SGTexture()
35    : texture_id(0),
36      texture_data(0),
37      num_colors(3),
38      file(0)
39 {
40 }
41
42 SGTexture::SGTexture(unsigned int width, unsigned int height)
43    : texture_id(0),
44      errstr("")
45 {
46     texture_data = new GLubyte[ width * height * 3 ];
47 }
48
49 SGTexture::~SGTexture()
50 {
51     if ( texture_data ) {
52         delete texture_data;
53     }
54
55     if ( texture_id != 0 ) {
56         free_id();
57     }
58 }
59
60 void
61 SGTexture::bind()
62 {
63     bool gen = false;
64     if (!texture_id) {
65 #ifdef GL_VERSION_1_1
66         glGenTextures(1, &texture_id);
67
68 #elif GL_EXT_texture_object
69         glGenTexturesEXT(1, &texture_id);
70 #endif
71         gen = true;
72     }
73
74 #ifdef GL_VERSION_1_1
75     glBindTexture(GL_TEXTURE_2D, texture_id);
76
77 #elif GL_EXT_texture_object
78     glBindTextureEXT(GL_TEXTURE_2D, texture_id);
79 #endif
80
81     if (gen) {
82         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
83         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
84         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
85         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
86     }
87 }
88
89 /**
90  * A function to resize the OpenGL window which will be used by
91  * the dynamic texture generating routines.
92  *
93  * @param width The width of the new window
94  * @param height The height of the new window
95  */
96 void
97 SGTexture::resize(unsigned int width, unsigned int height)
98 {
99     GLfloat aspect;
100
101     // Make sure that we don't get a divide by zero exception
102     if (height == 0)
103         height = 1;
104
105     // Set the viewport for the OpenGL window
106     glViewport(0, 0, width, height);
107
108     // Calculate the aspect ratio of the window
109     aspect = width/height;
110
111     // Go to the projection matrix, this gets modified by the perspective
112     // calulations
113     glMatrixMode(GL_PROJECTION);
114     glLoadIdentity();
115
116     // Do the perspective calculations
117     gluPerspective(45.0, aspect, 1.0, 400.0);
118
119     // Return to the modelview matrix
120     glMatrixMode(GL_MODELVIEW);
121 }
122
123 /**
124  * A function to prepare the OpenGL state machine for dynamic
125  * texture generation.
126  *
127  * @param width The width of the texture
128  * @param height The height of the texture
129  */
130 void
131 SGTexture::prepare(unsigned int width, unsigned int height) {
132
133     texture_width = width;
134     texture_height = height;
135
136     // Resize the OpenGL window to the size of our dynamic texture
137     resize(texture_width, texture_height);
138
139     glClearColor(0.0, 0.0, 0.0, 1.0);
140 }
141
142 /**
143  * A function to generate the dynamic texture.
144  *
145  * The actual texture can be accessed by calling get_texture()
146  *
147  * @param width The width of the previous OpenGL window
148  * @param height The height of the previous OpenGL window
149  */
150 void
151 SGTexture::finish(unsigned int width, unsigned int height) {
152     // If a texture hasn't been created then it gets created, and the contents
153     // of the frame buffer gets copied into it. If the texture has already been
154     // created then its contents just get updated.
155     bind();
156     if (!texture_data)
157     {
158       // Copies the contents of the frame buffer into the texture
159       glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0,
160                                       texture_width, texture_height, 0);
161
162     } else {
163       // Copies the contents of the frame buffer into the texture
164       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
165                                          texture_width, texture_height);
166     }
167
168     // Set the OpenGL window back to its previous size
169     resize(width, height);
170
171     // Clear the window back to black
172     glClearColor(0.0, 0.0, 0.0, 1.0);
173     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
174 }
175
176
177 void
178 SGTexture::read_alpha_texture(const char *name)
179 {
180     GLubyte *lptr;
181     SGTexture::ImageRec *image;
182     int y;
183
184     if (texture_data)
185         delete texture_data;
186
187     image = ImageOpen(name);
188     if(!image) {
189         errstr = FILE_OPEN_ERROR;
190         return;
191     }
192
193     texture_width = image->xsize;
194     texture_height = image->ysize;
195
196     // printf("image->zsize = %d\n", image->zsize);
197
198     if (image->zsize != 1) {
199       ImageClose(image);
200       errstr = WRONG_COUNT;
201       return;
202     }
203
204     texture_data = new GLubyte[ image->xsize * image->ysize ];
205     num_colors = 1;
206     if (!texture_data) {
207         errstr = NO_TEXTURE;
208         return;
209     }
210
211     lptr = texture_data;
212     for(y=0; y<image->ysize; y++) {
213         ImageGetRow(image,lptr,y,0);
214         lptr += image->xsize;
215     }
216     ImageClose(image);
217 }
218
219 void
220 SGTexture::read_rgb_texture(const char *name)
221 {
222     GLubyte *ptr;
223     GLubyte *rbuf, *gbuf, *bbuf, *abuf;
224     SGTexture::ImageRec *image;
225     int y;
226
227     if (texture_data)
228         delete texture_data;
229
230     image = ImageOpen(name);
231     if(!image) {
232         errstr = FILE_OPEN_ERROR;
233         return;
234     }
235
236     texture_width = image->xsize;
237     texture_height = image->ysize;
238     if (image->zsize != 3 && image->zsize != 4) {
239       ImageClose(image);
240       errstr = WRONG_COUNT;
241       return;
242     }
243
244     texture_data = new GLubyte[ image->xsize * image->ysize * 3 ];
245     num_colors = 3;
246     rbuf = new GLubyte[ image->xsize ];
247     gbuf = new GLubyte[ image->xsize ];
248     bbuf = new GLubyte[ image->xsize ];
249     abuf = new GLubyte[ image->xsize ];
250     if(!texture_data || !rbuf || !gbuf || !bbuf || !abuf) {
251       delete texture_data;
252       delete rbuf;
253       delete gbuf;
254       delete bbuf;
255       delete abuf;
256       errstr = OUT_OF_MEMORY;
257       return;
258     }
259
260     ptr = texture_data;
261     for(y=0; y<image->ysize; y++) {
262         if(image->zsize == 4) {
263             ImageGetRow(image,rbuf,y,0);
264             ImageGetRow(image,gbuf,y,1);
265             ImageGetRow(image,bbuf,y,2);
266             ImageGetRow(image,abuf,y,3); // discard
267             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
268             ptr += (image->xsize * 3);
269         } else {
270             ImageGetRow(image,rbuf,y,0);
271             ImageGetRow(image,gbuf,y,1);
272             ImageGetRow(image,bbuf,y,2);
273             rgbtorgb(rbuf,gbuf,bbuf,ptr,image->xsize);
274             ptr += (image->xsize * 3);
275         }
276     }
277
278     ImageClose(image);
279     delete rbuf;
280     delete gbuf;
281     delete bbuf;
282     delete abuf;
283 }
284
285
286
287 void
288 SGTexture::read_rgba_texture(const char *name)
289 {
290     GLubyte *ptr;
291     GLubyte *rbuf, *gbuf, *bbuf, *abuf;
292     SGTexture::ImageRec *image;
293     int y;
294
295     if (texture_data)
296         delete texture_data;
297
298     image = ImageOpen(name);
299     if(!image) {
300         errstr = FILE_OPEN_ERROR;
301         return;
302     }
303
304     texture_width = image->xsize;
305     texture_height = image->ysize;
306     if (image->zsize != 3 && image->zsize != 4) {
307       ImageClose(image);
308       errstr = WRONG_COUNT;
309       return;
310     }
311
312     texture_data = new GLubyte[ image->xsize * image->ysize * 4 ];
313     num_colors = 4;
314     rbuf = new GLubyte[ image->xsize ];
315     gbuf = new GLubyte[ image->xsize ];
316     bbuf = new GLubyte[ image->xsize ];
317     abuf = new GLubyte[ image->xsize ];
318     if(!texture_data || !rbuf || !gbuf || !bbuf || !abuf) {
319       delete texture_data;
320       delete rbuf;
321       delete gbuf;
322       delete bbuf;
323       delete abuf;
324       errstr = OUT_OF_MEMORY;
325       return;
326     }
327
328     ptr = texture_data;
329     memset(abuf, 255, image->xsize);
330     for(y=0; y<image->ysize; y++) {
331         if(image->zsize == 4) {
332             ImageGetRow(image,rbuf,y,0);
333             ImageGetRow(image,gbuf,y,1);
334             ImageGetRow(image,bbuf,y,2);
335             ImageGetRow(image,abuf,y,3);
336             rgbatorgba(rbuf,gbuf,bbuf,abuf,ptr,image->xsize);
337             ptr += (image->xsize * 4);
338         } else {
339             ImageGetRow(image,rbuf,y,0);
340             ImageGetRow(image,gbuf,y,1);
341             ImageGetRow(image,bbuf,y,2);
342             rgbatorgba(rbuf,gbuf,bbuf,abuf,ptr,image->xsize);
343             ptr += (image->xsize * 3);
344         }
345     }
346
347     ImageClose(image);
348     delete rbuf;
349     delete gbuf;
350     delete bbuf;
351     delete abuf;
352 }
353
354 void
355 SGTexture::read_raw_texture(const char *name)
356 {
357     GLubyte *ptr;
358     SGTexture::ImageRec *image;
359     int y;
360
361     if (texture_data)
362         delete texture_data;
363
364     image = RawImageOpen(name);
365
366     if(!image) {
367         errstr = FILE_OPEN_ERROR;
368         return;
369     }
370
371     texture_width = 256;
372     texture_height = 256;
373
374     texture_data = new GLubyte[ 256 * 256 * 3 ];
375     if(!texture_data) {
376       errstr = OUT_OF_MEMORY;
377       return;
378     }
379
380     ptr = texture_data;
381     for(y=0; y<256; y++) {
382         gzread(image->file, ptr, 256*3);
383         ptr+=256*3;
384     }
385     ImageClose(image);
386 }
387
388 void
389 SGTexture::read_r8_texture(const char *name)
390 {
391     unsigned char c[1];
392     GLubyte *ptr;
393     SGTexture::ImageRec *image;
394     int xy;
395
396     if (texture_data)
397         delete texture_data;
398
399     //it wouldn't make sense to write a new function ...
400     image = RawImageOpen(name);
401
402     if(!image) {
403         errstr = FILE_OPEN_ERROR;
404         return;
405     }
406
407     texture_width = 256;
408     texture_height = 256;
409
410     texture_data = new GLubyte [ 256 * 256 * 3 ];
411     if(!texture_data) {
412         errstr = OUT_OF_MEMORY;
413         return;
414     }
415
416     ptr = texture_data;
417     for(xy=0; xy<(256*256); xy++) {
418         gzread(image->file, c, 1);
419
420         //look in the table for the right colours
421         ptr[0]=msfs_colour[c[0]][0];
422         ptr[1]=msfs_colour[c[0]][1];
423         ptr[2]=msfs_colour[c[0]][2];
424
425         ptr+=3;
426     }
427     ImageClose(image);
428 }
429
430
431 void
432 SGTexture::write_texture(const char *name) {
433    SGTexture::ImageRec *image = ImageWriteOpen(name);
434
435    for (int c=0; c<num_colors; c++) {
436       GLubyte *ptr = texture_data + c;
437       for (int y=0; y<texture_height; y++) {
438          for (int x=0; x<texture_width; x++) {
439             image->tmp[x]=*ptr;
440             ptr = ptr + num_colors;
441          }
442          fwrite(image->tmp, 1, texture_width, file);
443       }
444    }
445
446    ImageClose(image);
447 }
448
449
450 void
451 SGTexture::set_pixel(GLuint x, GLuint y, GLubyte *c)
452 {
453     if (!texture_data) {
454         errstr = NO_TEXTURE;
455         return;
456     }
457
458     unsigned int pos = (x + y*texture_width) * num_colors;
459     memcpy(texture_data+pos, c, num_colors);
460 }
461
462
463 GLubyte *
464 SGTexture::get_pixel(GLuint x, GLuint y)
465 {
466     static GLubyte c[4] = {0, 0, 0, 0};
467
468     if (!texture_data) {
469         errstr = NO_TEXTURE;
470         return c;
471     }
472
473     unsigned int pos = (x + y*texture_width)*num_colors;
474     memcpy(c, texture_data + pos, num_colors);
475
476     return c;
477 }
478
479 SGTexture::ImageRec *
480 SGTexture::ImageOpen(const char *fileName)
481 {
482      union {
483        int testWord;
484        char testByte[4];
485      } endianTest;
486
487     SGTexture::ImageRec *image;
488     int swapFlag;
489     int x;
490
491     endianTest.testWord = 1;
492     if (endianTest.testByte[0] == 1) {
493         swapFlag = 1;
494     } else {
495         swapFlag = 0;
496     }
497
498     image = new SGTexture::ImageRec;
499     memset(image, 0, sizeof(SGTexture::ImageRec));
500     if (image == 0) {
501         errstr = OUT_OF_MEMORY;
502         return 0;
503     }
504     if ((image->file = gzopen(fileName, "rb")) == 0) {
505       errstr = FILE_OPEN_ERROR;
506       return 0;
507     }
508
509     gzread(image->file, image, 12);
510
511     if (swapFlag) {
512         ConvertShort(&image->imagic, 6);
513     }
514
515     image->tmp = new GLubyte[ image->xsize * 256 ];
516     if (image->tmp == 0) {
517         errstr = OUT_OF_MEMORY;
518         return 0;
519     }
520
521     if ((image->type & 0xFF00) == 0x0100) {
522         x = image->ysize * image->zsize * (int) sizeof(unsigned);
523         image->rowStart = new unsigned[x];
524         image->rowSize = new int[x];
525         if (image->rowStart == 0 || image->rowSize == 0) {
526             errstr = OUT_OF_MEMORY;
527             return 0;
528         }
529         image->rleEnd = 512 + (2 * x);
530         gzseek(image->file, 512, SEEK_SET);
531         gzread(image->file, image->rowStart, x);
532         gzread(image->file, image->rowSize, x);
533         if (swapFlag) {
534             ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
535             ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
536         }
537     }
538     return image;
539 }
540
541
542 void
543 SGTexture::ImageClose(SGTexture::ImageRec *image) {
544     if (image->file)  gzclose(image->file);
545     if (file) fclose(file);
546     delete image->tmp;
547     delete image;
548 }
549
550 SGTexture::ImageRec *
551 SGTexture::RawImageOpen(const char *fileName)
552 {
553      union {
554        int testWord;
555        char testByte[4];
556      } endianTest;
557
558     SGTexture::ImageRec *image;
559     int swapFlag;
560
561     endianTest.testWord = 1;
562     if (endianTest.testByte[0] == 1) {
563         swapFlag = 1;
564     } else {
565         swapFlag = 0;
566     }
567
568     image = new SGTexture::ImageRec;
569     memset(image, 0, sizeof(SGTexture::ImageRec));
570     if (image == 0) {
571         errstr = OUT_OF_MEMORY;
572         return 0;
573     }
574     if ((image->file = gzopen(fileName, "rb")) == 0) {
575       errstr = FILE_OPEN_ERROR;
576       return 0;
577     }
578
579     gzread(image->file, image, 12);
580
581     if (swapFlag) {
582         ConvertShort(&image->imagic, 6);
583     }
584
585
586     //just allocate a pseudo value as I'm too lazy to change ImageClose()...
587     image->tmp = new GLubyte;
588
589     if (image->tmp == 0) {
590         errstr = OUT_OF_MEMORY;
591         return 0;
592     }
593
594     return image;
595 }
596
597 SGTexture::ImageRec *
598 SGTexture::ImageWriteOpen(const char *fileName)
599 {
600     union {
601         int testWord;
602         char testByte[4];
603     } endianTest;
604     ImageRec* image;
605     int swapFlag;
606     int x;
607
608     endianTest.testWord = 1;
609     if (endianTest.testByte[0] == 1) {
610         swapFlag = 1;
611     } else {
612         swapFlag = 0;
613     }
614
615     image = new SGTexture::ImageRec;
616     memset(image, 0, sizeof(SGTexture::ImageRec));
617     if (image == 0) {
618         errstr = OUT_OF_MEMORY;
619         return 0;
620     }
621     if ((file = fopen(fileName, "wb")) == 0) {
622         errstr = FILE_OPEN_ERROR;
623         return 0;
624     }
625
626     image->imagic = 474;
627     image->type = 0x0001;
628     image->dim = (num_colors > 1) ? 3 : 2;
629     image->xsize = texture_width;
630     image->ysize = texture_height;
631     image->zsize = num_colors;
632
633     fwrite(image, 1, 12, file);
634
635     fseek(file, 512, SEEK_SET);
636
637     if (swapFlag) {
638         ConvertShort(&image->imagic, 6);
639     }
640
641     image->tmp = new GLubyte[ image->xsize * 256 ];
642     if (image->tmp == 0) {
643         errstr = OUT_OF_MEMORY;
644         return 0;
645     }
646
647     if ((image->type & 0xFF00) == 0x0100) {
648         x = image->ysize * image->zsize * (int) sizeof(unsigned);
649         image->rowStart = new unsigned[x];
650         image->rowSize = new int[x];
651         if (image->rowStart == 0 || image->rowSize == 0) {
652             errstr = OUT_OF_MEMORY;
653             return 0;
654         }
655         image->rleEnd = 512 + (2 * x);
656         fseek(file, 512, SEEK_SET);
657         fwrite(image->rowStart, 1, x, file);
658         fwrite(image->rowSize, 1, x, file);
659         if (swapFlag) {
660             ConvertUint(image->rowStart, x/(int) sizeof(unsigned));
661             ConvertUint((unsigned *)image->rowSize, x/(int) sizeof(int));
662         }
663     }
664
665     return image;
666
667 }
668
669 void
670 SGTexture::ImageGetRow(SGTexture::ImageRec *image, GLubyte *buf, int y, int z) {
671     GLubyte *iPtr, *oPtr, pixel;
672     int count;
673
674     if ((image->type & 0xFF00) == 0x0100) {
675         gzseek(image->file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
676         gzread(image->file, image->tmp,
677                (unsigned int)image->rowSize[y+z*image->ysize]);
678
679         iPtr = image->tmp;
680         oPtr = buf;
681         for (;;) {
682             pixel = *iPtr++;
683             count = (int)(pixel & 0x7F);
684             if (!count) {
685                 errstr = WRONG_COUNT;
686                 return;
687             }
688             if (pixel & 0x80) {
689                 while (count--) {
690                     *oPtr++ = *iPtr++;
691                 }
692             } else {
693                 pixel = *iPtr++;
694                 while (count--) {
695                     *oPtr++ = pixel;
696                 }
697             }
698         }
699     } else {
700         gzseek(image->file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
701               SEEK_SET);
702         gzread(image->file, buf, image->xsize);
703     }
704 }
705
706 void
707 SGTexture::ImagePutRow(SGTexture::ImageRec *image, GLubyte *buf, int y, int z) {
708     GLubyte *iPtr, *oPtr, pixel;
709     int count;
710
711     if ((image->type & 0xFF00) == 0x0100) {
712         fseek(file, (long) image->rowStart[y+z*image->ysize], SEEK_SET);
713         fread( image->tmp, 1, (unsigned int)image->rowSize[y+z*image->ysize],
714                file);
715
716         iPtr = image->tmp;
717         oPtr = buf;
718         for (;;) {
719             pixel = *iPtr++;
720             count = (int)(pixel & 0x7F);
721             if (!count) {
722                 errstr = WRONG_COUNT;
723                 return;
724             }
725             if (pixel & 0x80) {
726                 while (count--) {
727                     *oPtr++ = *iPtr++;
728                 }
729             } else {
730                 pixel = *iPtr++;
731                 while (count--) {
732                     *oPtr++ = pixel;
733                 }
734             }
735         }
736     } else {
737         fseek(file, 512+(y*image->xsize)+(z*image->xsize*image->ysize),
738               SEEK_SET);
739         fread(buf, 1, image->xsize, file);
740     }
741 }
742
743
744 void
745 SGTexture::rgbtorgb(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *l, int n) {
746     while(n--) {
747         l[0] = r[0];
748         l[1] = g[0];
749         l[2] = b[0];
750         l += 3; r++; g++; b++;
751     }
752 }
753
754 void
755 SGTexture::rgbatorgba(GLubyte *r, GLubyte *g, GLubyte *b, GLubyte *a,
756                       GLubyte *l, int n) {
757     while(n--) {
758         l[0] = r[0];
759         l[1] = g[0];
760         l[2] = b[0];
761         l[3] = a[0];
762         l += 4; r++; g++; b++; a++;
763     }
764 }
765
766
767 void
768 SGTexture::ConvertShort(unsigned short *array, unsigned int length) {
769     unsigned short b1, b2;
770     unsigned char *ptr;
771
772     ptr = (unsigned char *)array;
773     while (length--) {
774         b1 = *ptr++;
775         b2 = *ptr++;
776         *array++ = (b1 << 8) | (b2);
777     }
778 }
779
780
781 void
782 SGTexture::ConvertUint(unsigned *array, unsigned int length) {
783     unsigned int b1, b2, b3, b4;
784     unsigned char *ptr;
785
786     ptr = (unsigned char *)array;
787     while (length--) {
788         b1 = *ptr++;
789         b2 = *ptr++;
790         b3 = *ptr++;
791         b4 = *ptr++;
792         *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
793     }
794 }
795
796
797 void
798 SGTexture::make_monochrome(GLubyte r, GLubyte g, GLubyte b) {
799
800    if (num_colors >= 3)
801       return;
802
803    GLubyte ap[3];
804    for (int y=0; y<texture_height; y++)
805       for (int x=0; x<texture_width; x++)
806       {
807          GLubyte *rgb = get_pixel(x,y);
808          GLubyte avg = (rgb[0] + rgb[1] + rgb[2]) / 3;
809
810          ap[0] = avg*r/255;
811          ap[1] = avg*g/255;
812          ap[2] = avg*b/255;
813
814          set_pixel(x,y,ap);
815       }
816 }
817
818 void
819 SGTexture::make_normalmap(float brightness) {
820    GLubyte *map = (GLubyte *)malloc (texture_width * texture_height * 3);
821
822    for (int y=0; y<texture_height; y++)
823       for (int x=0; x<texture_width; x++)
824       {
825          int mpos = (x + y*texture_width)*3;
826          int dpos = (x + y*texture_width)*num_colors;
827
828          int xp1 = (x < (texture_width-1)) ? x+1 : 0;
829          int yp1 = (y < (texture_height-1)) ? y+1 : 0;
830          int posxp1 = (xp1 + y*texture_width)*num_colors;
831          int posyp1 = (x + yp1*texture_width)*num_colors;
832
833          map[mpos+0] = (128+(texture_data[posxp1]-texture_data[dpos])/2);
834          map[mpos+1] = (128+(texture_data[posyp1]-texture_data[dpos])/2);
835          map[mpos+2] = 128 + GLubyte(128*brightness);
836       }
837
838    free (texture_data);
839    texture_data = map;
840    num_colors = 3;
841 }