Pobieranie "image area" i "color area" pulpitu

0

Witam! tworzę taki mały programik i chciałem dodać do niego coś w stylu "image area" i "color area" ...
Tylko teraz problem jak to zrobić, ponieważ "color area" by miało działać na zasadzie że pobieram jakiś kolor z pulpitu a program po wciśnięciu jakiegoś klawisza lokalizuje (wyświetla położenie XY piksela z tym kolorem) ten kolor na pulpicie, nawet jeśli on jest w innym miejscu...
image area, powinno działać na podobnych zasadach tylko w stylu takim że jak bym robił zdjęcie dla pulpitu później wycinał mały fragment z tego zdjęcia a znów po wciśnięciu klawisza program powinien wyświetlić współrzędne tego fragmentu nawet jeśli on był by w innym miejscu :/

Ktoś spotkał się z czymś takim? a może ktoś już ma gotowy taki skrypt lub jakiś pomysł na zrobienie tego?

0
XA napisał(a):

Tylko teraz problem jak to zrobić, ponieważ "color area" by miało działać na zasadzie że pobieram jakiś kolor z pulpitu a program po wciśnięciu jakiegoś klawisza lokalizuje (wyświetla położenie XY piksela z tym kolorem) ten kolor na pulpicie, nawet jeśli on jest w innym miejscu...

Potrzebujesz na bieżąco sprawdzać kolor piksela znajdującego się pod kursorem. Do tego celu wystarczy kilka linijek kodu – stworzyć nowy obiekt płótna i ustawić mu uchwyt na ten pulpitu:

uses
  Windows, {...};

{..}

private
  FDesktopCanvas: TCanvas;

{...}

FDesktopCanvas := TCanvas.Create();
FDesktopCanvas.Handle := GetWindowDC(GetDesktopWindow());

To wszystko – płótno możesz teraz wykorzystywać jak każde inne, tak samo jak płótno formularza czy komponentu. Ono zawiera wszystko co znajduje się na pulpicie.

Jeśli potrzebujesz tylko pobrać dane koloru piksela pod kursorem, to np. w zdarzeniu wciśnięcia konkretnego klawisza (lub wciśnięcia przycisku – z poziomu klawiatury rzecz jasna, bo kursor może być gdziekolwiek) wykonujesz poniższe:

var
  LCursorPos: TPoint = (X: 0; Y: 0);
  LColor: TColor;
begin
  GetCursorPos(LCursorPos);
  LColor := GetPixel(FDesktopCanvas.Handle, LCursorPos.X, LCursorPos.Y);

Zmienna LColor zawierać będzie kolor piksela spod kursora.

Natomiast jeśli chcesz mieć podgląd koloru na żywo po włączeniu funkcji pobierania koloru (czyli na bieżąco, podczas przesuwania kursorem) to możesz w prosty sposób wykorzystać zwykły timer, w którym co określony interwał (np. 100ms) timer będzie pobierał kolor pod kursorem i używał go do malowania kontrolki podglądu (np. małego TPaintBox). Włączenie funkcji pobierania koloru odpali timer, jej wyłączenie (np. specjalnym skrótem klawiszowym) go zatrzyma.

Współrzędne tego piksela są znane, bo funkcja GetCursorPos je zwraca. Koordynaty te są bezwzględne, czyli dotyczą całego pulpitu, a nie ekranu czy formularza aplikacji. Liczba monitorów i ich układ nie ma znaczenia. Jeśli będą one potrzebne w późniejszym czasie to też sobie je przechowaj.

image area, powinno działać na podobnych zasadach tylko w stylu takim że jak bym robił zdjęcie dla pulpitu […]

Nie musisz robić zdjęcia całości – szkoda na to czasu i zasobów. Masz dostep do płótna całego pulpitu, więc spokojnie wystarczy CopyRect zadanego fragmentu do pomocniczej, 24-bitowej bitmapy. Kod poboru współrzędnych kursora masz wyżej, klasę płótna też. Jak będziesz chciał użyć funkcji z Windows API do pobrania zadanego obszaru pulpitu, to uchwyt typu HDC zwraca właściwość FDesktopCanvas.Handle.

