You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ScaleFilters.cxx 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* Copyright (C) 2006 TightVNC Team. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #include <string.h>
  22. #include <assert.h>
  23. #include <math.h>
  24. #include <rfb/Rect.h>
  25. #include <rfb/ScaleFilters.h>
  26. using namespace rfb;
  27. //
  28. // -=- 1-D filters functions
  29. //
  30. // Nearest neighbor filter function
  31. double nearest_neighbor(double x) {
  32. if (x < -0.5) return 0.0;
  33. if (x < 0.5) return 1.0;
  34. return 0.0;
  35. }
  36. // Linear filter function
  37. double linear(double x) {
  38. if (x < -1.0) return 0.0;
  39. if (x < 0.0) return 1.0+x;
  40. if (x < 1.0) return 1.0-x;
  41. return 0.0;
  42. }
  43. // Cubic filter functions
  44. double cubic(double x) {
  45. double t;
  46. if (x < -2.0) return 0.0;
  47. if (x < -1.0) {t = 2.0+x; return t*t*t/6.0;}
  48. if (x < 0.0) return (4.0+x*x*(-6.0+x*-3.0))/6.0;
  49. if (x < 1.0) return (4.0+x*x*(-6.0+x*3.0))/6.0;
  50. if (x < 2.0) {t = 2.0-x; return t*t*t/6.0;}
  51. return 0.0;
  52. }
  53. //
  54. // -=- ScaleFilters class
  55. //
  56. SFilter &ScaleFilters::operator[](unsigned int filter_id) {
  57. assert(filter_id <= scaleFilterMaxNumber);
  58. return filters[filter_id];
  59. }
  60. int ScaleFilters::getFilterIdByName(char *filterName) {
  61. for (unsigned int i = 0; i <= scaleFilterMaxNumber; i++) {
  62. if (strcasecmp(filters[i].name, filterName) == 0) return i;
  63. }
  64. return -1;
  65. }
  66. void ScaleFilters::initFilters() {
  67. filters[scaleFilterNearestNeighbor] = create("Nearest neighbor", 0.5, nearest_neighbor);
  68. filters[scaleFilterBilinear] = create("Bilinear", 1, linear);
  69. filters[scaleFilterBicubic] = create("Bicubic", 2, cubic);
  70. }
  71. SFilter ScaleFilters::create(const char *name_, double radius_, filter_func func_) {
  72. SFilter filter;
  73. strncpy(filter.name, name_, sizeof(filter.name)-1);
  74. filter.name[sizeof(filter.name)-1] = '\0';
  75. filter.radius = radius_;
  76. filter.func = func_;
  77. return filter;
  78. }
  79. void ScaleFilters::makeWeightTabs(int filter_id, int src_x, int dst_x, SFilterWeightTab **pWeightTabs) {
  80. double sxc;
  81. double offset = 0.5;
  82. double ratio = (double)dst_x / src_x;
  83. double sourceScale = __rfbmax(1.0, 1.0/ratio);
  84. double sourceRadius = __rfbmax(0.5, sourceScale * filters[filter_id].radius);
  85. double sum, nc;
  86. int i, ci;
  87. SFilter sFilter = filters[filter_id];
  88. *pWeightTabs = new SFilterWeightTab[dst_x];
  89. SFilterWeightTab *weightTabs = *pWeightTabs;
  90. // Make the weight tab for the each dest x position
  91. for (int x = 0; x < dst_x; x++) {
  92. sxc = (double(x)+offset) / ratio;
  93. // Calculate the scale filter interval, [i0, i1)
  94. int i0 = int(__rfbmax(sxc-sourceRadius+0.5, 0));
  95. int i1 = int(__rfbmin(sxc+sourceRadius+0.5, src_x));
  96. weightTabs[x].i0 = i0; weightTabs[x].i1 = i1;
  97. weightTabs[x].weight = new short[i1-i0];
  98. // Calculate coeff to normalize the filter weights
  99. for (sum = 0, i = i0; i < i1; i++) sum += sFilter.func((double(i)-sxc+0.5)/sourceScale);
  100. if (sum == 0.) nc = (double)(WEIGHT_OF_ONE); else nc = (double)(WEIGHT_OF_ONE)/sum;
  101. // Calculate the weight coeffs on the scale filter interval
  102. for (ci = 0, i = i0; i < i1; i++) {
  103. weightTabs[x].weight[ci++] = (short)floor((sFilter.func((double(i)-sxc+0.5)/sourceScale) * nc) + 0.5);
  104. }
  105. }
  106. }