image32.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. #include "memory/malloc.hh"
  9. #include "image/image32.hh"
  10. #include "image/image8.hh"
  11. #include "palette/pal.hh"
  12. #include "error/error.hh"
  13. #include <string.h>
  14. i4_color i4_image32::get_pixel(i4_coord x, i4_coord y)
  15. {
  16. return i4_pal_man.convert_to_32(*paddr(x,y), pal);
  17. }
  18. void i4_image32::put_pixel(i4_coord x, i4_coord y, w32 color)
  19. {
  20. *paddr(x,y)=i4_pal_man.convert_32_to(color, &pal->source);
  21. }
  22. i4_image32::i4_image32(w16 _w, w16 _h, const i4_pal *_pal)
  23. {
  24. w=_w;
  25. h=_h;
  26. bpl=_w*4;
  27. set_pal(_pal);
  28. data=i4_malloc(w*h*4,"");
  29. }
  30. i4_image32::i4_image32(w16 _w, w16 _h, const i4_pal *_pal,
  31. void *_data, int _bpl)
  32. {
  33. data=_data;
  34. bpl=_bpl;
  35. pal=_pal;
  36. w=_w;
  37. h=_h;
  38. dont_free_data=i4_T;
  39. }
  40. i4_image32::~i4_image32()
  41. {
  42. if (!dont_free_data)
  43. i4_free(data);
  44. }
  45. inline w32 color_dist(w32 c1, w32 c2)
  46. {
  47. sw32 r1=(c1 & 0xff0000)>>16;
  48. sw32 r2=(c2 & 0xff0000)>>16;
  49. sw32 g1=(c1 & 0xff00)>>8;
  50. sw32 g2=(c2 & 0xff00)>>8;
  51. sw32 b1=(c1 & 0xff);
  52. sw32 b2=(c2 & 0xff);
  53. return (r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2);
  54. }
  55. inline w16 _32_to_16_565(w32 c)
  56. {
  57. w8 r = ((c&0xff0000)>>16)>>3;
  58. w8 g = ((c&0xff00)>>8)>>2;
  59. w8 b = (c&0xff)>>3;
  60. return (r<<11) | (g<<5) | b;
  61. }
  62. i4_image_class *i4_image32::quantize(const i4_pal *pal,
  63. w32 skip_colors,
  64. i4_coord x1, i4_coord y1,
  65. i4_coord x2, i4_coord y2)
  66. {
  67. if (pal->source.pixel_depth!=I4_8BIT)
  68. i4_error("palette handle, should be 8 bit");
  69. // first check to make sure the sub image is located within this one
  70. if (x1<0) x1=0;
  71. if (y1<0) y1=0;
  72. if (x2>=width())
  73. x2 = width()-1;
  74. if (y2>=height())
  75. y2 = height()-1;
  76. if (x2<x1 || y2<y1)
  77. return 0;
  78. i4_image8 *im8 = new i4_image8(x2-x1+1,
  79. y2-y1+1,
  80. pal);
  81. w32 *pixel32 = (w32 *)((w8 *)data + x1*4 + y1*bpl);
  82. w8 *pixel8 = (w8 *)im8->data;
  83. w32 skip_32 = bpl-(x2-x1+1); // pixels to skip per line
  84. w32 x,y;
  85. w8 closest_color;
  86. w32 closest_distance,
  87. distance,
  88. *color_index;
  89. w32 *pal_data=pal->source.lookup;
  90. // maps 16 bits color space into closest 8 bit color
  91. w8 *lookup_table=(w8 *)i4_malloc(0x10000, "lookup");
  92. // indicates if above color has been calculated yet
  93. w8 *table_calced=(w8 *)i4_malloc(0x10000, "table_calced");
  94. memset(table_calced,0,0x10000); // initially no mappings are calculated
  95. for (y=y2-y1+1; y; y--)
  96. {
  97. for (x=x2-x1+1; x; x--)
  98. {
  99. i4_color color=*pixel32;
  100. w16 c16 = _32_to_16_565(color);
  101. if (table_calced[c16]) // have we found the closest color to this yet?
  102. *pixel8=lookup_table[c16];
  103. else
  104. {
  105. // find the closest color to this pixel
  106. color_index = pal_data+skip_colors;
  107. closest_distance = 0xffffffff;
  108. for (w32 c=skip_colors; c<256; c++)
  109. {
  110. distance=color_dist(*color_index,color);
  111. if (distance<closest_distance)
  112. {
  113. closest_distance=distance;
  114. closest_color=c;
  115. }
  116. color_index++;
  117. }
  118. table_calced[c16]=1;
  119. lookup_table[c16]=closest_color;
  120. *pixel8=closest_color;
  121. }
  122. ++pixel32;
  123. ++pixel8;
  124. }
  125. pixel32+=skip_32;
  126. }
  127. i4_free(lookup_table);
  128. i4_free(table_calced);
  129. return im8;
  130. }