Podane kody działają pod Lazarusem i pochodzą z mojego ”color pickera”.

0

supcio, super! tylko z tym pierwszym bardziej mi chodzi o to że jak już ustalę jaki to kolor zapiszę w pliku (np #000000), a za jakieś parę minut ten piksel (lub obszar koloru) zmieni pozycje np z X10 Y100 na X nie wiadomo Y nie wiadoma to jak mam pobrać pozycje tego YX w którym on jest już gdy zmienił położenie z poziomu programu, bez manualnego ganiania po pulpicie kursorem? najlepiej by było gdyby program do ustalania pozycji wtedy też nie ruszał kursorem w celu badania pikseli :/

tak samo chodzi o te ustalenie fragmentu zdjęcia jak je zlokalizować gdy już mam zapisane gdzieś wcześniej w formie zdjęcia czy innej formie :/ i np później na tym fragmencie narysować kwadrat :)

0
XA napisał(a):

supcio, super! tylko z tym pierwszym bardziej mi chodzi o to że jak już ustalę jaki to kolor zapiszę w pliku (np #000000) […]

Jakim pliku?

[…] a za jakieś parę minut ten piksel (lub obszar koloru) zmieni pozycje […]

Skąd program ma wiedzieć, że zmienił pozycję?

[…] np z X10 Y100 na X nie wiadomo Y nie wiadoma […]

Jeśli piksel zmienił pozycję (btw. piksele nie zmieniają swoich pozycji) to trzeba wiedzieć jaka jest nowa pozycja.

[…] to jak mam pobrać pozycje tego YX w którym on jest już gdy zmienił położenie […]

Normalnie – zamiast wołania GetCursorPos, użyj swoich współrzędnych w funkcji GetPixel.

najlepiej by było gdyby program do ustalania pozycji wtedy też nie ruszał kursorem w celu badania pikseli :/

No to napisz kod, który nie bazuje na GetCursorPos – wtedy pozycja i ruch kursora nie będą miały znaczenia.

tak samo chodzi o te ustalenie fragmentu zdjęcia jak je zlokalizować gdy już mam zapisane gdzieś wcześniej w formie zdjęcia czy innej formie :/

Poszukaj w sieci informacji na temat tego, w jaki sposób wyszukiwać zadany fragment w całym obrazie. Im większy fragment i większy obraz główny, tym szybszy kod trzeba będzie napisać.

i np później na tym fragmencie narysować kwadrat :)

Canvas.FillRect lub Canvas.Rectangle – jak już współrzędne i rozmiar będą znane.

0
  1. Rozwijam program Auto Mouse Clicker (AMC) i on bazuje na plikach projektów do sekwencji i w tych plikach było by zapisywane te fragmenty "zdjęcia" lub informacje o kolorze.

  2. Właśnie chodzi o to by po naciśnięciu klawisza jakoś sam zbadał pulpit w celu pobrania współrzędnych w których jest ten kolor.

  3. szukam od tygodnia w google, bink i nic a nic przykładowych kodów :/ albo w sumie nie umiem szukać bo nie wiem jak dokładnie określić to o co mi chodzi :(

Tzn :) jeśli na zdjęciu 1.png wybrałem kolor niebieski a on zmienił pozycje tak jak na 2.png to jak mam uzyskać pozycje koloru z 2.png ? z poziomu programu bez jechania kursorem po każdym pikselu ?

Tak samo ze zdjęciem jak mam wykonać zdjęcie ikony "ten komputer" 1.png a po jakimś czasie z poziomu programu odnaleźć miejsce gdzie jest ta ikona (te zdjęcie) tak np jak na 2.png i pobrać jej XY :/

ehh... ale się motam z tym tłumaczeniem, przepraszam

0
XA napisał(a):
  1. Właśnie chodzi o to by po naciśnięciu klawisza jakoś sam zbadał pulpit w celu pobrania współrzędnych w których jest ten kolor.

Problem w tym, że na pulpicie znajduje się mnóstwo pikseli o zadanym kolorze, więc znalezienie tego odpowiedniego tylko i wyłącznie na podstawie kodu koloru jest awykonalne. Im więcej pikseli o zadanym kolorze, tym mniejsze prawdopodobieństwo wskazania tego właściwego.

