blur.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. © 2011-2015 by Kornel Lesiński.
  3. This file is part of libimagequant.
  4. libimagequant is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. libimagequant 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. You should have received a copy of the GNU General Public License
  13. along with libimagequant. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "libimagequant.h"
  16. #include "pam.h"
  17. #include "blur.h"
  18. /*
  19. Blurs image horizontally (width 2*size+1) and writes it transposed to dst (called twice gives 2d blur)
  20. */
  21. static void transposing_1d_blur(unsigned char *restrict src, unsigned char *restrict dst, unsigned int width, unsigned int height, const unsigned int size)
  22. {
  23. assert(size > 0);
  24. for(unsigned int j=0; j < height; j++) {
  25. unsigned char *restrict row = src + j*width;
  26. // accumulate sum for pixels outside line
  27. unsigned int sum;
  28. sum = row[0]*size;
  29. for(unsigned int i=0; i < size; i++) {
  30. sum += row[i];
  31. }
  32. // blur with left side outside line
  33. for(unsigned int i=0; i < size; i++) {
  34. sum -= row[0];
  35. sum += row[i+size];
  36. dst[i*height + j] = sum / (size*2);
  37. }
  38. for(unsigned int i=size; i < width-size; i++) {
  39. sum -= row[i-size];
  40. sum += row[i+size];
  41. dst[i*height + j] = sum / (size*2);
  42. }
  43. // blur with right side outside line
  44. for(unsigned int i=width-size; i < width; i++) {
  45. sum -= row[i-size];
  46. sum += row[width-1];
  47. dst[i*height + j] = sum / (size*2);
  48. }
  49. }
  50. }
  51. /**
  52. * Picks maximum of neighboring pixels (blur + lighten)
  53. */
  54. LIQ_PRIVATE void liq_max3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height)
  55. {
  56. for(unsigned int j=0; j < height; j++) {
  57. const unsigned char *row = src + j*width,
  58. *prevrow = src + (j > 1 ? j-1 : 0)*width,
  59. *nextrow = src + MIN(height-1,j+1)*width;
  60. unsigned char prev,curr=row[0],next=row[0];
  61. for(unsigned int i=0; i < width-1; i++) {
  62. prev=curr;
  63. curr=next;
  64. next=row[i+1];
  65. unsigned char t1 = MAX(prev,next);
  66. unsigned char t2 = MAX(nextrow[i],prevrow[i]);
  67. *dst++ = MAX(curr,MAX(t1,t2));
  68. }
  69. unsigned char t1 = MAX(curr,next);
  70. unsigned char t2 = MAX(nextrow[width-1],prevrow[width-1]);
  71. *dst++ = MAX(t1,t2);
  72. }
  73. }
  74. /**
  75. * Picks minimum of neighboring pixels (blur + darken)
  76. */
  77. LIQ_PRIVATE void liq_min3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height)
  78. {
  79. for(unsigned int j=0; j < height; j++) {
  80. const unsigned char *row = src + j*width,
  81. *prevrow = src + (j > 1 ? j-1 : 0)*width,
  82. *nextrow = src + MIN(height-1,j+1)*width;
  83. unsigned char prev,curr=row[0],next=row[0];
  84. for(unsigned int i=0; i < width-1; i++) {
  85. prev=curr;
  86. curr=next;
  87. next=row[i+1];
  88. unsigned char t1 = MIN(prev,next);
  89. unsigned char t2 = MIN(nextrow[i],prevrow[i]);
  90. *dst++ = MIN(curr,MIN(t1,t2));
  91. }
  92. unsigned char t1 = MIN(curr,next);
  93. unsigned char t2 = MIN(nextrow[width-1],prevrow[width-1]);
  94. *dst++ = MIN(t1,t2);
  95. }
  96. }
  97. /*
  98. Filters src image and saves it to dst, overwriting tmp in the process.
  99. Image must be width*height pixels high. Size controls radius of box blur.
  100. */
  101. LIQ_PRIVATE void liq_blur(unsigned char *src, unsigned char *tmp, unsigned char *dst, unsigned int width, unsigned int height, unsigned int size)
  102. {
  103. assert(size > 0);
  104. if (width < 2*size+1 || height < 2*size+1) {
  105. return;
  106. }
  107. transposing_1d_blur(src, tmp, width, height, size);
  108. transposing_1d_blur(tmp, dst, height, width, size);
  109. }