//--------------------------------------------------------------------------- #include #include #pragma hdrstop #include "SpreadFill.h" #include "MainImage.h" #include "Palette.h" #include "Undo.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "Selector" #pragma link "TPSpin" #pragma resource "*.dfm" //--------------------------------------------------------------------------- #define IDS_MULTIPLEGRADE StringTable[0] #define IDS_SINGLEGRADE StringTable[1] #define IDS_WAVEFREQUENCY StringTable[2] #define IDS_WAVEHEIGHT StringTable[3] #define IDS_LINEAR StringTable[4] #define IDS_CIRCULATE StringTable[5] #define IDS_READYTODRAW StringTable[6] #define IDS_COLORSELECT StringTable[7] //--------------------------------------------------------------------------- TSpreadFillForm *SpreadFillForm; //--------------------------------------------------------------------------- __fastcall TSpreadFillForm::TSpreadFillForm(TComponent* Owner) : TForm(Owner) { hWnd = ((TWinControl *)Owner)->Handle; //=================================================================== StringTable.Create(DirectoryBin, Language, "SpreadFill"); SetSmallFont(Font); SetSmallFont(StaticTextColor->Font); sbMultiple->Caption = IDS_MULTIPLEGRADE; sbSingle->Caption = IDS_SINGLEGRADE; Label2->Caption = IDS_WAVEFREQUENCY; Label3->Caption = IDS_WAVEHEIGHT; SpeedButtonPosition->Caption = IDS_COMMON_POSITION; StaticTextColor->Caption = IDS_READYTODRAW; SpeedButtonNew->Hint = IDS_COMMON_NEW; SpeedButtonAll->Hint = IDS_COMMON_ALL; SpeedButtonOne->Hint = IDS_COMMON_BLOCKCOLOR; SpeedButtonDelete->Hint = IDS_COMMON_INSERTCOLOR; SpeedButtonBefore->Hint = IDS_COMMON_BEFORECOLOR; ImageView->Hint = IDS_LINEAR; Image1->Hint = IDS_LINEAR; Image2->Hint = IDS_CIRCULATE; //===================================================================== } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::FormCreate(TObject *Sender) { // } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::ImageViewClick(TObject *Sender) { if (Item) { ExitItem(); InitItem(0); } else { ExitItem(); InitItem(1); } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpeedButtonNewClick(TObject *Sender) { ColorSelector->Initial(); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::StaticTextColorClick(TObject *Sender) { if (!Bpp24) { if (bColor) { ExitItem(); StaticTextColor->Caption = IDS_READYTODRAW; ColorSelector->Enabled = false; SpeedButtonNew->Enabled = false; SpeedButtonAll->Enabled = false; SpeedButtonOne->Enabled = false; SpeedButtonDelete->Enabled = false; SpeedButtonBefore->Enabled = false; SpeedButtonPosition->Enabled = true; bColor = false; } else { StaticTextColor->Caption = IDS_COLORSELECT; ColorSelector->Enabled = true; SpeedButtonNew->Enabled = true; SpeedButtonAll->Enabled = true; SpeedButtonOne->Enabled = true; SpeedButtonDelete->Enabled = true; SpeedButtonBefore->Enabled = true; SpeedButtonPosition->Down = false; SpeedButtonPosition->Enabled = false; bColor = true; } } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpeedButtonAllClick(TObject *Sender) { TCursor cursor; cursor = Screen->Cursor; Screen->Cursor = crHourGlass; if (MainImageForm->WorkArea->Mask) MainImageForm->SearchWorkAreaColor(ColorSelector->ChoiceColor); else MainImageForm->SearchWholeColor(ColorSelector->ChoiceColor); ColorSelector->Invalid(); Screen->Cursor = cursor; } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpeedButtonOneClick(TObject *Sender) { if (SpeedButtonOne->Down) SpeedButtonOne->Hint = IDS_COMMON_ONECOLOR; else SpeedButtonOne->Hint = IDS_COMMON_BLOCKCOLOR; } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpeedButtonDeleteClick(TObject *Sender) { if (SpeedButtonDelete->Down) SpeedButtonDelete->Hint=IDS_COMMON_DELETECOLOR; else SpeedButtonDelete->Hint = IDS_COMMON_INSERTCOLOR; } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::TrackBarChange(TObject *Sender) { if (PosMax) if (seGap->Value == 1) Gap[Pos] = 1; else Gap[Pos] = seGap->Value-1; Pos = TrackBar->Position; if (PosMax) { seGap->Value = Gap[Pos]+1; seGap->Enabled = true; } else { seGap->Enabled = false; } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::UpDownClick(TObject *Sender, TUDBtnType Button) { TrackBar->Max = UpDown->Position-1; if ((pal) && (Pos == 0)) { TrackBar->Position = TrackBar->Max; Pos = TrackBar->Position; } bChange = true; View(); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::seGapChange(TObject *Sender) { if (seGap->Text.Length()>0) { if (seGap->Value < 1) seGap->Value = 1; if (seGap->Value > 255) seGap->Value = 255; UpDown->Enabled = true; if (seGap->Value == 1) Gap[Pos] = 1; else Gap[Pos] = seGap->Value-1; bChange = true; if (EnoughPalette()) View(); else { Gap[Pos] = 1; seGap->Value = 2; EXCEPTION_MESSAGE_OK(EC_COLOR_OVERFLOW); } } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpinEditClick(TObject *Sender) { ((TPSpinEdit *) Sender)->SetFocus(); ((TPSpinEdit *) Sender)->SelectAll(); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpeedButtonPositionClick(TObject *Sender) { if (PosMax) { if (seGap->Value == 1) seGap->Value = 2; Gap[Pos] = seGap->Value-1; } ExitItem(); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::SpeedButtonBeforeClick(TObject *Sender) { ColorSelector->LoadFromFile(DirectoryItem+"\\SpreadFill.Ini", "ColorSelect"); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::sbMultipleClick(TObject *Sender) { if (sbMultiple->Down) { PanelMultiple->BringToFront(); mono = false; SpeedButtonPosition->Down = false; ClientHeight = 270; Parent->Height = ParentHeight+ClientHeight; } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::sbSingleClick(TObject *Sender) { if (sbSingle->Down) { PanelSingle->BringToFront(); mono = true; monoItem = 0; Image1->BringToFront(); FGColor = PaletteForm->DIB256Palette->GetFGCOLORREF(24); ImagePreview->Canvas->Brush->Color = (TColor)FGColor; ImagePreview->Canvas->FillRect(Rect(0, 0, ImagePreview->Width, ImagePreview->Height)); SpeedButtonPosition->Down = true; ClientHeight = 160; Parent->Height = ParentHeight+ClientHeight; } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::ImageClick(TObject *Sender) { TImage *s = (TImage *) Sender; if (s->Tag == 0) { monoItem = 1; Image2->BringToFront();; } else { monoItem = 0; Image1->BringToFront(); } } ///////////////////////////////////////////////////////////////////////////// //----------------------------/Private Method/------------------------------- ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::InitItem(int i) { Item = i; if (Item) { ImageView->Hint = IDS_CIRCULATE; } else { ImageView->Hint = IDS_LINEAR; } View(); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::ExitItem() { if (SpeedButtonPosition->Down) { if (SpeedButtonOne->Down==false) { if (step>0) { if (IsDraw) MainImageForm->DrawRectangleLocate(Temp); IsDraw = false; step = 0; } } } else { if (step>0) { if (IsDraw) MainImageForm->DrawLineLocate(First, Second); IsDraw = false; step = 0; } } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::View() { int i, j ,k, l, x, y, d, m, ec; Byte r, g, b; RGBQUAD rgb[256]; Byte *sl, *scan; if (SpreadColor) { HeapFree(GetProcessHeap(), 0, SpreadColor); SpreadColor = NULL; } SpreadCount = 1; for (i=0; iMax; i++) SpreadCount = SpreadCount+Gap[i]; SpreadColor = (TColor*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SpreadCount*sizeof(TColor)); if (SpreadColor == NULL) { ec = EC_MEMORY_LACK; goto fail; } cp = SpreadColor; for (i=0; iMax; i++) { rgb[0] = MainImageForm->Palette->ColorData[ColorIndex[i]]->RGB; rgb[255] = MainImageForm->Palette->ColorData[ColorIndex[i+1]]->RGB; for (j=0; jPalette->ColorData[ColorIndex[TrackBar->Max]]->RGB.rgbRed; g = MainImageForm->Palette->ColorData[ColorIndex[TrackBar->Max]]->RGB.rgbGreen; b = MainImageForm->Palette->ColorData[ColorIndex[TrackBar->Max]]->RGB.rgbBlue; *cp = RGB2TColor(r, g, b); j = MainImageForm->Palette->UseColor+1; cp = SpreadColor; if (j + SpreadCount >= 252) { ec = EC_COLOR_OVERFLOW; goto fail; } for (i=0; iPicture->Bitmap->PixelFormat = pf8bit; ImageGrade->Picture->Bitmap->Width = 209; ImageGrade->Picture->Bitmap->Height = 33; SetDIBColorTable(ImageGrade->Picture->Bitmap->Canvas->Handle, 0, 256, rgb); ImageView->Picture->Bitmap->PixelFormat = pf8bit; ImageView->Picture->Bitmap->Width = 112; ImageView->Picture->Bitmap->Height = 112; SetDIBColorTable(ImageView->Picture->Bitmap->Canvas->Handle, 0, 256, rgb); j = MainImageForm->Palette->UseColor+1; l = ImageGrade->Width; k = ((l-1)/(SpreadCount-1))+1; for (y=0; yHeight; y++) { scan = (Byte*) ImageGrade->Picture->Bitmap->ScanLine[y]; for (x=0; xWidth; x++) { d = x/k; m = x%k; if (rand() % k > m) scan[x] = (Byte) j+d; else scan[x] = (Byte) j+d+1; } } ImageGrade->Repaint(); if (Item==0) { l = ImageView->Width; k = ((l-1)/(SpreadCount-1))+1; for (y=0; yHeight; y++) { sl = (Byte*) ImageView->Picture->Bitmap->ScanLine[y]; for (x=0; xWidth; x++) { d = x/k; m = x%k; if (rand() % k > m) sl[x] = (Byte) j+d; else sl[x] = Byte(j+d+1); } } ImageView->Repaint(); } else { k = (80/(SpreadCount-1))+1; for (y=-55; y<=55; y++) { sl = (Byte*) ImageView->Picture->Bitmap->ScanLine[y+55]; for (x=-55; x<=55; x++) { l = sqrt(x*x+y*y); d = l/k; m = l%k; if (rand() % k > m) sl[x+55] = (Byte) j+d; else sl[x+55] = (Byte) j+d+1; } } ImageView->Repaint(); } return; fail: EXCEPTION_MESSAGE_OK(ec); if (ec == EC_MEMORY_LACK) PostMessage(hWnd, TPM_EXITFUNCTION, 0, 0); } //--------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::FillSingle8(Byte *p, int x) { return *(p + x) == (Byte)FillColor; } //---------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::FillMulti8(Byte *p, int x) { return ColorSelector->Number[*(p+x)] < 255; } //---------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::FillSingle24(Byte *p, int x) { COLORREF c; p += 3*x; GetPixel24(p, c); return c == FillColor; } //---------------------------------------------------------------------------- int xTransfer(int x, int y, double ct, double st) { int k = x*ct+y*st+0.5; return k; } //--------------------------------------------------------------------------- TPoint xyTransfer(int x, int y, double ct, double st) { return Point(x*ct+y*st+0.5, -x*st+y*ct+0.5); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::GoSpreadFill() { int pn = 0; TCursor cursor = Screen->Cursor; Screen->Cursor = crHourGlass; RECT r; bool undoSw = false; r = Rect(0, 0, MainImageForm->iMainImage->Bitmap->Width, MainImageForm->iMainImage->Bitmap->Height); if ((undoSw = MainImageForm->UndoSave(UK_ALL, r)) == false) goto fail; if (seGap->Value>=2) { if (bChange) { Index = MainImageForm->Palette->UseColor+1; for (int i = 0; i< TrackBar->Max; i++) pn += (Gap[i]+1); if ((pn + Index + 1) >= 252) { if (undoSw == true) Undo->RemoveLast(); EXCEPTION_MESSAGE_OK(EC_COLOR_OVERFLOW); Screen->Cursor = cursor; PostMessage(hWnd, TPM_EXITFUNCTION, 0, 0); return; } MainImageForm->Palette->MakeSpread(TrackBar->Max, ColorIndex, 5, Gap, 4); bChange = false; } } if (MainImageForm->iMainImage->Bitmap->BitsPerPixel == 8) { if (Item == 0) { if (!LinearSpreadFill_8()) goto fail; } else { if (!CirculateSpreadFill_8()) goto fail; } } else { if (Item ==0) { if (!LinearSpreadFill_24()) goto fail; } else { if (!CirculateSpreadFill_24()) goto fail; } } ::RepaintColor(); Screen->Cursor = cursor; return; fail: Screen->Cursor = cursor; if (undoSw == true) Undo->RemoveLast(); EXCEPTION_MESSAGE_OK(EC_MEMORY_LACK); } //--------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::LinearSpreadFill_8() { int i, j, k, d, m, x, y; double dx, dy, Theta, st, ct; TRect rect[2]; bool sw; Byte *sl, *mp; TPBitmap *Mask = NULL; if ((Mask = new TPBitmap) == NULL) goto fail; dx = Second.x-First.x; dy = Second.y-First.y; if (dx || dy) Theta = atan2(dy, dx); else Theta = 0; st = sin(Theta); ct = cos(Theta); if (ColorSelector->Count==0) { FillColor = MainImageForm->iMainImage->Bitmap->GetPixelColor(First.x, First.y); if (MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillSingle8, NULL, rect[0], Mask) == false) goto fail; } else { if (MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillMulti8, NULL, rect[0], Mask) == false) goto fail; } #ifdef TPDEBUG if (!Mask->Lock()) SHOWDEBUG; #else Mask->Lock(); #endif sw = true; for (y=rect[0].Top; yScanLine(y); for (x=rect[0].Left; x> 3)) & (0x80 >> (x & 7))) { i = xTransfer(x, y, ct, st); if (sw) { rect[1].Left = i; rect[1].Right = rect[1].Left; sw = false; } else { if (irect[1].Right) rect[1].Right = i; } } } } j = Index; k = (rect[1].Right-rect[1].Left)/(SpreadCount-1)+1; if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y=rect[0].Top; yiMainImage->Bitmap->GetScanLine(y); mp = Mask->ScanLine(y); for (x=rect[0].Left; x> 3)) & (0x80 >> (x &7))) { i = xTransfer(x, y, ct, st)-rect[1].Left; d = i/k; m = i%k; if (rand() % k > m) *(sl+x) = (Byte) j+d; else *(sl+x) = (Byte) j+d+1; } } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); delete Mask; return true; fail: if (Mask) delete Mask; MainImageForm->iMainImage->Bitmap->StopScanLine(); return false; } //--------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::CirculateSpreadFill_8() { int i, j, k, d, m, x, y, xx, yy; TRect rect; Byte *sl, *mp; double max, l; TPBitmap *Mask = NULL; if((Mask = new TPBitmap) == NULL) goto fail; if (ColorSelector->Count==0) { FillColor = MainImageForm->iMainImage->Bitmap->GetPixelColor(First.x, First.y); if(MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillSingle8, NULL, rect, Mask) == false) goto fail; } else { if(MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillMulti8, NULL, rect, Mask) == false) goto fail; } #ifdef TPDEBUG if (!Mask->Lock()) SHOWDEBUG; #else Mask->Lock() ; #endif max = 0; for (y=rect.Top; yScanLine(y); yy = y-First.y; for (x=rect.Left; x> 3)) & (0x80 >> (x & 7))) { xx = x-First.x; l = sqrt(xx*xx+yy*yy); if (l>max) max = l; } } } j = Index; k = max/(SpreadCount-1)+1; if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y=rect.Top; yiMainImage->Bitmap->GetScanLine(y); mp = Mask->ScanLine(y); yy = y-First.y; for (x=rect.Left; x> 3)) & (0x80 >> (x&7))) { xx = x-First.x; i = sqrt(xx*xx+yy*yy); d = i/k; m = i%k; if (rand() % k > m) *(sl+x) = (Byte) j+d; else *(sl+x) = (Byte) j+d+1; } } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); delete Mask; return true; fail : if (Mask) delete Mask; MainImageForm->iMainImage->Bitmap->StopScanLine(); return false; } //--------------------------------------------------------------------------- COLORREF TSpreadFillForm::ColorMap2COLORREF(int i) { RGBQUAD rgb = MainImageForm->Palette->ColorData[i]->RGB; return rgb.rgbRed | (rgb.rgbGreen << 8) | (rgb.rgbBlue << 16); } //--------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::LinearSpreadFill_24() { int i, j, k, d, m, x, y; double dx, dy, Theta, st, ct; TRect rect[2]; RECT rc; bool sw; Byte *ssl, *mp, mm; COLORREF crrf; TPBitmap *Mask = NULL; dx = Second.x-First.x; dy = Second.y-First.y; if (dx || dy) Theta = atan2(dy, dx); else Theta = 0; st = sin(Theta); ct = cos(Theta); if (MainImageForm->WorkArea->Mask) { rc = MainImageForm->WorkArea->Range; if (L_IsPtInBitmapRgn(MainImageForm->iMainImage->Bitmap->Handle, First.y, First.x)) { rect[0] = Rect(rc.left, rc.top, rc.right, rc.bottom); if (!MainImageForm->WorkArea->Mask->StartScanLine()) goto fail; sw = true; for (y=rect[0].Top; yWorkArea->Mask->GetScanLine(y-rect[0].Top); mm = 0x80; for (x=rect[0].Left; xrect[1].Right) rect[1].Right = i; } } if (mm == 1) { mp++; mm = 0x80; } else mm >>= 1; } } j = Index; k = (rect[1].Right-rect[1].Left)/(SpreadCount-1)+1; if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y=rect[0].Top; yiMainImage->Bitmap->GetScanLine(y) + 3*rect[0].Left; mp = MainImageForm->WorkArea->Mask->GetScanLine(y-rect[0].Top); mm = 0x80; for (x=rect[0].Left; x m) crrf = ColorMap2COLORREF(j+d); else crrf = ColorMap2COLORREF(j+d+1); SetPixel24(ssl, crrf); } if (mm == 1) { mp++; mm = 0x80; } else mm >>= 1; } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->WorkArea->Mask->StopScanLine(); MainImageForm->iMainImage->Bitmap->StopScanLine(); } else { goto next; } } else { next: if((Mask = new TPBitmap) == NULL) goto fail; FillColor = MainImageForm->iMainImage->Bitmap->GetPixelColor(First.x, First.y); if (MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillSingle24, NULL, rect[0], Mask) == false) goto fail; #ifdef TPDEBUG if (!Mask->Lock()) SHOWDEBUG; #else Mask->Lock(); #endif sw = true; for (y=rect[0].Top; yScanLine(y); for (x=rect[0].Left; x> 3)) & (0x80 >> (x & 7))) { i = xTransfer(x, y, ct, st); if (sw) { rect[1].Left = i; rect[1].Right = rect[1].Left; sw = false; } else { if (irect[1].Right) rect[1].Right = i; } } } } j = Index; k = (rect[1].Right-rect[1].Left)/(SpreadCount-1)+1; if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y=rect[0].Top; yiMainImage->Bitmap->GetScanLine(y) + 3*rect[0].Left; mp = Mask->ScanLine(y); for (x=rect[0].Left; x> 3)) & (0x80 >> (x &7))) { i = xTransfer(x, y, ct, st)-rect[1].Left; d = i/k; m = i%k; if (rand() % k > m) crrf = ColorMap2COLORREF(j+d); else crrf = ColorMap2COLORREF(j+d+1); SetPixel24(ssl, crrf); } } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); delete Mask; } return true; fail : if (Mask) delete Mask; if (MainImageForm->WorkArea->Mask) MainImageForm->WorkArea->Mask->StopScanLine(); MainImageForm->iMainImage->Bitmap->StopScanLine(); return false; } //--------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::CirculateSpreadFill_24() { int i, j, k, d, m, x, y, xx, yy; TRect rect; RECT rc; Byte *ssl, *mp, mm; double max, l; COLORREF crrf; TPBitmap *Mask = NULL; if (MainImageForm->WorkArea->Mask) { rc = MainImageForm->WorkArea->Range; if (L_IsPtInBitmapRgn(MainImageForm->iMainImage->Bitmap->Handle, First.y, First.x)) { max = 0; rect = Rect(rc.left, rc.top, rc.right, rc.bottom); if (!MainImageForm->WorkArea->Mask->StartScanLine()) goto fail; for (y=rect.Top; yWorkArea->Mask->GetScanLine(y - rect.Top); yy = y-First.y; mm = 0x80; for (x=rect.Left; xmax) max = l; } if (mm == 1) { mp++; mm = 0x80; } else mm >>= 1; } } j = Index; k = max/(SpreadCount-1)+1; if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y=rect.Top; yiMainImage->Bitmap->GetScanLine(y) + 3*rect.Left; mp = MainImageForm->WorkArea->Mask->GetScanLine(y - rect.Top); yy = y-First.y; mm = 0x80; for (x=rect.Left; x m) crrf = ColorMap2COLORREF(j+d); else crrf = ColorMap2COLORREF(j+d+1); SetPixel24(ssl, crrf); } if (mm == 1) { mp++; mm = 0x80; } else mm >>= 1; } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); MainImageForm->WorkArea->Mask->StopScanLine(); } else goto next; } else { next: if((Mask = new TPBitmap) == NULL) goto fail; FillColor = MainImageForm->iMainImage->Bitmap->GetPixelColor(First.x, First.y); if(MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillSingle24, NULL, rect, Mask) == false) goto fail; #ifdef TPDEBUG if (!Mask->Lock()) SHOWDEBUG; #else Mask->Lock(); #endif max = 0; for (y=rect.Top; yScanLine(y); yy = y-First.y; for (x=rect.Left; x> 3)) & (0x80 >> (x & 7))) { xx = x-First.x; l = sqrt(xx*xx+yy*yy); if (l>max) max = l; } } } j = Index; k = max/(SpreadCount-1)+1; if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y=rect.Top; yiMainImage->Bitmap->GetScanLine(y) + 3*rect.Left; mp = Mask->ScanLine(y); yy = y-First.y; for (x=rect.Left; x> 3)) & (0x80 >> (x&7))) { xx = x-First.x; i = sqrt(xx*xx+yy*yy); d = i/k; m = i%k; if (rand() % k > m) crrf = ColorMap2COLORREF(j+d); else crrf = ColorMap2COLORREF(j+d+1); SetPixel24(ssl, crrf); } } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); delete Mask; } return true; fail : if (Mask) delete Mask; if (MainImageForm->WorkArea->Mask) MainImageForm->WorkArea->Mask->StopScanLine(); MainImageForm->iMainImage->Bitmap->StopScanLine(); return false; } //-------------------------------------------------------------------------- void __fastcall TSpreadFillForm::GoSingleSpread() { bool undoSw = false; TCursor cursor = Screen->Cursor; Screen->Cursor = crHourGlass; RECT r = Rect(0, 0, MainImageForm->iMainImage->Bitmap->Width, MainImageForm->iMainImage->Bitmap->Height); if ((undoSw = MainImageForm->UndoSave(UK_ALL, r)) == false) goto fail; if (!monoItem) { if (LinearSingleSpread() == false) goto fail; } else { if (CirculateSingleSpread() == false) goto fail; } ::RepaintColor(); Screen->Cursor = cursor; return; fail: Screen->Cursor = cursor; if (undoSw == true) Undo->RemoveLast(); EXCEPTION_MESSAGE_OK(EC_MEMORY_LACK); } //-------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::LinearSingleSpread() { int i, j, x, y, hei, dx, dy; double st, ct, Theta; TRect rect[2]; bool sw; Byte *ssl, *mp; Byte RGB[3][3]; COLORREF crrf; TPoint center, start, o; int WaveLength, tempdeg; double WaveHeight, ratio, r, temprad, tempdouble; double *wh = NULL; short *eLen = NULL, sLen; TPBitmap *Mask = NULL; dx = Second.x-First.x; dy = Second.y-First.y; if (dx || dy) Theta = atan2(dy, dx); else Theta = 0; st = sin(Theta); ct = cos(Theta); if ((Mask = new TPBitmap) == NULL) goto fail; FillColor = MainImageForm->iMainImage->Bitmap->GetPixelColor(First.x, First.y); if(MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillSingle24, NULL, rect[0], Mask) == false) goto fail; #ifdef TPDEBUG if (!Mask->Lock()) SHOWDEBUG; #else Mask->Lock(); #endif sw = true; for (y=rect[0].Top; yScanLine(y); for (x=rect[0].Left; x> 3)) & (0x80 >> (x & 7))) { o = xyTransfer(x, y, ct, st); if (sw) { rect[1].Left = o.x; rect[1].Right = rect[1].Left; rect[1].Top = o.y; rect[1].Bottom = rect[1].Top; sw = false; } else { if (o.xrect[1].Right) rect[1].Right = o.x; if (o.yrect[1].Bottom) rect[1].Bottom = o.y; } } } } WaveLength = spEditWlength->Value; WaveHeight = spEditWheight->Value / 100.0; center = xyTransfer(First.x, First.y, ct, st); start = xyTransfer(Second.x, Second.y, ct, st); RGB[0][0] = FillColor & 0xFF; RGB[0][1] = (FillColor >> 8) & 0xFF; RGB[0][2] = (FillColor >> 16) & 0xFF; RGB[1][0] = FGColor & 0xFF; RGB[1][1] = (FGColor >> 8) & 0xFF; RGB[1][2] = (FGColor >> 16) & 0xFF; hei = rect[1].Bottom - rect[1].Top; if (hei == 0) hei = 1; eLen = (short *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, hei*sizeof(short)); if (eLen == NULL) goto fail; for (y = rect[1].Top; y < rect[1].Bottom; y++) { for (x = rect[1].Right - 1; x >= rect[1].Left; x--) { o = xyTransfer(x, y, ct, -st); if (rect[0].Top <= o.y && rect[0].Bottom > o.y && rect[0].Left <= o.x && rect[0].Right > o.x) { mp = Mask->ScanLine(o.y); if (*(mp + (o.x>>3)) & (0x80 >> (o.x&7))) break; } } eLen[y - rect[1].Top] = x - center.x; } if (eLen[start.y - rect[1].Top]) ratio = double(start.x - center.x) / eLen[start.y - rect[1].Top]; else ratio = double(start.x - center.x); wh = (double *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2*WaveLength*sizeof(double)); if (wh == NULL) goto fail; for (i = 0; i < 2*WaveLength; i++) { wh[i] = WaveHeight * (rand()%1001 - 500) / 1000.0; // -0.005 - 0.5 } if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y = rect[0].Top; y < rect[0].Bottom; y++) { ssl = MainImageForm->iMainImage->Bitmap->GetScanLine(y) + 3*rect[0].Left; for (x = rect[0].Left; x < rect[0].Right; x++, ssl += 3) { mp = Mask->ScanLine(y); if (*(mp + (x >> 3)) & (0x80 >> (x & 7))) { o = xyTransfer(x, y, ct, st); o.x -= center.x; o.y -=rect[1].Top; j = 360 * o.y / hei; // 0 - 360 tempdeg = j * WaveLength / 180; // 0 - 2* WaveLength if (tempdeg >= 2*WaveLength) tempdeg = tempdeg - 1; temprad = WaveLength * j * M_PI / 180; tempdouble = wh[tempdeg] * sin(temprad); // -0.5 - 0.5 if (o.y >= hei) o.y = hei - 1; sLen = eLen[o.y] * ratio * (1.0 + tempdouble); if (o.x >= sLen) { if ((eLen[o.y] - sLen) == 0) r = 0; else r = (double) (o.x - sLen) / (eLen[o.y] - sLen); if (r < 0.0) r = 0.0; else if (r > 1.0) r = 1.0; RGB[2][0] = RGB[0][0] + r*(RGB[1][0] - RGB[0][0]); RGB[2][1] = RGB[0][1] + r*(RGB[1][1] - RGB[0][1]); RGB[2][2] = RGB[0][2] + r*(RGB[1][2] - RGB[0][2]); crrf = RGB(RGB[2][0], RGB[2][1], RGB[2][2]); SetPixel24(ssl, crrf); } } } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); HeapFree(GetProcessHeap(), 0, wh); HeapFree(GetProcessHeap(), 0, eLen); delete Mask; return true; fail : if (Mask) delete Mask; MainImageForm->iMainImage->Bitmap->StopScanLine(); if (wh) HeapFree(GetProcessHeap(), 0, wh); if (eLen) HeapFree(GetProcessHeap(), 0, eLen); EXCEPTION_MESSAGE_OK(EC_MEMORY_LACK); return false; } //-------------------------------------------------------------------------- double __fastcall TSpreadFillForm::max_process(TRect rect, TPoint center, double i, TPBitmap *mask) { int j; double a; TPoint p, l; Byte *mp; if (i > 45.0 && i < 135.0){ a = tan((90-i)*M_PI/180); for (p.y=rect.Bottom; p.y>=center.y; p.y--) { p.x = center.x+(p.y-center.y)*a; if (p.y >= mask->Height) p.y = mask->Height-1; if (p.y < 0) p.y = 0; mp = mask->ScanLine(p.y); if (*(mp + (p.x >> 3)) & (0x80 >> (p.x & 7))) break; } } else if (i >= 135.0 && i <= 225.0) { a = tan((i-180)*M_PI/180); for (p.x=rect.Left; p.x<=center.x; p.x++) { p.y = center.y+(p.x-center.x)*a; if (p.y >= mask->Height) p.y = mask->Height-1; if (p.y < 0) p.y = 0; mp = mask->ScanLine(p.y); if (*(mp + (p.x >> 3)) & (0x80 >> (p.x & 7))) break; } } else if (i > 225.0 && i < 315.0) { a = tan((270-i)*M_PI/180); for (p.y=rect.Top; p.y<=center.y; p.y++) { p.x = center.x+(p.y-center.y)*a; if (p.y >= mask->Height) p.y = mask->Height-1; if (p.y < 0) p.y = 0; mp = mask->ScanLine(p.y); if (*(mp + (p.x >> 3)) & (0x80 >> (p.x & 7))) break; } } else { a = tan(i*M_PI/180); for (p.x=rect.Right; p.x>=center.x; p.x--) { p.y = center.y+(p.x-center.x)*a; if (p.y >= mask->Height) p.y = mask->Height-1; if (p.y < 0) p.y = 0; mp = mask->ScanLine(p.y); if (*(mp + (p.x >> 3)) & (0x80 >> (p.x & 7))) break; } } l.x = p.x-center.x; l.y = p.y-center.y; return sqrt((double)l.x*l.x + l.y*l.y); } //------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::CirculateSingleSpread() { int i, j, x, y, n; TRect rect; Byte *ssl, *mp; double sLen, cLen, ratio, r, t, theta; COLORREF crrf; Byte RGB[3][3]; TPoint lxy; double *wh = NULL, *eLen = NULL; int WaveLength, tempdeg; double WaveHeight, temprad, tempdouble; TPBitmap *Mask = NULL; if((Mask = new TPBitmap) == NULL) goto fail; FillColor = MainImageForm->iMainImage->Bitmap->GetPixelColor(First.x, First.y); if(MainImageForm->iMainImage->Bitmap->FloodFillMask(First, FillSingle24, NULL, rect, Mask) == false) goto fail; #ifdef TPDEBUG if (!Mask->Lock()) SHOWDEBUG; #else Mask->Lock(); #endif WaveLength = spEditWlength->Value; WaveHeight = spEditWheight->Value / 100.0; RGB[0][0] = FillColor & 0xFF; RGB[0][1] = (FillColor >> 8) & 0xFF; RGB[0][2] = (FillColor >> 16) & 0xFF; RGB[1][0] = FGColor & 0xFF; RGB[1][1] = (FGColor >> 8) & 0xFF; RGB[1][2] = (FGColor >> 16) & 0xFF; lxy.x = max(First.x - rect.Left + 1, rect.Right - First.x + 1); lxy.y = max(First.y - rect.Top + 1, rect.Bottom - First.y + 1); i = 8*max(lxy.x, lxy.y); n = 90; while (i > n) n <<= 1; t = n / 360.0; eLen = (double *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, n*sizeof(double)); if (eLen == NULL) goto fail; for (i = 0; i < n; i++) eLen[i] = max_process(rect, First, i/t, Mask); lxy.x = Second.x - First.x; lxy.y = Second.y - First.y; if (lxy.x) { theta = atan2(lxy.y, lxy.x) / M_PI; if (theta < 0.0) theta += 2.0; j = 180 * theta; } else { if (lxy.y) j = lxy.y < 0 ? 270: 90; else j = 0; } sLen = sqrt(lxy.x * lxy.x + lxy.y * lxy.y); i = j * t; if (i >= n) i = n - 1; if (eLen[i] == 0) ratio = sLen; else ratio = sLen / eLen[i]; wh = (double *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2*WaveLength*sizeof(double)); if (wh == NULL) goto fail; for (i = 0; i < 2*WaveLength; i++) { wh[i] = WaveHeight * (rand() % 1001 - 500) / 1000.0; } if (!MainImageForm->iMainImage->Bitmap->StartScanLine()) goto fail; for (y = rect.Top; y < rect.Bottom; y++) { ssl = MainImageForm->iMainImage->Bitmap->GetScanLine(y) + 3*rect.Left; for (x = rect.Left; x < rect.Right; x++, ssl += 3) { mp = Mask->ScanLine(y); if (*(mp + (x >> 3)) & (0x80 >> (x & 7))) { lxy.x = x - First.x; lxy.y = y - First.y; if (lxy.x) { theta = atan2(lxy.y, lxy.x) / M_PI; if (theta < 0.0) theta += 2.0; j = 180 * theta; } else { if (lxy.y) j = lxy.y < 0 ? 270: 90; else j = 0; } cLen = sqrt (lxy.x * lxy.x + lxy.y * lxy.y); tempdeg = j * WaveLength / 180; // 0 - 2* WaveLength if (tempdeg == 2*WaveLength) tempdeg = tempdeg - 1; temprad = WaveLength * j * M_PI / 180; tempdouble = wh[tempdeg] * sin(temprad); // -0.5 - 0.5 i = j * t; if (i >= n) i = n - 1; sLen = eLen[i] * ratio * (1.0 + tempdouble); if (cLen >= sLen) { if ((eLen[i] - sLen) == 0) r = 0; else r = (cLen - sLen) / (eLen[i] - sLen); if (r < 0.0) r = 0.0; else if (r > 1.0) r = 1.0; RGB[2][0] = RGB[0][0] + r*(RGB[1][0] - RGB[0][0]); RGB[2][1] = RGB[0][1] + r*(RGB[1][1] - RGB[0][1]); RGB[2][2] = RGB[0][2] + r*(RGB[1][2] - RGB[0][2]); crrf = RGB(RGB[2][0], RGB[2][1], RGB[2][2]); SetPixel24(ssl, crrf); } } } MainImageForm->iMainImage->Bitmap->PutScanLine(y); } MainImageForm->iMainImage->Bitmap->StopScanLine(); HeapFree(GetProcessHeap(), 0, wh); HeapFree(GetProcessHeap(), 0, eLen); delete Mask; return true; fail : if(Mask) delete Mask; MainImageForm->iMainImage->Bitmap->StopScanLine(); if(wh) HeapFree(GetProcessHeap(), 0, wh); if(eLen) HeapFree(GetProcessHeap(), 0, eLen); EXCEPTION_MESSAGE_OK(EC_MEMORY_LACK); return false; } //------------------------------/Public Method/------------------------------ void __fastcall TSpreadFillForm::InitForm() { int i, SingleSpread, fgcol, s_item, max; TIniFile* SpIni = NULL; ParentHeight = Parent->Height+20; if (MainImageForm->iMainImage->Bitmap->BitsPerPixel == 8) { sbSingle->Enabled = false; Bpp24 = false; } else { sbSingle->Enabled = true; Bpp24 = true; } ColorSelector->SetPalette(MainImageForm->Palette); step = 0; TrackBar->Position = 0; Pos = 0; for (i=0; i<5; i++) { ColorIndex[i] = 1; if (i<4) Gap[i] = 1; } SpreadColor = NULL; bChange = true; pal = false; ////////// Multi Spread Init........ SpIni = new TIniFile(DirectoryItem+"\\SpreadFill.ini"); if (SpIni) { Item = SpIni->ReadInteger("DrawType", "Type", 0); TrackBar->Max = SpIni->ReadInteger("TrackBar", "Max", 1); UpDown->Position = SpIni->ReadInteger("UpDown", "Pos", 2); max = 0; for (i=0; i<=TrackBar->Max; i++) { AnsiString str = Format("%d", OPENARRAY(TVarRec, (i))); if (i < 4) Gap[i] = SpIni->ReadInteger("Gap", str, 1); ColorIndex[i] = SpIni->ReadInteger("Color", str, 1); if (max < ColorIndex[i]) max = ColorIndex[i]; } if (EnoughPalette() == false) { for (i=0; i < TrackBar->Max; i++) Gap[i] = 1; } SingleSpread = SpIni->ReadInteger("Single", "Single", 0); fgcol = SpIni->ReadInteger("Single", "Foreground", 2); s_item = SpIni->ReadInteger("Single", "monoItem", 0); delete SpIni; } seGap->Value = Gap[Pos]+ 1; InitItem(Item); SpeedButtonPosition->Down = false; if (Bpp24) { ///////// Single Spread Init..... if (SingleSpread) { PaletteForm->DIB256Palette->ChoiceIndex = fgcol; sbSingle->Down = true; sbSingleClick(sbSingle); monoItem = s_item; if (s_item) Image2->BringToFront(); else Image1->BringToFront(); return; } } sbMultiple->Down = true; PanelMultiple->BringToFront(); ClientHeight = 270; Parent->Height = ParentHeight+ClientHeight; } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::ExitForm() { int max, i; AnsiString str; TIniFile* SpIni = NULL; if (SpreadColor) { HeapFree(GetProcessHeap(), 0, SpreadColor); SpreadColor = NULL; } if (IsDraw) MainImageForm->iMainImage->Repaint(); SpIni = new TIniFile(DirectoryItem+"\\SpreadFill.ini"); if (SpIni) { max = SpIni->ReadInteger("TrackBar", "Max", 0); if (TrackBar->Max < max) { for (i=TrackBar->Max; iDeleteKey("Gap", str); SpIni->DeleteKey("Color", str); } } SpIni->WriteInteger("DrawType", "Type", Item); SpIni->WriteInteger("TrackBar", "Max", TrackBar->Max); SpIni->WriteInteger("UpDown", "Pos", UpDown->Position); for (i=0; i<=TrackBar->Max; i++) { AnsiString str = Format("%d", OPENARRAY(TVarRec, (i))); if (i < 4) SpIni->WriteInteger("Gap", str, Gap[i]); SpIni->WriteInteger("Color", str, ColorIndex[i]); } if (sbSingle->Down) SpIni->WriteInteger("Single", "Single", 1); else SpIni->WriteInteger("Single", "Single", 0); SpIni->WriteInteger("Single", "Foreground", PaletteForm->DIB256Palette->ChoiceIndex); SpIni->WriteInteger("Single", "monoItem", monoItem); delete SpIni; } ColorSelector->SaveToFile(DirectoryItem+"\\SpreadFill.Ini", "ColorSelect"); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::iMainImageMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { TRect r; Byte *scan; int ix, iy; TPItemImage *MainImage = (TPItemImage *) Sender; if (SpeedButtonPosition->Down) { if (!Shift.Contains(ssShift) && Button==mbLeft) { if (step>0) { Second = Point(X, Y); MainImageForm->DrawLineLocate(First, Second); IsDraw = false; step = 0; if (!mono) GoSpreadFill(); else GoSingleSpread(); } else { First = Point(X, Y); Second = First; MainImageForm->DrawLineLocate(First, Second); IsDraw = true; step = 1; } } } else { if (Button==mbMiddle || (Shift.Contains(ssShift) && Button==mbLeft)) { if (bColor) { if (SpeedButtonOne->Down) { if (SpeedButtonDelete->Down) { ColorSelector->DeleteColor(MainImageForm->iMainImage->Bitmap->GetPixelColor(X, Y)); } else { ColorSelector->AddColor(MainImageForm->iMainImage->Bitmap->GetPixelColor(X, Y)); } } else { if (step>0) { Temp.right = X; Temp.bottom = Y; MainImageForm->DrawRectangleLocate(Temp); if (Temp.left>Temp.right) { r.Left = Temp.right; r.Right = Temp.left; } else { r.Left = Temp.left; r.Right = Temp.right; } if (Temp.top>Temp.bottom) { r.Top = Temp.bottom; r.Bottom = Temp.top; } else { r.Top = Temp.top; r.Bottom = Temp.bottom; } if (MainImage->Bitmap->StartScanLine() == false) goto fail; if (SpeedButtonDelete->Down) { for (iy=r.Top; iyBitmap->GetScanLine(iy); for (ix=r.Left; ixDeleteColor(*(scan+ix)); } } } else { for (iy=r.Top; iyBitmap->GetScanLine(iy); for (ix=r.Left; ixAddColor(*(scan+ix)); } } } MainImage->Bitmap->StopScanLine(); step = 0; IsDraw = false; } else { Temp.left = X; Temp.top = Y; Temp.bottom = Temp.top; Temp.right = Temp.left; MainImageForm->DrawRectangleLocate(Temp); IsDraw = true; step = 11; } } } else { FGChange(MainImageForm->iMainImage->Bitmap->GetPixelColor(X, Y)); } } } return; fail : MainImage->Bitmap->StopScanLine(); EXCEPTION_MESSAGE_OK(EC_MEMORY_LACK); } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::iMainImageMouseMove(TObject *Sender, TShiftState Shift, int X, int Y) { if (SpeedButtonPosition->Down) { if (step>0) { if (IsDraw) MainImageForm->DrawLineLocate(First, Second); Second = Point(X, Y); MainImageForm->DrawLineLocate(First, Second); IsDraw = true; } } else { if (bColor) { if (SpeedButtonOne->Down==false) { if (step>0) { if (IsDraw) MainImageForm->DrawRectangleLocate(Temp); Temp.right = X; Temp.bottom = Y; MainImageForm->DrawRectangleLocate(Temp); IsDraw = true; } } } } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::iMainImagePaint() { IsDraw = false; } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::FGChange(int Value) { if (!mono) { if (EnoughPalette()){ ColorIndex[Pos] = Value; if (PosMax) TrackBar->Position = Pos+1; else TrackBar->Position = 0; TrackBarChange(TrackBar); bChange = true; pal = true; View(); } else { EXCEPTION_MESSAGE_OK(EC_COLOR_OVERFLOW); } } else { FGColor = PaletteForm->DIB256Palette->GetFGCOLORREF(24); ImagePreview->Canvas->Brush->Color = (TColor)FGColor; ImagePreview->Canvas->FillRect(Rect(0, 0, ImagePreview->Width, ImagePreview->Height)); } } //--------------------------------------------------------------------------- bool __fastcall TSpreadFillForm::EnoughPalette() { int i, total = 0; for (i = 0; i < TrackBar->Max; i++) total += Gap[i]; if ((MainImageForm->Palette->UseColor+total)>251) { return false; } return true; } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::spEditWlengthChange(TObject *Sender) { if (spEditWlength->Text.Length() > 0 ) { if (spEditWlength->Value > spEditWlength->MaxValue) spEditWlength->Value = spEditWlength->MaxValue; else if (spEditWlength->Value < spEditWlength->MinValue) spEditWlength->Value = spEditWlength->MinValue; } } //--------------------------------------------------------------------------- void __fastcall TSpreadFillForm::spEditWheightChange(TObject *Sender) { if (spEditWheight->Text.Length() > 0) { if (spEditWheight->Value > spEditWheight->MaxValue) spEditWheight->Value = spEditWheight->MaxValue; else if (spEditWheight->Value < spEditWheight->MinValue) spEditWheight->Value = spEditWheight->MinValue; } } //---------------------------------------------------------------------------