Tzn :) jeśli na zdjęciu 1.png wybrałem kolor niebieski a on zmienił pozycje tak jak na 2.png to jak mam uzyskać pozycje koloru z 2.png ? z poziomu programu bez jechania kursorem po każdym pikselu ?

Patrz wyżej – możesz szukać, np. o zgrozo przeiterować po wszystkich pikselach pulpitu, ale nie będziesz miał żadnej pewności, że znalazłeś ten właściwy.

Tak samo ze zdjęciem jak mam wykonać zdjęcie ikony "ten komputer" 1.png a po jakimś czasie z poziomu programu odnaleźć miejsce gdzie jest ta ikona (te zdjęcie) tak np jak na 2.png i pobrać jej XY :/

Jeśli brać pod uwagę wyszukiwanie obrazem i szukać idealnego dopasowania, to mechanizm ten będzie działał prawidłowo tylko i wyłącznie wtedy, gdy:

  • ikona będzie identyczna jak we wzorcu,
  • tytuł ikony będzie identyczny,
  • tło pod ikoną (np. fragment tapety pulpitu) w obu przypadkach będzie identyczne,
  • ustawienia wygładzania fontów w systemie nie zmienią się, itd.

Jak widzisz, sposób beznadziejny – istnieje wysokie ryzyko niedopasowania obrazu, a tym samym nieodnalezienia ikony. Co prawda można wyliczyć procentowe dopasowanie i dopuścić pewien margines błędu, ale to wciąż niepewny sposób, nie dający stuprocentowej gwarancji poprawności dzialania.

Jeśli jakikolwiek program potrafi odnaleźć zadaną ikonkę na pulpicie (gdy zmieniła swoją pozycję) to na 100% nie bazuje ani na kolorze spod kursora, ani tym bardziej na porównywaniu obrazów.

0

Dlatego właśnie tutaj się zwróciłem o pomoc, bo mnie to już przerasta :(
kolor w sumie można obejść w taki sposób że już mam zapisany #000000 teraz gdy przychodzi czas na wyszukanie takiego koloru na pulpicie to zaczynam sprawdzać piksele 0-1 0-2 0-3...1-0 1-2 ... bingo jest taki kolor w 1-2 więc program klika kursorem we współrzędne 1-2... tylko teraz jak wykonać takie skanowanie pulpitu w poszukiwaniu takiego piksela bez używania przez program kursora w sprawdzaniu pikseli ? tutaj problemu nie ma bo zakładam badanie od Y0 X0 i jechanie w np y1...y2...y3 i uzyskiwanie położenia pierwszego piksela z tym kolorem

teraz z tą ikono to wiesz chodzi tylko o to by wyszukać identyczny fragment na pulpicie, i tu już poległem kompletnie :) bo jeśli nie ma to ok program przerywa sekwencję ze zdjęciem i idzie do kolejnej sekwencji programu... ale jeśli pojawi się takie np zdjęcie z tym fragmentem jak pobrać wtedy lokalizacje tego fragmentu XY oraz XY2 tak by na nim narysować kwadrat ?

1
XA napisał(a):

