raster.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*!
  2. \file lib/pngdriver/raster.c
  3. \brief GRASS png display driver - draw raster
  4. (C) 2003-2014 by Per Henrik Johansen and the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Per Henrik Johansen (original contributor)
  8. \author Glynn Clements
  9. */
  10. #include <string.h>
  11. #include <math.h>
  12. #include <grass/gis.h>
  13. #include "driver.h"
  14. #include "pngdriver.h"
  15. #ifndef min
  16. #define min(a,b) ((a)<(b)?(a):(b))
  17. #endif
  18. #ifndef max
  19. #define max(a,b) ((a)>(b)?(a):(b))
  20. #endif
  21. static int *trans;
  22. static int ncols;
  23. static int nalloc;
  24. static int masked;
  25. static int src[2][2];
  26. static int dst[2][2];
  27. static double scale(double k, const int src[2], const int dst[2])
  28. {
  29. return dst[0] + (double)(k - src[0]) * (dst[1] - dst[0]) / (src[1] -
  30. src[0]);
  31. }
  32. static int scale_fwd_y(int sy)
  33. {
  34. return (int)floor(scale(sy, src[1], dst[1]) + 0.5);
  35. }
  36. static int scale_rev_x(int dx)
  37. {
  38. return (int)floor(scale(dx + 0.5, dst[0], src[0]));
  39. }
  40. static int next_row(int sy, int dy)
  41. {
  42. sy++;
  43. for (;;) {
  44. int y = scale_fwd_y(sy);
  45. if (y > dy)
  46. return sy - 1;
  47. sy++;
  48. }
  49. }
  50. static void alloc_buffers(void)
  51. {
  52. if (nalloc >= ncols)
  53. return;
  54. nalloc = ncols;
  55. trans = G_realloc(trans, nalloc * sizeof(int));
  56. }
  57. /*!
  58. \brief Start drawing raster
  59. \param mask non-zero int for mask
  60. \param s source (map) extent (left, right, top, bottom)
  61. \param fd destination (image) extent (left, right, top, bottom)
  62. */
  63. void PNG_begin_raster(int mask, int s[2][2], double fd[2][2])
  64. {
  65. int d[2][2];
  66. int i;
  67. d[0][0] = (int) floor(fd[0][0] + 0.5);
  68. d[0][1] = (int) floor(fd[0][1] + 0.5);
  69. d[1][0] = (int) floor(fd[1][0] + 0.5);
  70. d[1][1] = (int) floor(fd[1][1] + 0.5);
  71. ncols = d[0][1] - d[0][0];
  72. memcpy(src, s, sizeof(src));
  73. memcpy(dst, d, sizeof(dst));
  74. masked = mask;
  75. alloc_buffers();
  76. for (i = 0; i < ncols; i++)
  77. trans[i] = scale_rev_x(d[0][0] + i);
  78. }
  79. /*!
  80. \brief Draw raster row
  81. \param n number of cells
  82. \param row raster row (starts at 0)
  83. \param red,grn,blu,nul red,green,blue and null value
  84. \return next row
  85. */
  86. int PNG_raster(int n, int row,
  87. const unsigned char *red, const unsigned char *grn,
  88. const unsigned char *blu, const unsigned char *nul)
  89. {
  90. int d_y0 = scale_fwd_y(row + 0);
  91. int d_y1 = scale_fwd_y(row + 1);
  92. int d_rows = d_y1 - d_y0;
  93. int x0 = max(png.clip_left - dst[0][0], 0);
  94. int x1 = min(png.clip_rite - dst[0][0], ncols);
  95. int y0 = max(png.clip_top - d_y0, 0);
  96. int y1 = min(png.clip_bot - d_y0, d_rows);
  97. int x, y;
  98. if (y1 <= y0)
  99. return next_row(row, d_y1);
  100. for (x = x0; x < x1; x++) {
  101. int xx = dst[0][0] + x;
  102. int j = trans[x];
  103. int c;
  104. if (masked && nul && nul[j])
  105. continue;
  106. c = png_get_color(red[j], grn[j], blu[j], 0);
  107. for (y = y0; y < y1; y++) {
  108. int yy = d_y0 + y;
  109. png.grid[yy * png.width + xx] = c;
  110. }
  111. }
  112. png.modified = 1;
  113. return next_row(row, d_y1);
  114. }