//--------------------------------------------------------------------------- #include #include #pragma hdrstop #include "Smooth_F.h" #include "MainImage.h" #include "Undo.h" #include "Exception.h" #include "common.h" #include "StatusProgress.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "TPSpin" #pragma resource "*.dfm" //--------------------------------------------------------------------------- #define IDS_BOUND StringTable[0] #define IDS_TYPE StringTable[1] #define IDS_CLOSECOLOR StringTable[2] #define IDS_CLOSEAREA StringTable[3] #define IDS_WHOLE StringTable[4] //--------------------------------------------------------------------------- TSmoothForm *SmoothForm; //--------------------------------------------------------------------------- __fastcall TSmoothForm::TSmoothForm(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TSmoothForm::FormCreate(TObject *Sender) { //======================================= StringTable.Create(DirectoryItem, Language, "Smooth"); SetSmallFont(Font); Label1->Caption = IDS_BOUND; Label2->Caption = IDS_TYPE; //======================================= cbType->Items->Clear(); cbType->Items->Add(IDS_CLOSECOLOR); cbType->Items->Add(IDS_CLOSEAREA); cbType->Items->Add(IDS_WHOLE); } //--------------------------------------------------------------------------- void __fastcall TSmoothForm::seBoundClick(TObject *Sender) { ((TPSpinEdit *)Sender)->SetFocus(); ((TPSpinEdit *)Sender)->SelectAll(); } //--------------------------------------------------------------------------- // Private Function //--------------------------------------------------------------------------- bool __fastcall TSmoothForm::win_smooth() { int x, y, i, j, Bound, width, height; RECT work; Byte maxi, maxp, c, fc; Byte color[252]; Byte *bp = 0, *dp = 0, *mp = 0, *tp = 0; TTexpiaBitmap *tb = 0, *srctb = 0; RGBQUAD rgb[256]; TPBitmap *Itemp = NULL, *Utemp = NULL; Byte *Ilock = NULL, *Ulock = NULL; TPItemImage *Image = MainImageForm->iMainImage; TCursor OldCursor = Screen->Cursor; srctb = Image->Bitmap; if (MainImageForm->WorkArea->Mask) { Screen->Cursor = crHourGlass; work = MainImageForm->WorkArea->Range; tb = Undo->Last->Bitmap; width = work.right - work.left; height = work.bottom - work.top; Bound = seBound->Value / 2; if ((Itemp = new TPBitmap) == NULL) goto fail; if (!Itemp->Create(width, height, 8)) goto fail; if ((Ilock = Itemp->Lock()) == NULL) goto fail; srctb->SaveToMemory(Itemp->ScanLine(), Itemp->BytesPerLine, work); /* if(srctb->StartScanLine() == false) goto fail; for (y = work.top; y < work.bottom; y++){ bp = srctb->GetScanLine(y) + work.left; mp = Itemp->ScanLine(y-work.top); memcpy(mp, bp, width); } srctb->StopScanLine(); */ if ((Utemp = new TPBitmap) == NULL) goto fail; if (!Utemp->Create(width, height, 8)) goto fail; if ((Ulock = Utemp->Lock()) == NULL) goto fail; tb->SaveToMemory(Utemp->ScanLine(), Utemp->BytesPerLine, work); /* if(tb->StartScanLine() == false) goto fail; for (y = work.top; y < work.bottom; y++){ bp = tb->GetScanLine(y) + work.left; mp = Utemp->ScanLine(y-work.top); memcpy(mp, bp, width); } tb->StopScanLine(); */ StatusProgress->Maximum = height; if (MainImageForm->WorkArea->Mask->StartScanLine() == false) goto fail; for (y = Bound; y < height-Bound; y++) { StatusProgress->Position = y; bp = Utemp->ScanLine(y); mp = MainImageForm->WorkArea->Mask->GetScanLine(y)+Bound; dp = Itemp->ScanLine(y); for (x = Bound; x < width-Bound; x++, mp++) { if (*mp) { if (SmoothColor == *(bp + x)) { Wcolor.count = 0; memset(color, 0, sizeof(color)); maxi = 0; maxp = *(bp + x); fc = maxp; for (j = -Bound; j <= Bound; j++) { tp = Utemp->ScanLine(y + j); for (i = -Bound; i <= Bound; i++) { c = *(tp + x + i); color[c]++; if (color[c] > maxi) { maxi = color[c]; fc = c; } } } *(dp + x) = fc; } } } } StatusProgress->End(); MainImageForm->WorkArea->Mask->StopScanLine(); if((srctb->LoadFromMemory(Itemp->ScanLine(), Itemp->BytesPerLine, work))==NULL) goto fail; delete Utemp; Utemp = NULL; delete Itemp; Itemp = NULL; Screen->Cursor = OldCursor; } else { MessageDlg(IDS_MESSAGE_SETWINDOW, mtWarning, TMsgDlgButtons()<Unlock(); delete Itemp; } if (Utemp) { if (Ulock) Utemp->Unlock(); delete Utemp; } Screen->Cursor = OldCursor; return false; } //--------------------------------------------------------------------------- bool __fastcall TSmoothForm::smooth_fill_read(Byte *p, int x) { return Wcolor.code[*(p+x)]; } //---------------------------------------------------------------------------- void __fastcall TSmoothForm::smooth_fill_save(Byte *p, int x) { *(p+x) = 0xFF; } //--------------------------------------------------------------------------- bool __fastcall TSmoothForm::smooth() { TPBitmap *temp = NULL; Byte *lock = NULL, *tp, *mp; TPoint max, min; int x, y; TTexpiaBitmap *tb = 0; Byte *bp = 0; TRect rect; TPItemImage *Image = MainImageForm->iMainImage; TCursor OldCursor = Screen->Cursor; Screen->Cursor = crHourGlass; tb = Image->Bitmap; if (Wcolor.code[tb->GetPixelColor(start.x, start.y)]) { tb->FloodFill(start, smooth_fill_read, smooth_fill_save, rect); min.x = rect.Left; max.x = rect.Right; min.y = rect.Top; max.y = rect.Bottom; StatusProgress->Maximum = (max.y - min.y)*2; if (!smooth_process(max, min)) goto fail; if ((temp = new TPBitmap) == NULL) goto fail; if (!temp->Create(max.x-min.x, max.y-min.y, 8)) goto fail; if ((lock = temp->Lock()) == NULL) goto fail; tb->SaveToMemory(temp->ScanLine(), temp->BytesPerLine, rect); /* if(tb->StartScanLine() == false) goto fail; for (y = min.y; y < max.y; y++){ tp = tb->GetScanLine(y) + min.x; mp = temp->ScanLine(y-min.y); memcpy(mp, tp, max.x-min.x); } tb->StopScanLine(); */ // StatusProgress->Maximum = max.y - min.y; for (y = 0; y < max.y-min.y; y++) { StatusProgress->Position = y+(max.y-min.y); bp = temp->ScanLine(y); for (x = 0; x < max.x-min.x; x++) { if (*(bp + x) == 0xFF) { *(bp + x) = SmoothColor; } } } // StatusProgress->End(); if((tb->LoadFromMemory(temp->ScanLine(), temp->BytesPerLine, rect))==NULL) goto fail; delete temp; temp = NULL; } StatusProgress->End(); Screen->Cursor = OldCursor; return true; fail : if (temp) { if (lock) temp->Unlock(); delete temp; } Screen->Cursor = OldCursor; return false; } //--------------------------------------------------------------------------- bool __fastcall TSmoothForm::smooth_process(TPoint max, TPoint min) { int lbound, gbound, sx, sy, ex, ey, x, y, smoothc, antic, r, t; int i, j, check; Byte maxi, maxp, c, d, fc; Byte color[252]; Byte *bp = 0, *dp = 0, *sp = 0; TTexpiaBitmap *tb; TPBitmap *temp = NULL; Byte *tp, *mp, *lock = NULL; TRect rect; TPItemImage *Image = MainImageForm->iMainImage; tb = Image->Bitmap; lbound = (int)seBound->Value % 2; if (lbound == 1) { lbound = seBound->Value / 2; } else { lbound = (seBound->Value / 2) - 1; } gbound = seBound->Value / 2; sx = min.x; sy = min.y; ex = max.x; ey = max.y; if (ex > tb->Width - seBound->Value / 2) ex = tb->Width - seBound->Value / 2; if (ey > tb->Height - seBound->Value / 2) ey = tb->Height - seBound->Value / 2; if (sx < seBound->Value / 2) sx = seBound->Value / 2; if (sy < seBound->Value / 2) sy = seBound->Value / 2; int tempx, tempy; rect.Left = sx - lbound; rect.Right = ex + gbound; rect.Top = sy - lbound; rect.Bottom = ey + gbound; tempx = rect.Right - rect.Left; tempy = rect.Bottom - rect.Top; if ((temp = new TPBitmap) == NULL) goto fail; if (!temp->Create(tempx, tempy, 8)) goto fail; if ((lock = temp->Lock()) == NULL) goto fail; tb->SaveToMemory(temp->ScanLine(), temp->BytesPerLine, rect); /* if(tb->StartScanLine() == false) goto fail; for (y = rect.Top; y < rect.Bottom; y++){ tp = tb->GetScanLine(y) + rect.Left; mp = temp->ScanLine(y-rect.Top); memcpy(mp, tp, tempx); } tb->StopScanLine(); */ for (y = lbound; y < tempy-gbound; y++) { StatusProgress->Position = y - lbound; bp = temp->ScanLine(y); for (x = lbound; x < tempx-gbound; x++) { memset(color, 0, sizeof(color)); maxi = 0; smoothc = 0; antic = 0; check = 0; maxp = *(bp + x); for (j = -1; j <= 1; j++) { if (y+j >= 0 && y+j ScanLine(y + j); for (i = -1; i <= 1; i++) { if (x+i>=0 && x+i= 9) { maxp = 0xFF; } else { for (r = -lbound; r <= gbound; r++) { sp = temp->ScanLine(y + r); for (t = -lbound; t <= gbound; t++) { c = *(sp + x + t); if (c == 0xFF) { smoothc++; } else { color[c]++; antic++; if (color[c] > maxi) { maxi = color[c]; fc = c; } } } } if (smoothc >= antic) { maxp = 0xFF; } else { maxp = fc; } } *(bp + x) = maxp; } } } if((tb->LoadFromMemory(temp->ScanLine(), temp->BytesPerLine, rect))==NULL) goto fail; delete temp; temp = NULL; return true; fail : if (temp) { if (lock) temp->Unlock(); delete temp; } return false; } //--------------------------------------------------------------------------- bool __fastcall TSmoothForm::whole_smooth() { int x, y, i, j, Bound, width, height; RECT work; Byte maxi, maxp, c, fc; Byte color[252]; Byte *bp = 0, *dp = 0, *mp = 0, *tp = 0; TTexpiaBitmap *tb = 0, *srctb = 0; RGBQUAD rgb[256]; TPBitmap *Itemp = NULL, *Utemp = NULL; Byte *Ilock = NULL, *Ulock = NULL; TPItemImage *Image = MainImageForm->iMainImage; srctb = Image->Bitmap; TCursor OldCursor = Screen->Cursor; if (MainImageForm->WorkArea->Mask) { Screen->Cursor = crHourGlass; work = MainImageForm->WorkArea->Range; tb = Undo->Last->Bitmap; width = work.right - work.left; height = work.bottom - work.top; Bound = seBound->Value / 2; if ((Itemp = new TPBitmap) == NULL) goto fail; if (!Itemp->Create(width, height, 8)) goto fail; if ((Ilock = Itemp->Lock()) == NULL) goto fail; srctb->SaveToMemory(Itemp->ScanLine(), Itemp->BytesPerLine, work); /* if(srctb->StartScanLine() == false) goto fail; for (y = work.top; y < work.bottom; y++){ bp = srctb->GetScanLine(y) + work.left; mp = Itemp->ScanLine(y-work.top); memcpy(mp, bp, width); } srctb->StopScanLine(); */ if ((Utemp = new TPBitmap) == NULL) goto fail; if (!Utemp->Create(width, height, 8)) goto fail; if ((Ulock = Utemp->Lock()) == NULL) goto fail; tb->SaveToMemory(Utemp->ScanLine(), Utemp->BytesPerLine, work); /* if(tb->StartScanLine() == false) goto fail; for (y = work.top; y < work.bottom; y++){ bp = tb->GetScanLine(y) + work.left; mp = Utemp->ScanLine(y-work.top); memcpy(mp, bp, width); } tb->StopScanLine(); */ StatusProgress->Maximum = height; if (MainImageForm->WorkArea->Mask->StartScanLine() == false) goto fail; for (y = Bound; y < height-Bound; y++) { StatusProgress->Position = y; bp = Utemp->ScanLine(y); mp = MainImageForm->WorkArea->Mask->GetScanLine(y)+Bound; dp = Itemp->ScanLine(y); for (x = Bound; x < width-Bound; x++, mp++) { if (*mp) { Wcolor.count = 0; memset(color, 0, sizeof(color)); maxi = 0; maxp = *(bp + x); fc = maxp; for (j = -Bound; j <= Bound; j++) { tp = Utemp->ScanLine(y + j); for (i = -Bound; i <= Bound; i++) { c = *(tp + x + i); color[c]++; if (color[c] > maxi) { maxi = color[c]; fc = c; } } *(dp + x) = fc; } } } } StatusProgress->End(); MainImageForm->WorkArea->Mask->StopScanLine(); if((srctb->LoadFromMemory(Itemp->ScanLine(), Itemp->BytesPerLine, work))==NULL) goto fail; delete Utemp; Utemp = NULL; delete Itemp; Itemp = NULL; Screen->Cursor = OldCursor; } else { MessageDlg(IDS_MESSAGE_SETWINDOW, mtWarning, TMsgDlgButtons()<Unlock(); delete Itemp; } if (Utemp) { if (Ulock) Utemp->Unlock(); delete Utemp; } Screen->Cursor = OldCursor; return false; } //--------------------------------------------------------------------------- // Public Function //--------------------------------------------------------------------------- void __fastcall TSmoothForm::InitForm(void) { TPItemImage *Image = MainImageForm->iMainImage; ParentHeight = Parent->Height+20; ClientHeight = 80; Parent->Height = ParentHeight+ClientHeight; cbType->ItemIndex = 0; } //--------------------------------------------------------------------------- void __fastcall TSmoothForm::SmoothMouseDown(int X, int Y) { TTexpiaBitmap *tb = 0; bool undoSw = false; TPItemImage *Image = MainImageForm->iMainImage; tb = Image->Bitmap; if (!(undoSw = MainImageForm->UndoSave(UK_ALL, Rect(0, 0, tb->Width, tb->Height)))) goto fail; if (cbType->ItemIndex == 0) { start.x = X; start.y = Y; Wcolor.count = 0; memset(Wcolor.code, 0, sizeof(Wcolor.code)); Wcolor.code[tb->GetPixelColor(start.x, start.y)] = 1; SmoothColor = tb->GetPixelColor(start.x, start.y); if (!win_smooth()) goto fail; } else if (cbType->ItemIndex == 1) { start.x = X; start.y = Y; Wcolor.count = 0; memset(Wcolor.code, 0, sizeof(Wcolor.code)); Wcolor.code[tb->GetPixelColor(start.x, start.y)] = 1; SmoothColor = tb->GetPixelColor(start.x, start.y); if (!smooth()) goto fail; } else if (cbType->ItemIndex == 2) { if (!whole_smooth()) goto fail; } Image->Repaint(); return; fail: if (undoSw) Undo->RemoveLast(); EXCEPTION_MESSAGE_OK(EC_MEMORY_LACK); } //---------------------------------------------------------------------------