Dlatego właśnie tutaj się zwróciłem o pomoc, bo mnie to już przerasta :(

IMO jest to problem XY – zamiast tkwić w złym pomyśle, należy znaleźć odpowiedni sposób.

kolor w sumie można obejść w taki sposób że już mam zapisany #000000 teraz gdy przychodzi czas na wyszukanie takiego koloru na pulpicie to zaczynam sprawdzać piksele 0-1 0-2 0-3...1-0 1-2 ... bingo […]

Eee tam bingo – raz że będziesz musiał sprawdzać miliony pikseli (co potrwa dość długo), a dwa, Twój algorytm co prawda znajdzie piksel o zadanym kolorze, ale nie da żadnej gwarancji, że znalazł ten właściwy.

[…] jest taki kolor w 1-2 więc program klika kursorem we współrzędne 1-2...

I kliknie w pierwsze lepsze miejsce, niekoniecznie prawidłowe. Biorąc pod uwagę to, że pikseli o zadanym kolorze może być dziesiątki tysiący, prawdopodobieństwo wskazania poprawnego liczyć należy w ‰.

tylko teraz jak wykonać takie skanowanie pulpitu w poszukiwaniu takiego piksela bez używania przez program kursora w sprawdzaniu pikseli ?

Osłabiasz mnie – przecież funkcja GetPixel nie potrzebuje kursora, a współrzędnych X i Y per pulpit, które równie dobrze możesz podać z iteratorów dwóch zagnieżdżonych pętli. Po raz kolejny przypominam – to bardzo złe i wadliwe rozwiązanie.

tutaj problemu nie ma bo zakładam badanie od Y0 X0 i jechanie w np y1...y2...y3 i uzyskiwanie położenia pierwszego piksela z tym kolorem

No jak nie ma problemu jak jest, i to gigantyczny? Wydajność tej metody jest tragiczna, a sam tragizm rośnie wprost proporcjonalnie do rozdzielczości ekranu.

teraz z tą ikono to wiesz chodzi tylko o to by wyszukać identyczny fragment na pulpicie, i tu już poległem kompletnie :)

Wyszukiwanie obrazem to jeszcze większa tragedia niż wyszukiwanie kolorem. Nie dość że musisz znaleźć pierwszy pasujący piksel, to następnie musisz sprawdzić dla niego cały wiersz i jeśli pasuje to w pętli pozostałe wiersze.

I znów – biorąc pod uwagę liczbę pikseli na ekranie o zadanym kolorze, znalezienie dopasowania portwa potwornie długo, tym dłużej, im większa rozdzielczość ekranu i rozmiar szukanego fragmentu.

0

To na razie zostańmy przy tym kolorze :)
Wiem, wiem np rozdzielczość 2000x1000 daje już 2.000.000 pikseli do sprawdzenia....

W tej funkcji co chcę wprowadzić nie chodzi o dokładność tylko o to że np masz 1000 pikseli niebieskich i musisz byle który wybrać aby tylko miał kolor niebieski :)

Teraz tylko mi zostaje jak zbadać ten pulpit w poszukiwaniu tego piksela z tym kolorem :/
Pod jakimi frazami tego szukać w internecie? tak by znaleźć coś w miare optymalnego ?

1

Przecież podałem Ci to co trzeba – jak uzyskać uchwyt pulpitu, jak pobrać kolor konkretnego piksela.

Jak się boisz tych funkcji to zrób zrzut ekranu, zapisz go do pomocniczej bitmapy i przeszukaj, używając właściwości Pixels. Będzie to trwało pół roku, ale zadziała. Aby to przyspieszyć, zamiast właściwości Pixels użyj metody ScanLine i kupki wskaźników – iteracja potrwa o wiele krócej.

0
furious programming napisał(a):

Przecież podałem Ci to co trzeba – jak uzyskać uchwyt pulpitu, jak pobrać kolor konkretnego piksela.

Jak się boisz tych funkcji to zrób zrzut ekranu, zapisz go do pomocniczej bitmapy i przeszukaj, używając właściwości Pixels. Będzie to trwało pół roku, ale zadziała. Aby to przyspieszyć, zamiast właściwości Pixels użyj metody ScanLine i kupki wskaźników – iteracja potrwa o wiele krócej.

Yyy zaraz zabieram się do wprowadzenia tego w życie :) gdzie tu można dać ci jakoś pochwałę lub plusa za pomoc?
Nie boje się funkcji a boje się tego że nie dam rady ze swoimi umiejętnościami ich wprowadzić...

0

W sieci jest mnóstwo gotowców – wystarczy poszukać (najlepiej po angielsku) i posklejać z nich całość.

0

ten programik powstawał właśnie na takich zasadach ;)

Wszystko pięknie, tylko jak rozwiązać problem z tym że gdy pobierając kolor najeżdżam na jakoś ikonkę a ona się "podświetla"? da się jakoś yyyy zamrozić pulpit do czasu "kliknięcia" by zapisać ten kolor?

0
XA napisał(a):

da się jakoś yyyy zamrozić pulpit do czasu "kliknięcia" by zapisać ten kolor?

