source: golgotha/src/render/mip_average.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 15.0 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "mip_average.hh"
10#include "palette/pal.hh"
11#include "mip.hh"
12#include <string.h>
13
14void setup_pixel_formats(i4_pixel_format &reg_fmt,
15                         i4_pixel_format &chroma_fmt,
16                         i4_pixel_format &alpha_fmt,
17                         w32 chroma_color)
18{
19  //regular format setup
20  mip_b_shift = 8-reg_fmt.blue_bits; 
21  mip_b_and   = reg_fmt.blue_mask;
22
23  mip_g_shift = reg_fmt.blue_bits - (8-reg_fmt.green_bits);
24  mip_g_and   = reg_fmt.green_mask;
25
26  mip_r_shift = reg_fmt.green_bits + reg_fmt.blue_bits - (8-reg_fmt.red_bits);
27  mip_r_and   = reg_fmt.red_mask;
28
29  //chroma format setup
30  mip_c_b_shift = 8-chroma_fmt.blue_bits; 
31  mip_c_b_and   = chroma_fmt.blue_mask;
32
33  mip_c_g_shift = chroma_fmt.blue_bits - (8-chroma_fmt.green_bits);
34  mip_c_g_and   = chroma_fmt.green_mask;
35
36  mip_c_r_shift = chroma_fmt.green_bits + chroma_fmt.blue_bits - (8-chroma_fmt.red_bits);
37  mip_c_r_and   = chroma_fmt.red_mask;
38
39  mip_c_a_shift = chroma_fmt.green_bits + chroma_fmt.blue_bits + chroma_fmt.red_bits - (8-chroma_fmt.alpha_bits);
40  mip_c_a_and   = chroma_fmt.alpha_mask;
41
42  //alpha format setup
43  mip_a_b_shift = 8-alpha_fmt.blue_bits; 
44  mip_a_b_and   = alpha_fmt.blue_mask;
45
46  mip_a_g_shift = alpha_fmt.blue_bits - (8-alpha_fmt.green_bits);
47  mip_a_g_and   = alpha_fmt.green_mask;
48
49  mip_a_r_shift = alpha_fmt.green_bits + alpha_fmt.blue_bits - (8-alpha_fmt.red_bits);
50  mip_a_r_and   = alpha_fmt.red_mask;
51       
52  mip_a_a_shift = alpha_fmt.green_bits + alpha_fmt.blue_bits + alpha_fmt.red_bits - (8-alpha_fmt.alpha_bits);
53  mip_a_a_and   = alpha_fmt.alpha_mask;
54
55  //chroma key color setup
56  mip_chroma_red   = (chroma_color & 0xFF0000) >> 16;
57  mip_chroma_green = (chroma_color & 0x00FF00) >> 8;
58  mip_chroma_blue  = (chroma_color & 0x0000FF);
59}
60
61
62void r1_dos_paths(char *src)
63{
64  while (*src)
65  {
66    if (*src=='/')
67      *src='\\';
68   
69    src++;
70  }
71}
72
73void r1_unix_paths(char *src)
74
75  while (*src)
76  {
77    if (*src=='\\')
78      *src='/';
79   
80    src++;
81  }   
82}
83
84char *r1_remove_paths(char *src)
85{
86  char *ret = src;
87
88  while (*src)
89  {
90    if (*src=='/')
91      ret=src+1;
92
93    src++;   
94  }
95
96  return ret;
97}
98
99void r1_remove_extention(char *src)
100{
101  while (*src)
102  {
103    if (*src=='.')
104    {
105      *src=0;
106      return;
107    }
108    src++;
109  }
110}
111
112void concatenate_path(char *src, char *path)
113{
114  char temp[256];
115
116  char *last_path = r1_remove_paths(src);
117  strcpy(temp,last_path);
118
119  *last_path=0;
120
121  strcat(src,path);
122  strcat(src,temp);
123}
124
125void chroma_process(w8 *&p, float &r, float &g, float &b, sw8 &num_regular, sw8 &num_chroma)
126{
127  if (p[0]==mip_chroma_red && p[1]==mip_chroma_green && p[2]==mip_chroma_blue)
128  {   
129    //IS the chroma color. dont average
130    num_chroma++;
131  }
132  else
133  {
134    //not the chroma color. average as a regular pixel
135    r += (float)(p[0]);
136    g += (float)(p[1]);
137    b += (float)(p[2]);
138   
139    num_regular++;
140  }
141}
142
143void average_4x4_chroma(w16 *&dst, w8 *dst_24, w8 *&p0, w8 *p1, w8 *p2, w8 *p3)
144{
145  sw8 num_chroma  = 0;
146  sw8 num_regular = 0;
147
148  float r=0;
149  float g=0;
150  float b=0;
151
152  chroma_process(p0,r,g,b,num_regular,num_chroma);
153  chroma_process(p1,r,g,b,num_regular,num_chroma);
154  chroma_process(p2,r,g,b,num_regular,num_chroma);
155  chroma_process(p3,r,g,b,num_regular,num_chroma);
156
157  //return the chroma color
158  if (num_chroma > num_regular)
159  {
160    //alpha component and rgb component of 16-bit pixel should be entirely 0'd
161    dst_24[0] = mip_chroma_red;
162    dst_24[1] = mip_chroma_green;
163    dst_24[2] = mip_chroma_blue;
164
165    *dst  = 0;
166   
167    return;
168  }
169
170  float ooreg = 1.f / num_regular;
171 
172  r *= ooreg; if (r<0) r=0; if (r>255) r = 255;
173  g *= ooreg; if (g<0) g=0; if (g>255) g = 255;
174  b *= ooreg; if (b<0) b=0; if (b>255) b = 255;
175
176  dst_24[0] = (w8)r;
177  dst_24[1] = (w8)g;
178  dst_24[2] = (w8)b;
179
180  *dst = (( (w16)dst_24[0] << mip_c_r_shift) & mip_c_r_and) |
181         (( (w16)dst_24[1] << mip_c_g_shift) & mip_c_g_and) |
182         (( (w16)dst_24[2] >> mip_c_b_shift) & mip_c_b_and) |         
183         (( 0xFFFFFFFF << mip_c_a_shift) & mip_c_a_and); 
184}
185
186void average_4x4_chroma(w8 *dst_24, w8 *&p0, w8 *p1, w8 *p2, w8 *p3)
187{
188  sw8 num_chroma  = 0;
189  sw8 num_regular = 0;
190
191  float r=0;
192  float g=0;
193  float b=0;
194
195  chroma_process(p0,r,g,b,num_regular,num_chroma);
196  chroma_process(p1,r,g,b,num_regular,num_chroma);
197  chroma_process(p2,r,g,b,num_regular,num_chroma);
198  chroma_process(p3,r,g,b,num_regular,num_chroma);
199
200  //return the chroma color
201  if (num_chroma > num_regular)
202  {
203    //alpha component and rgb component of 16-bit pixel should be entirely 0'd
204    dst_24[0] = mip_chroma_red;
205    dst_24[1] = mip_chroma_green;
206    dst_24[2] = mip_chroma_blue;
207    return;
208  }
209
210  float ooreg = 1.f / num_regular;
211 
212  r *= ooreg; if (r<0) r=0; if (r>255) r = 255;
213  g *= ooreg; if (g<0) g=0; if (g>255) g = 255;
214  b *= ooreg; if (b<0) b=0; if (b>255) b = 255;
215
216  dst_24[0] = (w8)r;
217  dst_24[1] = (w8)g;
218  dst_24[2] = (w8)b;
219}
220
221void average_4x4_alpha(w8 *dst_24, w8 *&p0, w8 *p1, w8 *p2, w8 *p3)
222{
223  sw32 ia,ir,ig,ib;
224 
225  ia = p0[0];
226  ir = p0[1];
227  ig = p0[2];
228  ib = p0[3];
229 
230  ia += (p1[0]);
231  ir += (p1[1]);
232  ig += (p1[2]);
233  ib += (p1[3]);
234 
235  ia += (p2[0]);
236  ir += (p2[1]);
237  ig += (p2[2]);
238  ib += (p2[3]);
239 
240  ia += (p3[0]);
241  ir += (p3[1]); 
242  ig += (p3[2]);
243  ib += (p3[3]);
244
245  ia = ia >> 2;
246  ir = ir >> 2;
247  ig = ig >> 2;
248  ib = ib >> 2;
249 
250  dst_24[0] = (w8)ia;
251  dst_24[1] = (w8)ir;
252  dst_24[2] = (w8)ig;
253  dst_24[3] = (w8)ib;
254}
255
256void average_4x4_alpha(w16 *dst, w8 *dst_24, w8 *&p0, w8 *p1, w8 *p2, w8 *p3)
257{
258  sw32 ia,ir,ig,ib;
259 
260  ia = p0[0];
261  ir = p0[1];
262  ig = p0[2];
263  ib = p0[3];
264 
265  ia += (p1[0]);
266  ir += (p1[1]);
267  ig += (p1[2]);
268  ib += (p1[3]);
269 
270  ia += (p2[0]);
271  ir += (p2[1]);
272  ig += (p2[2]);
273  ib += (p2[3]);
274 
275  ia += (p3[0]);
276  ir += (p3[1]); 
277  ig += (p3[2]);
278  ib += (p3[3]);
279
280  ia = ia >> 2;
281  ir = ir >> 2;
282  ig = ig >> 2;
283  ib = ib >> 2;
284 
285  dst_24[0] = (w8)ia;
286  dst_24[1] = (w8)ir;
287  dst_24[2] = (w8)ig;
288  dst_24[3] = (w8)ib;
289
290  *dst = (( (w16)dst_24[1] << mip_a_r_shift) & mip_a_r_and) |
291         (( (w16)dst_24[2] << mip_a_g_shift) & mip_a_g_and) |
292         (( (w16)dst_24[3] >> mip_a_b_shift) & mip_a_b_and) |         
293         (( (w16)dst_24[0] << mip_a_a_shift) & mip_a_a_and);
294}
295
296
297void average_4x4_normal(w16 *dst, w8 *dst_24, w8 *p0, w32 bpl)
298
299#ifndef WIN32
300 
301  sw32 ir,ig,ib;
302 
303  ir = p0[0];
304  ig = p0[1];
305  ib = p0[2];
306 
307  ir += (p0[0+3]);
308  ig += (p0[1+3]);
309  ib += (p0[2+3]);
310 
311  ir += (p0[0+bpl]);
312  ig += (p0[1+bpl]);
313  ib += (p0[2+bpl]);
314 
315  ir += (p0[0+bpl+3]);
316  ig += (p0[1+bpl+3]);
317  ib += (p0[2+bpl+3]);
318
319  ir = ir >> 2;
320  ig = ig >> 2;
321  ib = ib >> 2;
322
323  dst_24[0] = (w8)ir;
324  dst_24[1] = (w8)ig;
325  dst_24[2] = (w8)ib;
326
327  *dst = (( (w16)p0[0] << mip_r_shift) & mip_r_and) |
328         (( (w16)p0[1] << mip_g_shift) & mip_g_and) |
329         (( (w16)p0[2] >> mip_b_shift) & mip_b_and);
330#else
331  _asm
332  {
333  mov esi,p0
334  mov edi,dst
335 
336  mov ecx,bpl
337
338  mov eax,0 //red
339  mov ebx,0 //green
340  mov edx,0 //blue
341
342  mov al,byte ptr [esi] 
343  add al,byte ptr [esi+3]
344  adc ah,0
345  add al,byte ptr [esi+ecx]
346  adc ah,0
347  add al,byte ptr [esi+ecx+3]
348  adc ah,0
349
350  mov bl,byte ptr [esi+1] 
351  add bl,byte ptr [esi+4]
352  adc bh,0
353  add bl,byte ptr [esi+ecx+1]
354  adc bh,0
355  add bl,byte ptr [esi+ecx+4]
356  adc bh,0
357
358  mov dl,byte ptr [esi+2]
359  add dl,byte ptr [esi+5]
360  adc dh,0
361  add dl,byte ptr [esi+ecx+2]
362  adc dh,0
363  add dl,byte ptr [esi+ecx+5]
364  adc dh,0
365     
366  shr eax,2
367  shr ebx,2
368  shr edx,2
369
370  mov esi,dst_24
371
372  mov byte ptr [esi],al
373  mov byte ptr [esi+1],bl
374  mov byte ptr [esi+2],dl
375 
376  mov cl,mip_r_shift
377  shl eax,cl
378  and eax,mip_r_and
379
380  mov cl,mip_g_shift
381  shl ebx,cl
382  and ebx,mip_g_and
383
384  mov cl,mip_b_shift
385  shr edx,cl
386  and edx,mip_b_and
387
388  or  eax,ebx
389  or  eax,edx
390
391  mov word ptr [edi],ax
392  }
393#endif
394}
395
396void average_4x4_normal(w8 *dst_24, w8 *p0, w32 bpl)
397
398#ifndef WIN32
399  sw32 ir,ig,ib;
400 
401  ir = (p0[0]);
402  ig = (p0[1]);
403  ib = (p0[2]);
404 
405  ir += (p0[0+3]);
406  ig += (p0[1+3]);
407  ib += (p0[2+3]);
408 
409  ir += (p0[0+bpl]);
410  ig += (p0[1+bpl]);
411  ib += (p0[2+bpl]);
412 
413  ir += (p0[0+bpl+3]);
414  ig += (p0[1+bpl+3]);
415  ib += (p0[2+bpl+3]); 
416
417  ir = ir >> 2; if (ir<0) ir = 0; else if (ir>255) ir = 255;
418  ig = ig >> 2; if (ig<0) ig = 0; else if (ig>255) ig = 255;
419  ib = ib >> 2; if (ib<0) ib = 0; else if (ib>255) ib = 255;
420 
421  dst_24[0] = (w8)ir;
422  dst_24[1] = (w8)ig;
423  dst_24[2] = (w8)ib; 
424#else 
425  _asm
426  {
427  mov esi,p0
428  mov edx,bpl
429  mov edi,dst_24
430
431  mov eax,0 //red
432  mov ebx,0 //green
433  mov ecx,0 //blue
434
435  mov al,byte ptr [esi] 
436  add al,byte ptr [esi+3]
437  adc ah,0
438  add al,byte ptr [esi+edx]
439  adc ah,0
440  add al,byte ptr [esi+edx+3]
441  adc ah,0
442
443  mov bl,byte ptr [esi+1] 
444  add bl,byte ptr [esi+4]
445  adc bh,0
446  add bl,byte ptr [esi+edx+1]
447  adc bh,0
448  add bl,byte ptr [esi+edx+4]
449  adc bh,0
450
451  mov cl,byte ptr [esi+2]
452  add cl,byte ptr [esi+5]
453  adc ch,0
454  add cl,byte ptr [esi+edx+2]
455  adc ch,0
456  add cl,byte ptr [esi+edx+5]
457  adc ch,0
458     
459  shr eax,2
460  shr ebx,2
461  shr ecx,2
462 
463  mov byte ptr [edi],al
464  mov byte ptr [edi+1],bl
465  mov byte ptr [edi+2],cl
466  }
467#endif
468}
469
470
471void mip_24_to_16(w8 *mip24, w16 *mip16, sw32 &width, sw32 &height, sw32 &base_width, w8 &flags)
472{
473  pf_mip_24_to_16.start();
474
475  sw32 i,j,total_pixels;
476 
477  w8  *src = mip24;
478  w16 *dst = mip16;
479   
480  sw32 base_bpl = base_width*3;
481  sw32 src_add  = (base_width - width)*3;
482 
483  if (flags & R1_MIP_IS_ALPHATEXTURE)
484  {
485    base_bpl = base_width*4;
486    src_add  = (base_width - width)*4;
487  } 
488
489  if (flags & R1_MIP_IS_TRANSPARENT)
490  {
491    for (j=0;j<height;j++)
492    {
493      for (i=0;i<width;i++)
494      {       
495        chroma_remap_pixel(dst,src);
496     
497        dst += 1;
498        src += 3;     
499      }
500 
501      src += src_add;
502    }
503  }
504  else
505  if (flags & R1_MIP_IS_ALPHATEXTURE)
506  {
507    for (j=0;j<height;j++)
508    {
509      for (i=0;i<width;i++)
510      {       
511        alpha_remap_pixel(dst,src);
512     
513        dst += 1;
514        src += 4;     
515      }
516 
517      src += src_add;
518    }
519  }
520  else
521  {
522    for (j=0; j<height; j++)
523    {
524      src = mip24 + j*base_bpl;
525
526      for (i=0; i<width;  i++)
527      {
528        remap_pixel(dst,src);
529     
530        dst += 1;
531        src += 3;
532      }
533     
534      //src += src_add;
535    }
536  }
537  pf_mip_24_to_16.stop();
538}
539
540void make_next_mip(w8 *mip24, w16 *mip16, sw32 &width, sw32 &height, sw32 &base_width, w8 &flags)
541{
542  pf_make_next_mip.start();
543
544  sw32 i,j;
545 
546  w8  *src    = mip24;
547  w16 *dst    = mip16;
548  w8  *dst_24 = mip24;
549
550  sw32 base_bpl   = base_width*3;
551  sw32 dst_24_add = (base_width - width)*3;
552  sw32 src_add    = (base_width - width*2)*3 + base_bpl;
553 
554  if (flags & R1_MIP_IS_ALPHATEXTURE)
555  {
556    base_bpl   = base_width*4;
557    dst_24_add = (base_width - width)*4;
558    src_add    = (base_width - width*2)*4 + base_bpl;
559  } 
560
561  if (dst)
562  {
563    if (flags & R1_MIP_IS_TRANSPARENT)
564    {
565      for (j=0; j<height; j++)
566      {
567        for (i=0; i<width;  i++)
568        {
569          average_4x4_chroma(dst,dst_24,src,src+3,src+base_bpl,src+base_bpl+3);
570       
571          dst    += 1;
572          dst_24 += 3;
573          src    += 6;
574        }
575       
576        dst_24 += dst_24_add;
577        src    += src_add;       
578      }
579    }
580    else
581    if (flags & R1_MIP_IS_ALPHATEXTURE)
582    {
583      for (j=0; j<height; j++)
584      {
585        for (i=0; i<width;  i++)
586        {
587          average_4x4_alpha(dst,dst_24,src,src+4,src+base_bpl,src+base_bpl+4);
588       
589          dst    += 1;
590          dst_24 += 4;
591          src    += 8;
592        }
593       
594        dst_24 += dst_24_add;
595        src    += src_add;       
596      }
597    }
598    else
599    {
600      for (j=0; j<height; j++)
601      {
602        for (i=0; i<width;  i++)
603        {
604          average_4x4_normal(dst,dst_24,src,base_bpl);
605       
606          dst    += 1;
607          dst_24 += 3;
608          src    += 6;
609        }
610               
611        dst_24 += dst_24_add;
612        src    += src_add;       
613      }
614    }
615  }
616  else
617  {
618    if (flags & R1_MIP_IS_TRANSPARENT)
619    {
620      for (j=0; j<height; j++)
621      {       
622        for (i=0; i<width;  i++)
623        {
624          average_4x4_chroma(dst_24,src,src+3,src+base_bpl,src+base_bpl+3);
625         
626          dst_24 += 3;
627          src    += 6;
628        }       
629       
630        dst_24 += dst_24_add;
631        src    += src_add;
632      }
633    }
634    else
635    if (flags & R1_MIP_IS_ALPHATEXTURE)
636    {
637      for (j=0; j<height; j++)
638      {
639        for (i=0; i<width;  i++)
640        {
641          average_4x4_alpha(dst_24,src,src+4,src+base_bpl,src+base_bpl+4);
642
643          dst_24 += 4;
644          src    += 8;
645        }
646       
647        dst_24 += dst_24_add;
648        src    += src_add;       
649      }
650    }
651    else
652    {
653      for (j=0; j<height; j++)
654      {       
655        for (i=0; i<width;  i++)
656        {
657          average_4x4_normal(dst_24,src,base_bpl);
658         
659          dst_24 += 3;
660          src    += 6;
661        }       
662       
663        dst_24 += dst_24_add;
664        src    += src_add;
665      }
666    }
667  }
668 
669  pf_make_next_mip.stop();
670}
671
672void make_square(w8 *mip24, w8 *square_mip24, w8 base_pixel_size, sw32 base_width,
673                 sw32 base_height, sw32 new_dimention)
674{
675  double width_ratio  = (double)base_width  / (double)new_dimention;
676  double height_ratio = (double)base_height / (double)new_dimention;
677   
678  //now scale the old to fit the new
679  sw32 i,j,k;
680
681  w8 *dst = square_mip24;
682
683  for (j=0; j<new_dimention; j++)
684  for (i=0; i<new_dimention; i++)
685  {   
686    w8 *src = &mip24[(i4_f_to_i( ((double)j * height_ratio)*base_width ) +
687                      i4_f_to_i( ((double)i * width_ratio))) * base_pixel_size ];
688
689    for (k=0; k<base_pixel_size; k++)
690    {
691      *dst = *src;
692      src++;
693      dst++;
694    }
695  }
696
697}
698
699
700void generate_mip_offsets(sw32 base_width,sw32 base_height,
701                          sw32 num_to_copy,
702                          sw32 *offsets, sw32 pixel_size)
703
704  sw32 cur_offset = r1_mip_header_disk_size();
705
706  //start copying w/this mip
707  sw32 i;
708  for (i=0;i<num_to_copy;i++)
709  {
710    offsets[i] = cur_offset;
711
712    sw32 width  = base_width  / (1<<i);
713    sw32 height = base_height / (1<<i);
714   
715    cur_offset += ((width*height*pixel_size) + sizeof(sw32)*2);
716  }
717}
Note: See TracBrowser for help on using the repository browser.