| 1 | /*!
|
|---|
| 2 | \file lib/display/raster.c
|
|---|
| 3 |
|
|---|
| 4 | \brief Display Driver - draw raster data
|
|---|
| 5 |
|
|---|
| 6 | (C) 2006-2011 by the GRASS Development Team
|
|---|
| 7 |
|
|---|
| 8 | This program is free software under the GNU General Public License
|
|---|
| 9 | (>=v2). Read the file COPYING that comes with GRASS for details.
|
|---|
| 10 |
|
|---|
| 11 | \author Glynn Clements <glynn gclements.plus.com> (original contributor)
|
|---|
| 12 | \author Huidae Cho <grass4u gmail.com>
|
|---|
| 13 | */
|
|---|
| 14 |
|
|---|
| 15 | #include <stdio.h>
|
|---|
| 16 | #include <stdlib.h>
|
|---|
| 17 |
|
|---|
| 18 | #include <grass/gis.h>
|
|---|
| 19 | #include <grass/raster.h>
|
|---|
| 20 | #include <grass/display.h>
|
|---|
| 21 | #include "driver.h"
|
|---|
| 22 |
|
|---|
| 23 | extern int D__overlay_mode;
|
|---|
| 24 |
|
|---|
| 25 | static int src[2][2];
|
|---|
| 26 | static double dst[2][2];
|
|---|
| 27 |
|
|---|
| 28 | static int draw_cell(int, const void *, struct Colors *, RASTER_MAP_TYPE);
|
|---|
| 29 |
|
|---|
| 30 | /*!
|
|---|
| 31 | \brief Draw raster row
|
|---|
| 32 |
|
|---|
| 33 | - determine which pixel row gets the data
|
|---|
| 34 | - resamples the data to create a pixel array
|
|---|
| 35 | - determines best way to draw the array
|
|---|
| 36 | a - for single cat array, a move and a draw
|
|---|
| 37 | b - otherwise, a call to D_raster()
|
|---|
| 38 |
|
|---|
| 39 | Presumes the map is drawn from north to south.
|
|---|
| 40 |
|
|---|
| 41 | If overlay mode is desired, then call D_set_overlay_mode() first.
|
|---|
| 42 |
|
|---|
| 43 | \param A_row row number (starts at 0)
|
|---|
| 44 | \param array data buffer
|
|---|
| 45 | \param colors pointer to Colors structure
|
|---|
| 46 | \param data_type raster type (CELL, FCELL, DCELL)
|
|---|
| 47 |
|
|---|
| 48 | \return row number needed for next pixel row
|
|---|
| 49 | \return -1 nothing to draw (on error or end of raster)
|
|---|
| 50 | */
|
|---|
| 51 | int D_draw_raster(int A_row,
|
|---|
| 52 | const void *array,
|
|---|
| 53 | struct Colors *colors, RASTER_MAP_TYPE data_type)
|
|---|
| 54 | {
|
|---|
| 55 | return draw_cell(A_row, array, colors, data_type);
|
|---|
| 56 | }
|
|---|
| 57 |
|
|---|
| 58 | /*!
|
|---|
| 59 | \brief Draw raster row (DCELL)
|
|---|
| 60 |
|
|---|
| 61 | \param A_row row number (starts at 0)
|
|---|
| 62 | \param darray data buffer
|
|---|
| 63 | \param colors pointer to Colors structure
|
|---|
| 64 |
|
|---|
| 65 | \return
|
|---|
| 66 | */
|
|---|
| 67 | int D_draw_d_raster(int A_row, const DCELL * darray, struct Colors *colors)
|
|---|
| 68 | {
|
|---|
| 69 | return draw_cell(A_row, darray, colors, DCELL_TYPE);
|
|---|
| 70 | }
|
|---|
| 71 |
|
|---|
| 72 | /*!
|
|---|
| 73 | \brief Draw raster row (FCELL)
|
|---|
| 74 |
|
|---|
| 75 | \param A_row row number (starts at 0)
|
|---|
| 76 | \param farray data buffer
|
|---|
| 77 | \param colors pointer to Colors structure
|
|---|
| 78 |
|
|---|
| 79 | \return row number needed for next pixel row
|
|---|
| 80 | \return -1 nothing to draw (on error or end of raster)
|
|---|
| 81 | */
|
|---|
| 82 | int D_draw_f_raster(int A_row, const FCELL * farray, struct Colors *colors)
|
|---|
| 83 | {
|
|---|
| 84 | return draw_cell(A_row, farray, colors, FCELL_TYPE);
|
|---|
| 85 | }
|
|---|
| 86 |
|
|---|
| 87 | /*!
|
|---|
| 88 | \brief Draw raster row (CELL)
|
|---|
| 89 |
|
|---|
| 90 | The <b>row</b> gives the map array row. The <b>carray</b> array
|
|---|
| 91 | provides the categories for each raster value in that row. This
|
|---|
| 92 | routine is called consecutively with the information necessary to
|
|---|
| 93 | draw a raster image from north to south. No rows can be skipped. All
|
|---|
| 94 | screen pixel rows which represent the current map array row are
|
|---|
| 95 | rendered. The routine returns the map array row which is needed to
|
|---|
| 96 | draw the next screen pixel row.
|
|---|
| 97 |
|
|---|
| 98 | \param A_row row number (starts at 0)
|
|---|
| 99 | \param carray data buffer
|
|---|
| 100 | \param colors pointer to Colors structure
|
|---|
| 101 |
|
|---|
| 102 | \return row number needed for next pixel row
|
|---|
| 103 | \return -1 nothing to draw (on error or end of raster)
|
|---|
| 104 | */
|
|---|
| 105 | int D_draw_c_raster(int A_row, const CELL * carray, struct Colors *colors)
|
|---|
| 106 | {
|
|---|
| 107 | return draw_cell(A_row, carray, colors, CELL_TYPE);
|
|---|
| 108 | }
|
|---|
| 109 |
|
|---|
| 110 | static int draw_cell(int A_row,
|
|---|
| 111 | const void *array,
|
|---|
| 112 | struct Colors *colors, RASTER_MAP_TYPE data_type)
|
|---|
| 113 | {
|
|---|
| 114 | static unsigned char *red, *grn, *blu, *set;
|
|---|
| 115 | static int nalloc;
|
|---|
| 116 |
|
|---|
| 117 | int ncols = src[0][1] - src[0][0];
|
|---|
| 118 | int i;
|
|---|
| 119 |
|
|---|
| 120 | if (nalloc < ncols) {
|
|---|
| 121 | nalloc = ncols;
|
|---|
| 122 | red = G_realloc(red, nalloc);
|
|---|
| 123 | grn = G_realloc(grn, nalloc);
|
|---|
| 124 | blu = G_realloc(blu, nalloc);
|
|---|
| 125 | set = G_realloc(set, nalloc);
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | Rast_lookup_colors(array, red, grn, blu, set, ncols, colors,
|
|---|
| 129 | data_type);
|
|---|
| 130 |
|
|---|
| 131 | if (D__overlay_mode)
|
|---|
| 132 | for (i = 0; i < ncols; i++) {
|
|---|
| 133 | set[i] = Rast_is_null_value(array, data_type);
|
|---|
| 134 | array = G_incr_void_ptr(array, Rast_cell_size(data_type));
|
|---|
| 135 | }
|
|---|
| 136 |
|
|---|
| 137 | A_row =
|
|---|
| 138 | COM_raster(ncols, A_row, red, grn, blu, D__overlay_mode ? set : NULL);
|
|---|
| 139 |
|
|---|
| 140 | return (A_row < src[1][1])
|
|---|
| 141 | ? A_row : -1;
|
|---|
| 142 | }
|
|---|
| 143 |
|
|---|
| 144 | /*!
|
|---|
| 145 | \brief Prepare for raster graphic
|
|---|
| 146 |
|
|---|
| 147 | The raster display subsystem establishes conversion parameters based
|
|---|
| 148 | on the screen extent defined by <b>top, bottom, left</b>, and
|
|---|
| 149 | <b>right</b>, all of which are obtainable from D_get_dst() for the
|
|---|
| 150 | current frame.
|
|---|
| 151 | */
|
|---|
| 152 | void D_raster_draw_begin(void)
|
|---|
| 153 | {
|
|---|
| 154 | /* Set up the screen for drawing map */
|
|---|
| 155 | D_get_a(src);
|
|---|
| 156 | D_get_d(dst);
|
|---|
| 157 | COM_begin_raster(D__overlay_mode, src, dst);
|
|---|
| 158 | }
|
|---|
| 159 |
|
|---|
| 160 | /*!
|
|---|
| 161 | \brief Draw raster row in RGB mode
|
|---|
| 162 |
|
|---|
| 163 | \param A_row row number (starts at 0)
|
|---|
| 164 | \param r_raster red data buffer
|
|---|
| 165 | \param g_raster green data buffer
|
|---|
| 166 | \param b_raster blue data buffer
|
|---|
| 167 | \param r_colors colors used for red channel
|
|---|
| 168 | \param g_colors colors used for green channel
|
|---|
| 169 | \param b_colors colors used for blue channel
|
|---|
| 170 | \param r_type raster type used for red channel
|
|---|
| 171 | \param g_type raster type used for red channel
|
|---|
| 172 | \param b_type raster type used for red channel
|
|---|
| 173 |
|
|---|
| 174 | \return row number needed for next pixel row
|
|---|
| 175 | \return -1 nothing to draw (on error or end of raster)
|
|---|
| 176 | */
|
|---|
| 177 | int D_draw_raster_RGB(int A_row,
|
|---|
| 178 | const void *r_raster, const void *g_raster,
|
|---|
| 179 | const void *b_raster, struct Colors *r_colors,
|
|---|
| 180 | struct Colors *g_colors, struct Colors *b_colors,
|
|---|
| 181 | RASTER_MAP_TYPE r_type, RASTER_MAP_TYPE g_type,
|
|---|
| 182 | RASTER_MAP_TYPE b_type)
|
|---|
| 183 | {
|
|---|
| 184 | static unsigned char *r_buf, *g_buf, *b_buf, *n_buf;
|
|---|
| 185 | static int nalloc;
|
|---|
| 186 |
|
|---|
| 187 | int r_size = Rast_cell_size(r_type);
|
|---|
| 188 | int g_size = Rast_cell_size(g_type);
|
|---|
| 189 | int b_size = Rast_cell_size(b_type);
|
|---|
| 190 | int ncols = src[0][1] - src[0][0];
|
|---|
| 191 | int i;
|
|---|
| 192 |
|
|---|
| 193 | /* reallocate color_buf if necessary */
|
|---|
| 194 | if (nalloc < ncols) {
|
|---|
| 195 | nalloc = ncols;
|
|---|
| 196 | r_buf = G_realloc(r_buf, nalloc);
|
|---|
| 197 | g_buf = G_realloc(g_buf, nalloc);
|
|---|
| 198 | b_buf = G_realloc(b_buf, nalloc);
|
|---|
| 199 | n_buf = G_realloc(n_buf, nalloc);
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | /* convert cell values to bytes */
|
|---|
| 203 | Rast_lookup_colors(r_raster, r_buf, n_buf, n_buf, n_buf, ncols,
|
|---|
| 204 | r_colors, r_type);
|
|---|
| 205 | Rast_lookup_colors(g_raster, n_buf, g_buf, n_buf, n_buf, ncols,
|
|---|
| 206 | g_colors, g_type);
|
|---|
| 207 | Rast_lookup_colors(b_raster, n_buf, n_buf, b_buf, n_buf, ncols,
|
|---|
| 208 | b_colors, b_type);
|
|---|
| 209 |
|
|---|
| 210 | if (D__overlay_mode)
|
|---|
| 211 | for (i = 0; i < ncols; i++) {
|
|---|
| 212 | n_buf[i] = (Rast_is_null_value(r_raster, r_type) ||
|
|---|
| 213 | Rast_is_null_value(g_raster, g_type) ||
|
|---|
| 214 | Rast_is_null_value(b_raster, b_type));
|
|---|
| 215 |
|
|---|
| 216 | r_raster = G_incr_void_ptr(r_raster, r_size);
|
|---|
| 217 | g_raster = G_incr_void_ptr(g_raster, g_size);
|
|---|
| 218 | b_raster = G_incr_void_ptr(b_raster, b_size);
|
|---|
| 219 | }
|
|---|
| 220 |
|
|---|
| 221 | A_row = COM_raster(ncols, A_row, r_buf, g_buf, b_buf,
|
|---|
| 222 | D__overlay_mode ? n_buf : NULL);
|
|---|
| 223 |
|
|---|
| 224 | return (A_row < src[1][1])
|
|---|
| 225 | ? A_row : -1;
|
|---|
| 226 | }
|
|---|
| 227 |
|
|---|
| 228 | /*!
|
|---|
| 229 | \brief Finish raster rendering
|
|---|
| 230 | */
|
|---|
| 231 | void D_raster_draw_end(void)
|
|---|
| 232 | {
|
|---|
| 233 | COM_end_raster();
|
|---|
| 234 | }
|
|---|