Nie sądzę. Jak nie chcesz aby cokolwiek się zmieniało to zrób zrzut ekranu, zapisz go do zmiennej pomocniczej i na nim operuj – wtedy już bez pomocy kursora i klikania.

0

Nie no jestem pod wrażeniem wiedzy :)
Ale tutaj odpada to ponieważ chce by wszystko się działo na oczach użytkownika i było w stylu "profesjonalnym" :/

0
XA napisał(a):

Ale tutaj odpada to ponieważ chce by wszystko się działo na oczach użytkownika […]

Przecież chodzi wyłącznie o to, aby użyć pomocniczej bitmapy do odnalezienie zadanego piksela, a nie do ukrywania czegokolwiek przed użytkownikiem. Poza tym czytanie piksel po pikselu funkcją GetPixel nie jest rozwiązaniem efektywnym – stąd sugestia tylnego buforowania.

[…] i było w stylu "profesjonalnym" :/

Żeby móc stwierdzić co jest profesjonalne, a co nie, najpierw samemu trzeba być profesjonalistą. W przeciwnym razie takie stwierdzenia są całkowicie bezzasadne.

Profesjonalnie rozwiązanie tego problemu to hook na mysz i pobranie informacji o klikniętej ikonie pulpitu (współrzędnych, etykiety, ścieżki itd.), a nie zabawa z kolorami i zrzutami ekranu, które nie dość że są nieefektywne, to jeszcze wadliwe w działaniu.

0

profesjonalne od strony usera ;) właśnie mam już zrobiony ten hook że jeśli kliknie się prawym przyciskiem myszy wysyła kolor do zmiennej z danymi :) ale jeszcze denerwuje mnie fakt że po najechaniu myszką podświetlene są ikony :/

0
XA napisał(a):

profesjonalne od strony usera ;)

A to back buffering jest nieprofesjonalny…? :|

ale jeszcze denerwuje mnie fakt że po najechaniu myszką podświetlene są ikony :/

Będą się podświetlały, bo mają się podświetlać.

A jak tłumaczę, aby użyć buforowania ekranu (nie tylko po to, aby się obraz nie zmieniał, ale też ze względu na wydajność) to twierdzisz, że to nie jest profesjonalne… Przez połowę wątku usiłuję Ci wytłumaczyć, że źle się zabierasz za ten program, a Ty i tak robisz swoje.

0

Będą się podświetlały, bo mają się podświetlać.

W moim przypadku nie mogą, bo chce by to wyglądało jak "zamrożony" pulpit do czasu aż pobierze się kolor :)

Teraz mam kolejny problem :/ jak zrobić coś takiego jak jest tutaj na zdjęciu tak aby tymi czarnymi punktami dało się rozciągać ten kwadrat : Bez_tytułu_1.png

0
XA napisał(a):

W moim przypadku nie mogą, bo chce by to wyglądało jak "zamrożony" pulpit do czasu aż pobierze się kolor :)

Powtórzę po raz n-ty – operuj na pomocniczej bitmapie.

Utwórz bitmapę w pamięci, do niej wrzuć zrzut ekranu i w niej szukaj tego czego potrzebujesz. W ten sposób nic nie będzie się zmieniało (bo masz zrzut ekranu), a przeszukiwanie będzie działać o wiele szybciej niż bezpośrednio na pulpicie. Do tego celu użyj ScanLine – to najszybszy sposób odczytu danych (zapisu też) z obrazu.

jak zrobić coś takiego jak jest tutaj na zdjęciu tak aby tymi czarnymi punktami dało się rozciągać ten kwadrat […]

A ten ”kwadrat” to czym jest? Komponentem? Oknem? Czym?

0

A ten ”kwadrat” to czym jest? Komponentem? Oknem? Czym?

Komponentem timage opuszczonym na formatkę ;) ale chce uzyskać taki efekt by można było w moim programie na zrzucie ekranu (otwartym w image) narysować taki kwadrat a później by dało się tymi punktami rozciągać lub zmniejszać ten kwadrat, tak by wizualnie pobrać punkty A,B,C,D do wycięcia tego fragmentu ze zdjęcia

