// a(X-x0)^2 + b(Y-y0)^2 = r^2 static void FillEllipse(IplImage* mask, int setnum, int x0, int y0, int r, int a, int b) { int x,y,F,H; CvSize size = cvGetSize(mask); x = r / sqrt( (double)a ); y = 0; F = -2 * sqrt( (double)a ) * r + a + 2*b; H = -4 * sqrt( (double)a ) * r + 2*a + b; while ( x > 0 ) { for(int i=x0 - x; i<=x0 + x; i++){ SetMaskDataPos(mask, i, y0 + y, setnum); SetMaskDataPos(mask, i, y0 - y, setnum); } if ( F < 0 ) { y++; F += 4 * b * y + 2 * b; H += 4 * b * y; } else if ( H >= 0 ) { x--; F -= 4*a*x; H -= 4*a*x - 2*a; } else { x--; y++; F += 4*b*y - 4*a*x + 2*b; H += 4*b*y - 4*a*x + 2*a; } } }
static void FillMask(IplImage *image, uint8_t setnum, int x, int y) { if(( 0 <= x && x <= image->width -1 )&& (0 <= y && y <= image->height -1 ) ) { uint8_t cl = GetMaskDataPos(image, x, y); if(cl == 255){ ::MessageBox(NULL, "", "", MB_OK); } SetMaskDataPos(image, setnum, x, y); //上 if(GetMaskDataPos(image, x, y-1) == cl){ FillMask(image, setnum, x, y-1); } //右 else if(GetMaskDataPos(image, x+1, y) == cl){ FillMask(image, setnum, x + 1, y); } //下 else if(GetMaskDataPos(image, x, y-1) == cl){ FillMask(image, setnum, x, y-1); } //左 else if(GetMaskDataPos(image, x-1, y) == cl){ FillMask(image, setnum, x-1, y); } } }
/*! maskの範囲lprcをdst_maskにコピーする @param[in] mask マスク @param[in] lprc 範囲 @param[out] dst_mask 出力結果 */ _EXPORT void CutMask(const IplImage *mask, const LPRECT lprc, IplImage *dst_mask) { int x,y; for(y=lprc->top; y<= lprc->bottom; y++){ for(x=lprc->left; x<= lprc->right; x++){ int data = GetMaskDataPos(mask, x, y); SetMaskDataPos(dst_mask, x - lprc->left, y - lprc->top, data); } } }
/*! srcをdstに転送 @param[out] dst 出力先 @param[in] posX dst転送開始位置 @param[in] posY dst転送開始位置 @param[in] width 転送する画像幅 @param[in] height 転送画像高さ @param[in] src 転送元画像 @param[in] startX 転送元画像開始位置 @param[in] startY 転送元画像開始位置 */ _EXPORT void BltMaskToMask(IplImage* dst, int posX, int posY, int width, int height, const IplImage* src, int startX, int startY) { int x,y; for(y=0; y<height; y++){ for(x=0; x<width; x++){ uint8_t data = GetMaskDataPos(src, x + startX, y + startY); SetMaskDataPos(dst, posX + x, posY + y, data); } } }
void MoveSelectImage::MoveImage(LPINPUT_DATA lpd, LPPOINT beforPt) { ImgFile *f = m_pImgEdit->GetActiveFile(); if(f){ int shiftX = lpd->x - beforPt->x; int shiftY = lpd->y - beforPt->y; ImgLayer *l = f->GetSelectLayer(); if(!l){ IEMessageBox("レイヤーが選択されていません。"); } const IplImageExt *ImgExt = l->GetDrawImage(); IplImage* mask = f->GetSelectMask(); move_X += shiftX; move_Y += shiftY; RECT newRc; newRc.top = beforRc.top + shiftY; newRc.bottom = beforRc.bottom + shiftY; newRc.left = beforRc.left + shiftX; newRc.right = beforRc.right + shiftX; // RECT rc; OrRect(&beforRc, &newRc, &rc); //画像の移動 m_editNode->to_rect = newRc; //mask zero clear cvSet(mask, cvScalar(0)); //マスクの移動 for(int y=0; y < move_mask->height; y++){ for(int x=0; x < move_mask->width; x++){ SetMaskDataPos(mask, x + move_X + maskRc.left, y + move_Y + maskRc.top, GetMaskDataPos(move_mask, x, y)); } } //画像の更新 UPDATE_DATA data; data.isAll = false; data.rect = rc; data.update_flag = UPDATE_FLAG::UPDATE_SELECT_LAYER_ALL_NODE; f->PushUpdateData(&data); beforRc = newRc; } }
//四角形のマスクを作る。 void FillRectMask(IplImage* mask, uint8_t setnum, int x, int y, int width, int height) { int x_ = min(x, x + width); int y_ = min(y, y + height); int width_ = abs(width); int height_ = abs(height); for(int iy = y_; iy <= y_ + height_; iy++){ for(int ix = x_; ix <= x_ + width_; ix++){ SetMaskDataPos(mask, ix, iy, setnum); } } }
/*! 線分のマスクを作る。 @param[out] mask マスクの出力先 @param[in] setnum 埋める値 @param[in] start 開始位置 @param[in] end 終了位置 */ void LineMask(IplImage *mask, uint8_t setnum, const CvPoint2D64f *start, const CvPoint2D64f *end) { float t=0.0; CvPoint2D64f d; //傾き CvPoint2D64f p; //end-startの傾きを計算 SubVec2D(&d, end, start); float d_length = Vec2DLength(&d); float rev_d_length = 1.0 / d_length; do{ //p = start + t*d ScaleVec2D(&p, t, &d); AddVec2D(&p, &p , start); //位置pにsetnum書き込み SetMaskDataPos(mask, p.x, p.y, setnum); t += rev_d_length/2.0; }while(t <= 1.0); }
void SoftCircleMask( IplImage* dst, double center_x, double center_y, double r, uint8_t setnum, uint8_t alpha) { assert(dst); assert(r > 0); double inv_alpha = alpha / 255.0; int start_x = (int)(center_x - r); int start_y = (int)(center_y - r); int end_x = (int)(center_x + r + 0.5); int end_y = (int)(center_y + r + 0.5); assert(start_x >= 0); assert(start_y >= 0); assert(end_x < dst->width); assert(end_y < dst->height); int x,y; uint8_t pix; for(y=start_y; y<=end_y; y++){ for(x=start_x; x<=end_x; x++){ double fr = sqrt((double)(x-center_x+0.5)*(x-center_x+0.5)+(y-center_y+0.5)*(y-center_y+0.5)); if(fr < r){ fr = 1.0 - fr/r; pix = (fr*fr) * (3.0-2.0*fr) * setnum*inv_alpha; } else{ pix = 0; } SetMaskDataPos(dst, x, y, pix); } } }
void AddFillCircleMaskAA3( IplImage* dst, double center_x, double center_y, double r, double aa_d, uint8_t setnum, uint8_t alpha) { assert(dst); assert(r > 0); assert(0.0 < aa_d); double aa_min_d = r-aa_d; double aa_max_d = r+aa_d; double inv_alpha = alpha / 255.0; int start_x = (int)(center_x - aa_max_d); int start_y = (int)(center_y - aa_max_d); int end_x = (int)(center_x + aa_max_d); int end_y = (int)(center_y + aa_max_d); if(start_x < 0) start_x=0; if(start_y < 0) start_y=0; if(end_x >= dst->width) end_x = dst->width-1; if(end_y >= dst->height) end_y = dst->height-1; //浮動小数に定数を掛けて整数として計算する int FIXMUL = 32; int HF_FIXMUL = (int)FIXMUL/2.0; int ir = (int)(r * FIXMUL); int icenter_x = (int)(center_x * FIXMUL); int icenter_y = (int)(center_y * FIXMUL); int x,y; for(y=start_y; y<=end_y; y++){ for(x=start_x; x<=end_x; x++){ //int fx = x * FIXMUL - icenter_x; //int fy = y * FIXMUL - icenter_y; //bool inside0 = false; //左上 //bool inside1 = false; //右上 //bool inside2 = false; //左下 //bool inside3 = false; //右下 //if(!is_small){ // if((fx*fx + fy*fy) <= ir*ir) inside0 = true; // if(((fx + FIXMUL)*(fx + FIXMUL) + fy*fy) <= ir*ir) inside1 = true; // if((fx*fx + (fy + FIXMUL)*(fy + FIXMUL)) <= ir*ir) inside2 = true; // if(((fx + FIXMUL)*(fx + FIXMUL) + (fy + FIXMUL)*(fy + FIXMUL)) <= ir*ir) inside3 = true; //} //else{ // is_small = true; //} //bool outside = !inside0 && !inside1 && !inside2 && !inside3; //if(outside){ // continue; //} //bool notaa = inside0 && inside1 && inside2 && inside3; //if(notaa){ // SetMaskDataPos(dst, x, y, setnum*inv_alpha); //} //else{ uint8_t pix; double fr = sqrt((double)(x-center_x+0.5)*(x-center_x+0.5)+(y-center_y+0.5)*(y-center_y+0.5)); if(fr < aa_min_d){ pix = setnum*inv_alpha; } else if(fr >= aa_max_d){ pix = 0; } else{ double tmp = 1.0 - (fr - aa_min_d)/(aa_max_d - aa_min_d); pix = tmp * setnum*inv_alpha; } if(pix > GetMaskDataPos(dst, x, y)){ SetMaskDataPos(dst, x, y, pix); } //} } } }
void AddFillCircleMaskAA( IplImage* dst, double center_x, double center_y, double r, int div, uint8_t setnum, uint8_t alpha) { assert(dst); assert(r > 0); bool is_small = false; if(r <= 3) is_small = true; int start_x = (int)(center_x - r); int start_y = (int)(center_y - r); int end_x = (int)(center_x + r); int end_y = (int)(center_y + r); if(start_x < 0) start_x=0; if(start_y < 0) start_y=0; if(end_x >= dst->width) end_x = dst->width-1; if(end_y >= dst->height) end_y = dst->height-1; //固定小数表現する int FIXMUL = 32; int ir = (int)(r * FIXMUL); int icenter_x = (int)(center_x * FIXMUL); int icenter_y = (int)(center_y * FIXMUL); int dr = (int)(r * div); int dcenter_x = (int)(center_x * div); int dcenter_y = (int)(center_y * div); double dalpha = alpha / 255.0; int x,y; for(y=start_y; y<=end_y; y++){ for(x=start_x; x<=end_x; x++){ int fx = (x << 5) - icenter_x; //x * FIXMUL - icenter_x; int fy = (y << 5) - icenter_y; //y * FIXMUL - icenter_y; bool inside0 = false; //左上 bool inside1 = false; //右上 bool inside2 = false; //左下 bool inside3 = false; //右下 if(!is_small){ if((fx*fx + fy*fy) <= ir*ir) inside0 = true; if(((fx + FIXMUL)*(fx + FIXMUL) + fy*fy) <= ir*ir) inside1 = true; if((fx*fx + (fy + FIXMUL)*(fy + FIXMUL)) <= ir*ir) inside2 = true; if(((fx + FIXMUL)*(fx + FIXMUL) + (fy + FIXMUL)*(fy + FIXMUL)) <= ir*ir) inside3 = true; } else{ inside0 = true; } bool outside = !inside0 && !inside1 && !inside2 && !inside3; if(outside){ continue; } bool notaa = inside0 && inside1 && inside2 && inside3; if(notaa){ SetMaskDataPos(dst, x, y, setnum*dalpha); } else{ // int c = 0; int i,j; for(j=0; j<div; j++){ for(i=0; i<div; i++){ if((x*div+i - dcenter_x)*(x*div+i - dcenter_x) + (y*div+j - dcenter_y)*(y*div+j - dcenter_y) < dr*dr) c++; } } int d = 255* c / (div*div); uint8_t val = setnum*(d/255.0)*dalpha; if(val > GetMaskDataPos(dst, x, y)){ SetMaskDataPos(dst, x, y, val); } } } } }
_EXPORT void RadiallyBlur(const IplImage* src, IplImage* dst, double ef) { assert(src->nChannels == dst->nChannels); int center_x = src->width/2; int center_y = src->height/2; int i,x,y; int xx, yy; int dx, dy; int pat_sum, pat; double rate; double rad, dis, disI; double disMax = sqrt((double)src->height*src->height + src->width*src->width); int r, g, b, a=255; int sampling_r, sampling_g, sampling_b, sampling_a; for(y=0; y<src->height; y++){ for(x=0; x<src->width; x++){ dx = x - center_x; dy = y - center_y; if(dx != 0) rad = atan((double)dy/dx); else rad = _PI_/2.0; dis = sqrt((double)dx*dx + dy*dy); //distance of from center to (x, y) rate = ef * dis / disMax; rate /= (double)NN; pat_sum = 0; for(i=0; i<NN; i++){ if(i == NF) pat = 3; else pat = 1; disI = (double)(i-NF)*rate; xx = (int)(disI*cos(rad)) + x; yy = (int)(disI*sin(rad)) + y; //read pixel switch(src->nChannels){ case 1: a = GetMaskDataPos(src, x, y); sampling_a = a * pat; break; case 3: break; case 4: break; } pat_sum += pat; } //write pixel switch(dst->nChannels){ case 1: SetMaskDataPos(dst, x, y, a/pat_sum); break; case 3: break; case 4: break; } } } }
void MoveSelectImage::OnMouseLButtonDown(LPINPUT_DATA lpd) { move_X = 0; move_Y = 0; startPt.x = beforPt.x = lpd->x; startPt.y = beforPt.y = lpd->y; ImgFile *f = m_pImgEdit->GetActiveFile(); if(f){ int g,b,r,a; ImgLayer* l = f->GetSelectLayer(); if(!l){ IEMessageBox("レイヤーが選択されていません。"); } const IplImageExt *layer_img_ext = l->GetDrawImage(); IplImage *mask = f->GetSelectMask(); //選択範囲が収まる矩形を求める GetMaskRect(mask, &maskRc); //レイヤーの有効範囲を求める layer_img_ext->GetMaxRangeRect(&layer_Rc); // m_editNode = l->CreateEditNode(&maskRc); m_editNode->raster_code = IPLEXT_RASTER_CODE::ALPHA_BLEND; l->PushEditNode(m_editNode); // move_mask = cvCreateImage( cvSize(maskRc.right - maskRc.left, maskRc.bottom - maskRc.top), IPL_DEPTH_8U, 1); // _I8 md; for(int y=maskRc.top; y <= maskRc.bottom; y++){ for(int x=maskRc.left; x <= maskRc.right; x++){ //選択レイヤの画像をコピー layer_img_ext->GetPixel(x, y, &r, &g, &b, &a); //動かす部分のコピーを得る if(md = GetMaskDataPos(mask, x, y)){ layer_img_ext->GetPixel(x, y, &r, &g, &b, &a); m_editNode->edit_img.SetPixel(x-maskRc.left, y-maskRc.top, r, g, b, a); //画像の動かす部分は透明に } else{ //選択されていないところは透明に m_editNode->edit_img.SetPixel(x-maskRc.left, y-maskRc.top, 0, 0, 0, 0); } //mask SetMaskDataPos(move_mask, x-maskRc.left, y-maskRc.top, md); } } beforRc = maskRc; ////画像の更新 //UPDATE_DATA data; //data.isAll = false; //data.rect = maskRc; //data.update_flag = UPDATE_FLAG::UPDATE_SELECT_LAYER; //f->PushUpdateData(&data); } }