/*! \file lib/ogsf/gs_bm.c \brief OGSF library - manipulating bitmaps (lower level functions) GRASS OpenGL gsurf OGSF Library (C) 1999-2008 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. \author Bill Brown USACERL, GMSL/University of Illinois (September 1993) \author Doxygenized by Martin Landa (May 2008) */ #include #include #include #include "gsget.h" /*! \brief Do combining of bitmaps, make bitmaps from other data w/maskval \param frombuff data buffer \param maskval mask type \param rows number of rows \param cols number of cols \return pointer to BM struct */ struct BM *gsbm_make_mask(typbuff * frombuff, float maskval, int rows, int cols) { int i, j, ioff; struct BM *bm; float curval; bm = BM_create(cols, rows); if (frombuff) { if (frombuff->bm) { for (i = 0; i < rows; i++) { ioff = i * cols; for (j = 0; j < cols; j++) { BM_set(bm, j, i, BM_get(frombuff->bm, j, i)); } } } else { for (i = 0; i < rows; i++) { ioff = i * cols; for (j = 0; j < cols; j++) { if (GET_MAPATT(frombuff, (ioff + j), curval)) { BM_set(bm, j, i, (curval == maskval)); } else { BM_set(bm, j, i, 0); /* doesn't mask nulls */ } } } } } return (bm); } /*! \brief Zero mask \param map pointer to BM struct */ void gsbm_zero_mask(struct BM *map) { int numbytes; unsigned char *buf; numbytes = map->bytes * map->rows; buf = map->data; while (numbytes--) { *buf++ = 0; } return; } /*! \brief mask types */ #define MASK_OR 1 #define MASK_ORNOT 2 #define MASK_AND 3 #define MASK_XOR 4 /*! \brief Mask bitmap Must be same size, ORs bitmaps & stores in bmvar \param bmvar bitmap (BM) to changed \param bmcom bitmap (BM) \param mask_type mask type (see mask types macros) \return -1 on failure (bitmap mispatch) \return 0 on success */ static int gsbm_masks(struct BM *bmvar, struct BM *bmcon, const int mask_type) { int i; int varsize, consize, numbytes; varsize = bmvar->rows * bmvar->cols; consize = bmcon->rows * bmcon->cols; numbytes = bmvar->bytes * bmvar->rows; if (bmcon && bmvar) { if (varsize != consize) { G_warning(_("Bitmap mismatch")); return (-1); } if (bmvar->sparse || bmcon->sparse) return (-1); switch (mask_type) { case MASK_OR: for (i = 0; i < numbytes; i++) bmvar->data[i] |= bmcon->data[i]; break; case MASK_ORNOT: for (i = 0; i < numbytes; i++) bmvar->data[i] |= ~bmcon->data[i]; break; case MASK_AND: for (i = 0; i < numbytes; i++) bmvar->data[i] &= bmcon->data[i]; break; case MASK_XOR: for (i = 0; i < numbytes; i++) bmvar->data[i] ^= bmcon->data[i]; break; } return (0); } return (-1); } /*! \brief Mask bitmap (mask type OR) Must be same size, ORs bitmaps & stores in bmvar \param bmvar bitmap (BM) to changed \param bmcom bitmap (BM) \param mask_type mask type (see mask types macros) \return -1 on failure (bitmap mispatch) \return 0 on success */ int gsbm_or_masks(struct BM *bmvar, struct BM *bmcon) { return gsbm_masks(bmvar, bmcon, MASK_OR); } /*! \brief Mask bitmap (mask type ORNOT) Must be same size, ORNOTs bitmaps & stores in bmvar \param bmvar bitmap (BM) to changed \param bmcom bitmap (BM) \param mask_type mask type (see mask types macros) \return -1 on failure (bitmap mispatch) \return 0 on success */ int gsbm_ornot_masks(struct BM *bmvar, struct BM *bmcon) { return gsbm_masks(bmvar, bmcon, MASK_ORNOT); } /*! \brief Mask bitmap (mask type ADD) Must be same size, ADDs bitmaps & stores in bmvar \param bmvar bitmap (BM) to changed \param bmcom bitmap (BM) \param mask_type mask type (see mask types macros) \return -1 on failure (bitmap mispatch) \return 0 on success */ int gsbm_and_masks(struct BM *bmvar, struct BM *bmcon) { return gsbm_masks(bmvar, bmcon, MASK_AND); } /*! \brief Mask bitmap (mask type XOR) Must be same size, XORs bitmaps & stores in bmvar \param bmvar bitmap (BM) to changed \param bmcom bitmap (BM) \param mask_type mask type (see mask types macros) \return -1 on failure (bitmap mispatch) \return 0 on success */ int gsbm_xor_masks(struct BM *bmvar, struct BM *bmcon) { return gsbm_masks(bmvar, bmcon, MASK_XOR); } /*! \brief Update current maps \param surf surface (geosurf) \return 0 \return 1 */ int gs_update_curmask(geosurf * surf) { struct BM *b_mask, *b_topo, *b_color; typbuff *t_topo, *t_mask, *t_color; int row, col, offset, destroy_ok = 1; gsurf_att *coloratt; G_debug(5, "gs_update_curmask(): id=%d", surf->gsurf_id); if (surf->mask_needupdate) { surf->mask_needupdate = 0; surf->norm_needupdate = 1; /* edges will need to be recalculated */ t_topo = gs_get_att_typbuff(surf, ATT_TOPO, 0); if (!t_topo) { surf->mask_needupdate = 1; return (0); } if (surf->nz_topo || surf->nz_color || gs_mask_defined(surf) || t_topo->nm) { b_mask = b_topo = b_color = NULL; if (!surf->curmask) { surf->curmask = BM_create(surf->cols, surf->rows); } else { gsbm_zero_mask(surf->curmask); } if (surf->nz_topo) { /* no_zero elevation */ b_topo = gsbm_make_mask(t_topo, 0.0, surf->rows, surf->cols); } /* make_mask_from_color */ if (surf->nz_color && surf->att[ATT_COLOR].att_src == MAP_ATT) { t_color = gs_get_att_typbuff(surf, ATT_COLOR, 0); coloratt = &(surf->att[ATT_COLOR]); b_color = BM_create(surf->cols, surf->rows); for (row = 0; row < surf->rows; row++) { for (col = 0; col < surf->cols; col++) { offset = row * surf->cols + col; BM_set(b_color, col, row, (NULL_COLOR == gs_mapcolor(t_color, coloratt, offset))); } } } if (gs_mask_defined(surf)) { t_mask = gs_get_att_typbuff(surf, ATT_MASK, 0); if (t_mask->bm) { b_mask = t_mask->bm; destroy_ok = 0; } else { b_mask = BM_create(surf->cols, surf->rows); gs_set_maskmode((int)surf->att[ATT_MASK].constant); for (row = 0; row < surf->rows; row++) { for (col = 0; col < surf->cols; col++) { offset = row * surf->cols + col; BM_set(b_mask, col, row, gs_masked(t_mask, col, row, offset)); } } } } if (b_topo) { G_debug(5, "gs_update_curmask(): update topo mask"); gsbm_or_masks(surf->curmask, b_topo); BM_destroy(b_topo); } if (b_color) { G_debug(5, "gs_update_curmask(): update color mask"); gsbm_or_masks(surf->curmask, b_color); BM_destroy(b_color); } if (t_topo->nm) { G_debug(5, "gs_update_curmask(): update elev null mask"); gsbm_or_masks(surf->curmask, t_topo->nm); } if (b_mask) { G_debug(5, "gs_update_curmask(): update mask mask"); if (t_mask->bm) { if (surf->att[ATT_MASK].constant) { /* invert */ gsbm_or_masks(surf->curmask, t_mask->bm); } else { gsbm_ornot_masks(surf->curmask, t_mask->bm); } } else { gsbm_or_masks(surf->curmask, b_mask); } if (destroy_ok) { BM_destroy(b_mask); } } /* TODO: update surf->zminmasked */ return (1); } else if (surf->curmask) { BM_destroy(surf->curmask); surf->curmask = NULL; surf->zminmasked = surf->zmin; } } return (0); } /*! \brief Print bitmap to stderr \param bm bitmap (BM) */ void print_bm(struct BM *bm) { int i, j; for (i = 0; i < bm->rows; i++) { for (j = 0; j < bm->cols; j++) { fprintf(stderr, "%d ", BM_get(bm, j, i)); } fprintf(stderr, "\n"); } return; }