0
XA napisał(a):

ale chce uzyskać taki efekt by można było w moim programie na zrzucie ekranu (otwartym w image) […]

TImage nie służy do jakiejkolwiek obróbki, a do zwykłego wyświetlenia obrazka. Nie wiem dlaczego wszyscy lgną do tego komponentu i próbują robić z niego swojego painta… ;)

Dobrą kontrolką do takich rzeczy jest TPaintBox, z racji posiadania przygotowanego zestawu zdarzeń, w tym zdarzenia OnPaint, umożliwiającego pełną kontrolę nad renderowaniem tego komponentu. Oczywiście nie jest to jeden komponent nadający się do tego celu, a już najlepszym – według mnie – rozwiązaniem jest stworzenie własnego komponentu, dziedzicząc po jakiejś klasie bazowej (np. TWinControl pod Delphi lub TCustomControl pod Lazarusem).

Głównie chodzi o to, żeby przygotować kontrolkę do wyświetlania całego obrazu lub jego fragmentu (w przypadku, gdy obraz nie mieści się w całości w kontrolce) oraz dodać obsługę zaznaczania. Samo zaznaczanie to nic innego jak:

  • reagowanie na akcje myszy (oprogramowanie komunikatów myszy lub wykorzystanie zdarzeń),
  • zapamiętanie położenia i wymiarów ramki zaznaczenia (np. w postaci pola typu TRect),
  • jeśli zaznaczenie jest aktywne, namalowania tła (obrazu lub jego fragmentu), a na nim ramki.

Możesz napisać dedykowany komponent (opcja najlepsza), możesz też rozszerzyć klasę TPaintBox za pomocą subclassingu (nienajgorsza, ale dotyczy wszystkich kontrolek tego typu w oknie), a możesz też odpowiednio oprogramować zdarzenia, wrzucając do nich wymaganą logikę oraz potrzebne tej logice dane trzymać w osobnej klasie lub w klasie okna (rozwiązanie paskudne, ale też będzie działać). Wybierz sobie jedno.

[…] narysować taki kwadrat a później by dało się tymi punktami rozciągać lub zmniejszać ten kwadrat, tak by wizualnie pobrać punkty A,B,C,D do wycięcia tego fragmentu ze zdjęcia

To jest wyłącznie kwestia oprogramowania akcji myszy:

  • WM_LBUTTONDOWN lub OnMouseDown – rozpoczynamy zaznaczanie lub rozciąganie,
  • WM_LBUTTONUP lub OnMouseUp – zakańczamy zaznaczanie lub rozciąganie,
  • WM_MOUSEMOVE lub OnMouseMove – rozciągamy zaznaczenie, przesuwamy zaznaczenie lub sprawdzamy czy kursor znajduje się nad kropką do rozciągania, np. w celu zmiany kursora na łapkę.

Z danych potrzebnych logice na pewno trzeba przechować stan zaznaczenia (włączone zaznaczanie lub wyłączone), położenie i rozmiar ramki (w celu detekcji kropek do rozciągania oraz do poprawnego renderowania kontrolki), a także stan myszy (czy przycisk myszy jest wciśnięty, czy nie).

Jeśli chcesz namalować taką samą ramkę, jaka widoczna jest w designerze (dla kontrolki TImage) to kuknij do źródeł tego komponentu – w metodzie Paint znajdziesz odpowiedni kod.

0

TImage nie służy do jakiejkolwiek obróbki, a do zwykłego wyświetlenia obrazka. Nie wiem dlaczego wszyscy lgną do tego komponentu i próbują robić z niego swojego painta… ;)

Bo najłatwiej!

Ale w moim przypadku Timage ponieważ służy mi tylko do wyświetlenia zdjęcia :

    IrW:=screen.width ; // X
    IrH:=screen.height; // Y

    //skala:=3; !!! domyślna!
    Image3.Width := IrW * skala;
    Image3.Height := IrH * skala;
    Image3.Stretch := true;

  bmp := Graphics.TBitmap.Create;
  DC := GetDC(0);
  try
    bmp.LoadFromDevice(DC);
  finally
    ReleaseDC(0, DC);
  end;
  	Image2.Picture.Bitmap.Assign(bmp);
  	Image3.Picture.Bitmap.Assign(bmp);
  	FreeAndNil(bmp);  

