/** * Adds to the selection all the pixels matching the specified color. */ bool CxImage::SelectionAddColor(RGBQUAD c, uint8_t level) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; RECT localbox = {head.biWidth,0,0,head.biHeight}; for (int32_t y = 0; y < head.biHeight; y++){ for (int32_t x = 0; x < head.biWidth; x++){ RGBQUAD color = BlindGetPixelColor(x, y); if (color.rgbRed == c.rgbRed && color.rgbGreen == c.rgbGreen && color.rgbBlue == c.rgbBlue) { pSelection[x + y * head.biWidth] = level; if (localbox.top < y) localbox.top = y; if (localbox.left > x) localbox.left = x; if (localbox.right < x) localbox.right = x; if (localbox.bottom > y) localbox.bottom = y; } } } if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = localbox.top + 1; if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left; if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = localbox.right + 1; if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom; return true; }
/** * Adds to the selection all the pixels matching the specified color. */ bool CxImage::SelectionAddColor(RGBQUAD c) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; RECT localbox = {head.biWidth,0,0,head.biHeight}; for (long y = 0; y < head.biHeight; y++){ for (long x = 0; x < head.biWidth; x++){ RGBQUAD color = GetPixelColor(x, y); if (color.rgbRed == c.rgbRed && color.rgbGreen == c.rgbGreen && color.rgbBlue == c.rgbBlue) { pSelection[x + y * head.biWidth] = 255; // set the correct mask bit if (localbox.top < y) localbox.top = y; if (localbox.left > x) localbox.left = x; if (localbox.right < x) localbox.right = x; if (localbox.bottom > y) localbox.bottom = y; } } } if (info.rSelectionBox.top < localbox.top) info.rSelectionBox.top = localbox.top; if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left; if (info.rSelectionBox.right < localbox.right) info.rSelectionBox.right = localbox.right; if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom; return true; }
/** * Adds a single pixel to the existing selection. */ bool CxImage::SelectionAddPixel(int x, int y) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; if (IsInside(x,y)) { pSelection[x + y * head.biWidth] = 255; // set the correct mask bit return true; } return false; }
/** * Adds a single pixel to the existing selection. */ bool CxImage::SelectionAddPixel(int32_t x, int32_t y, uint8_t level) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; if (IsInside(x,y)) { pSelection[x + y * head.biWidth] = level; // set the correct mask bit if (info.rSelectionBox.top <= y) info.rSelectionBox.top = y+1; if (info.rSelectionBox.left > x) info.rSelectionBox.left = x; if (info.rSelectionBox.right <= x) info.rSelectionBox.right = x+1; if (info.rSelectionBox.bottom > y) info.rSelectionBox.bottom = y; return true; } return false; }
/** * Adds an ellipse to the existing selection. */ bool CxImage::SelectionAddEllipse(RECT r) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; long xradius = abs(r.right - r.left)/2; long yradius = abs(r.top - r.bottom)/2; if (xradius==0 || yradius==0) return false; long xcenter = (r.right + r.left)/2; long ycenter = (r.top + r.bottom)/2; if (info.rSelectionBox.left > (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius))); if (info.rSelectionBox.right < (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius))); if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius))); if (info.rSelectionBox.top < (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius))); long xmin = max(0L,min(head.biWidth,xcenter - xradius)); long xmax = max(0L,min(head.biWidth,xcenter + xradius)); long ymin = max(0L,min(head.biHeight,ycenter - yradius)); long ymax = max(0L,min(head.biHeight,ycenter + yradius)); long y,yo; for (y=ymin; y<ycenter; y++){ for (long x=xmin; x<xmax; x++){ yo = (long)(ycenter - yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2))); if (yo<y) pSelection[x + y * head.biWidth] = 255; } } for (y=ycenter; y<ymax; y++){ for (long x=xmin; x<xmax; x++){ yo = (long)(ycenter + yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2))); if (yo>y) pSelection[x + y * head.biWidth] = 255; } } return true; }
/** * Adds an ellipse to the existing selection. */ bool CxImage::SelectionAddEllipse(RECT r, uint8_t level) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; int32_t xradius = abs(r.right - r.left)/2; int32_t yradius = abs(r.top - r.bottom)/2; if (xradius==0 || yradius==0) return false; int32_t xcenter = (r.right + r.left)/2; int32_t ycenter = (r.top + r.bottom)/2; if (info.rSelectionBox.left > (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius))); if (info.rSelectionBox.right <= (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius + 1))); if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius))); if (info.rSelectionBox.top <= (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius + 1))); int32_t xmin = max(0L,min(head.biWidth,xcenter - xradius)); int32_t xmax = max(0L,min(head.biWidth,xcenter + xradius + 1)); int32_t ymin = max(0L,min(head.biHeight,ycenter - yradius)); int32_t ymax = max(0L,min(head.biHeight,ycenter + yradius + 1)); int32_t y,yo; for (y=ymin; y<min(ycenter,ymax); y++){ for (int32_t x=xmin; x<xmax; x++){ yo = (int32_t)(ycenter - yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2))); if (yo<y) pSelection[x + y * head.biWidth] = level; } } for (y=ycenter; y<ymax; y++){ for (int32_t x=xmin; x<xmax; x++){ yo = (int32_t)(ycenter + yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2))); if (yo>y) pSelection[x + y * head.biWidth] = level; } } return true; }
/** * Adds a rectangle to the existing selection. */ bool CxImage::SelectionAddRect(RECT r) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; RECT r2; if (r.left<r.right) {r2.left=r.left; r2.right=r.right; } else {r2.left=r.right ; r2.right=r.left; } if (r.bottom<r.top) {r2.bottom=r.bottom; r2.top=r.top; } else {r2.bottom=r.top ; r2.top=r.bottom; } if (info.rSelectionBox.top < r2.top) info.rSelectionBox.top = max(0L,min(head.biHeight,r2.top)); if (info.rSelectionBox.left > r2.left) info.rSelectionBox.left = max(0L,min(head.biWidth,r2.left)); if (info.rSelectionBox.right < r2.right) info.rSelectionBox.right = max(0L,min(head.biWidth,r2.right)); if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0L,min(head.biHeight,r2.bottom)); long ymin = max(0L,min(head.biHeight,r2.bottom)); long ymax = max(0L,min(head.biHeight,r2.top)); long xmin = max(0L,min(head.biWidth,r2.left)); long xmax = max(0L,min(head.biWidth,r2.right)); for (long y=ymin; y<ymax; y++) memset(pSelection + xmin + y * head.biWidth, 255, xmax-xmin); return true; }
/** * Adds a rectangle to the existing selection. */ bool CxImage::SelectionAddRect(Rect r, uint8_t level) { if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; Rect r2; if (r.left<r.right) {r2.left=r.left; r2.right=r.right; } else {r2.left=r.right ; r2.right=r.left; } if (r.bottom<r.top) {r2.bottom=r.bottom; r2.top=r.top; } else {r2.bottom=r.top ; r2.top=r.bottom; } if (info.rSelectionBox.top <= r2.top) info.rSelectionBox.top = max(0,min(head.biHeight,r2.top+1)); if (info.rSelectionBox.left > r2.left) info.rSelectionBox.left = max(0,min(head.biWidth,r2.left)); if (info.rSelectionBox.right <= r2.right) info.rSelectionBox.right = max(0,min(head.biWidth,r2.right+1)); if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0,min(head.biHeight,r2.bottom)); int32_t ymin = max(0,min(head.biHeight,r2.bottom)); int32_t ymax = max(0,min(head.biHeight,r2.top+1)); int32_t xmin = max(0,min(head.biWidth,r2.left)); int32_t xmax = max(0,min(head.biWidth,r2.right+1)); for (int32_t y=ymin; y<ymax; y++) memset(pSelection + xmin + y * head.biWidth, level, xmax-xmin); return true; }
/** * Adds a polygonal region to the existing selection. points points to an array of POINT structures. * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon. * npoints specifies the number of POINT structures in the array pointed to by points. */ bool CxImage::SelectionAddPolygon(POINT *points, long npoints) { if (points==NULL || npoints<3) return false; if (pSelection==NULL) SelectionCreate(); if (pSelection==NULL) return false; BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1); RECT localbox = {head.biWidth,0,0,head.biHeight}; long x,y,i=0; POINT *current,*next,*start; //trace contour while (i < npoints){ current = &points[i]; if (current->x!=-1){ if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i]; if ((i+1)==npoints || points[i+1].x==-1) next = start; else next = &points[i+1]; float beta; if (current->x != next->x){ beta = (float)(next->y - current->y)/(float)(next->x - current->x); if (current->x < next->x){ for (x=current->x; x<=next->x; x++){ y = (long)(current->y + (x - current->x) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } else { for (x=current->x; x>=next->x; x--){ y = (long)(current->y + (x - current->x) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } } if (current->y != next->y){ beta = (float)(next->x - current->x)/(float)(next->y - current->y); if (current->y < next->y){ for (y=current->y; y<=next->y; y++){ x = (long)(current->x + (y - current->y) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } else { for (y=current->y; y>=next->y; y--){ x = (long)(current->x + (y - current->y) * beta); if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255; } } } } RECT r2; if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; } if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; } if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1)); if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1)); if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1)); if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1)); i++; } //fill the outer region long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom); POINT* pix = (POINT*)calloc(npix,sizeof(POINT)); BYTE back=0, mark=1; long fx, fy, fxx, fyy, first, last,xmin,xmax,ymin,ymax; for (int side=0; side<4; side++){ switch(side){ case 0: xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1; break; case 1: xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1; break; case 2: xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1; break; case 3: xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1; break; } //fill from the border points for(y=ymin;y<ymax;y++){ for(x=xmin;x<xmax;x++){ if (plocal[x+y*head.biWidth]==0){ // Subject: FLOOD FILL ROUTINE Date: 12-23-97 (00:57) // Author: Petter Holmberg Code: QB, QBasic, PDS // Origin: [email protected] Packet: GRAPHICS.ABC first=0; last=1; while(first!=last){ fx = pix[first].x; fy = pix[first].y; fxx = fx + x; fyy = fy + y; do { if ((plocal[fxx + fyy*head.biWidth] == back) && fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) { plocal[fxx + fyy*head.biWidth] = mark; if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy - 1; last++; if (last == npix) last = 0; } if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy + 1; last++; if (last == npix) last = 0; } } else { break; } fx++; fxx++; } while(1); fx = pix[first].x - 1; fy = pix[first].y; fxx = fx + x; fyy = fy + y; do { if ((plocal[fxx + fyy*head.biWidth] == back) && fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top ) { plocal[fxx + (y + fy)*head.biWidth] = mark; if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy - 1; last++; if (last == npix) last = 0; } if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){ pix[last].x = fx; pix[last].y = fy + 1; last++; if (last == npix) last = 0; } } else { break; } fx--; fxx--; } while(1); first++; if (first == npix) first = 0; } } } } } //transfer the region long yoffset; for (y=localbox.bottom; y<=localbox.top; y++){ yoffset = y * head.biWidth; for (x=localbox.left; x<=localbox.right; x++) if (plocal[x + yoffset]!=1) pSelection[x + yoffset]=255; } if (info.rSelectionBox.top < localbox.top) info.rSelectionBox.top = localbox.top+1; if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left; if (info.rSelectionBox.right < localbox.right) info.rSelectionBox.right = localbox.right+1; if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom; free(plocal); free(pix); return true; }