i na tym image2 chce zrobić coś takiego jak jest w delphi z np butonami że gdy opuszczam na formę ten komponent to mam takie punkty którymi mogę go rozciągać itp...
Ten mój "komponent" nic nie będzie robił tylko po prostu będzie wyświetlany w formie ramki z tymi punktami, później sobie wezmę tylko współrzędny tej ramki i tyle :/ tylko nie mam pojęcia jak się zabrać do tego... próbuje coś z TShape ale hmmm 12 komponentów TShape czyli potrzebne 36 procedur na to :(

A podejrzewam że takie coś można osiągnąć za pomocą znacznie mniejszej ilości procedur...

0
XA napisał(a):

Bo najłatwiej!

Właśnie widać jak najłatwiej.

Ale w moim przypadku Timage ponieważ służy mi tylko do wyświetlenia zdjęcia :

No nie tylko do wyświetlenia, bo chcesz też mieć obsługę ramki zaznaczenia – to mini Paint, nie zwykły obrazek.

i na tym image2 chce zrobić coś takiego jak jest w delphi z np butonami że gdy opuszczam na formę ten komponent to mam takie punkty którymi mogę go rozciągać itp...

Użyj TPaintBox lub własnej kontrolki – potrzebujesz mieć dostęp do zdarzenia OnPaint lub metody Paint.

0

Właśnie widać jak najłatwiej.

?

No nie tylko do wyświetlenia, bo chcesz też mieć obsługę ramki zaznaczenia.

Tylko do wyświetlenia, ponieważ ta ramka zaznaczenia ma tylko pobierać w którym miejscu XY pulpitu znajdują się punkty A,B,C,D (czyli rogi tej ramki) i nie musi nic więcej wykonywać ani nic nie pobierać z innych komponentów :)

Czyli tzn, ta ramka po prostu musi znajdować się nad komponentem Timage i dać się rozciągać za pomocą "tych takich punktów" :/ tylko nie mam pojęcia :
A - jak to wykonać nie korzystając z masy Tshap
B - Jak oprogramować elementy tego by kod nie był strasznie długi ( tshap =36 procedur)
C - nie mam pojęcia jak się za to zabrać :/

0
XA napisał(a):

Tylko do wyświetlenia, ponieważ ta ramka zaznaczenia ma tylko pobierać w którym miejscu XY pulpitu znajdują się punkty A,B,C,D (czyli rogi tej ramki) i nie musi nic więcej wykonywać ani nic nie pobierać z innych komponentów :)

Ehh… mam wrażenie, że mówię do ściany…

Czyli tzn, ta ramka po prostu musi znajdować się nad komponentem Timage i dać się rozciągać za pomocą "tych takich punktów" :/ tylko nie mam pojęcia :

Problem XY – upierasz się przy złym rozwiązaniu, zamiast brać uwagę to co Ci się sugeruje.

Albo wywal TImage do kosza i zastosuj TPaintBox, albo radź sobie sam – szkoda mi czasu na takie przekomarzanie, skoro wiesz lepiej i nie dasz sobie nic przegadać.

0

Ok, dobra, spokojnie :) wywalam Timage, mam już TPaintBox1 i teraz jak w tym zrobić taką ramkę ?

0

Podłubałem trochę – w załączniku masz przykład wyświetlania obrazu i ramki na nim, całość działająca w kontrolce typu TPaintBox, z użyciem jego zdarzeń. Ramka obsługuje zmianę kursora – po umieszczeniu kursora wewnątrz niej, kursor zmieniany jest odpowiedni dla przesuwania, a nad kwadracikami w rogach zmienia się na strzałki do rozciągania.

preview.png

Niestety nie miałem czasu na oprogramowanie akcji myszy (innych niż sama zmiana kursora), więc to pozostawiam Tobie (ew. dorobię to kiedy indziej, jak znajdę chwilkę). Jeśli potrzebujesz więcej punktów umożliwiających rozciąganie to sobie je dorób. ;)

0

Dokładnie o to mi chodziło :)

Mam nadzieję że teraz gdy będę mniejszy obszar dawał w celu przeszukania koloru szybciej program będzie działał :/
Bo obecnie przy 1366x768 to zajmowało jakieś 250-300ms...

Teraz co do kwestii zdjęcia, tak od strony teoretycznej jak ma to wyglądać:
Szukam pierwszego piksela na monitorze o takim kolorze jaki ma piksel z bmp o współrzędnych 1x i 1y ze zdjęcia "próbki"
Gdy już znajdę, piksel na pulpicie to tylko skanuję piksel sąsiedni więc jeśli piksel pierwszy był na x10 y20 to tylko sprawdzam piksel x11 y20 z plikiem próbką x2 1y... jeśli się zgadza to mam tak sprawdzać aż skończę całą próbkę, a jeśli gdzieś w tym jest jakiś piksel szukam kolejnego piksela na ekranie z kolorem pasującym do próbki 1x 1y?
I kolejna kwestia jak zapisywać próbkę w pliku projektu, jeśli jest to plik typowany ?

0
XA napisał(a):

Bo obecnie przy 1366x768 to zajmowało jakieś 250-300ms...

Twoje algorytmy działają wolno, dlatego że nie piszesz ich z myślą o maksymalnej efektywności.

Teraz co do kwestii zdjęcia, tak od strony teoretycznej jak ma to wyglądać:
Szukam pierwszego piksela na monitorze o takim kolorze jaki ma piksel z bmp o współrzędnych 1x i 1y ze zdjęcia "próbki"

Nie, szukasz go w pomocniczej bitmapie, a nie na monitorze. Oczywiście samo wyszukiwanie opierasz o właściwość ScanLine, która zwraca wskaźnik do obszaru pamięci, w którym znajdują się dane pikseli (w formie BGR lub ABGR).

Gdy już znajdę, piksel na pulpicie to tylko skanuję piksel sąsiedni więc jeśli piksel pierwszy był na x10 y20 to tylko sprawdzam piksel x11 y20 z plikiem próbką x2 1y... jeśli się zgadza to mam tak sprawdzać aż skończę całą próbkę, a jeśli gdzieś w tym jest jakiś piksel szukam kolejnego piksela na ekranie z kolorem pasującym do próbki 1x 1y?

Najszybszy sposób jaki do tego celu sobie wyobrażam, to użycie ScanLine, znalezienie pierwszego pasującego piksela (czyli tego z lewego górnego rogu miniaturki), a następnie porównanie całego wiersza pikseli, np. za pomocą funkcji CompareByte. Tej funkcji należy użyć w pętli, porównując wszystkie wiersze obrazu pulpitu i miniaturki.

I kolejna kwestia jak zapisywać próbkę w pliku projektu, jeśli jest to plik typowany ?

Nijak – nie możesz użyć do tego celu plików typowanych, bo każdy rekord w nich musi posiadać taki sam rozmiar (a właściwie, rozmiar rekordu musi być znany podczas kompilacji). Obraz nie posiada z góry określonej wagi, więc i rekordy w pliku miałyby różny rozmiar, a to kłóci się z ideą plików typowanych.


Użyj plików amorficznych – utwórz strumień, zapisz do niego wszystko co potrzeba i zwolnij strumień. Liczby mają stały rozmiar, więc tutaj problemu nie ma. Łańcuchy znaków to taki sam ”problem” jak inne dynamiczne twory. W tym przypadku najpierw należy zapisać długość ciągu liczoną w bajtach, a następnie sam ciąg znaków. Bitmapę natomiast bardzo łatwo wrzucić do strumienia – wystarczy skorzystać z metody TBitmap.SaveToStream.

Podczas odczytu robisz dokładnie to samo, tyle że na odwrót. Liczby wczytujesz bezpośrednio, bo tak zostały zapisane. Przy ciągach znaków najpierw wczytujesz długość, następnie ustalasz rozmiar ciągu za pomocą SetLength, a następnie ładujesz ich dane. Z bitmapą nie problem – wystarczy użyć metody TBitmap.LoadFromStream.

Łatwizna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1