Rozpoznawanie pliku graficznego załadowanego do TImage

Rozpoznawanie pliku graficznego załadowanego do TImage
Romlus
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Postów:124
0

Ładuję do komponentu TImage co jakiś czas różne pliki graficzne (png) i chciałbym rozpoznać, który plik jest aktualnie załadowany. Próbowałem tak:

Kopiuj
if Image1.Picture.Graphic.Equals(bitmapa1) then

ale nie wychodzi.

edytowany 1x, ostatnio: flowCRANE
abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:7 miesięcy
  • Postów:6610
0

co to znaczy który plik jest aktualnie załadowany? Jak ładujesz, skąd?


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
0

Chodzi o porównanie zawartości, tak?


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Romlus
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Postów:124
0

Załadowany instrukcją LoadFromFile(filename)
Chcę wiedzieć jaki plik graficzny jest obecnie w komponencie TIMage. Czyli znać albo nazwę pliku graficznego (może być ze ścieżką dostępu), albo czy dany plik graficzny np.

Kopiuj
Var bitmap1:TBitmap;

bitmap1:=TBitmap.create;
bitmap1.loadfromfile(filename);

np. Bitmap1 jest aktualnie w TImage, czy też jakiś inny.

edytowany 1x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
0

No to sobie tę ścieżkę gdzieś przechowaj – w czym problem?

A jak potrzebujesz porównać zawartość dwóch obrazów, to do tego celu służy metoda Equals.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
Romlus
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Postów:124
0

Chodzi o to by tą ścieżkę odczytać z TImage.
Equals też nie wchodzi w grę.

Jest kilka plików graficznych, chodzi o to że nie wiem jaki obecnie jest w TImage i chcę odczytać z TImage jaki plik jest załadowany.

edytowany 1x, ostatnio: flowCRANE
LA
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 21 godzin
  • Postów:469
2

TImage nie przechowuje takiej informacji.
Równie dobrze możesz ustawić obraz z kamerki lub wkleić ze schowka - jak by była wtedy ścieżka?

Romlus
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad rok
  • Postów:124
0

A może to porównywanie obrazów byłoby możliwe.Jak jednak porównać do siebie dwie grafiki po ich wyglądzie czy są takie same?

flowCRANE
Porównanie zawartości nie ma sensu, bo musisz dodatkowo ładować obraz aby przeprowadzić takie porównanie. Tobie potrzebna jest nazwa pliku, więc takie informacje powinieneś sobie przechowywać i odczytywać.
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
1

Rozszerz sobie subclassingiem klasę TImage i dodaj do niej właściwość służącą do odczytu ścieżki ładowanego pliku oraz metodę, która załaduje obraz z pliku i zapamięta ścieżkę. I z głowy. ;)

Kopiuj
type
  TImage = class(ExtCtrls.TImage)
  private
    FFileName: String;
  public
    procedure LoadImageStoreName(const AFileName: String);
    procedure DoneImageClearName();
  public
    property FileName: String read FFileName;
  end;

{..}

procedure TImage.LoadImageStoreName(const AFileName: String);
begin
  Picture.LoadFromFile(AFileName);
  FFileName := AFileName;
end;

procedure TImage.DoneImageClearName();
begin
  Picture.Clear();
  FFileName := '';
end;

I zamiast używać metody LoadFromFile, użyj LoadImageStoreName (drugiej do usunięcia obrazu i nazwy).

A jeśli tych kontrolek używasz w wielu formularzach to zamiast subclassingu, po prostu stwórz sobie własną kontrolkę dziedziczącą z TImage i rozszerz jej funkcjonalność w podobny sposób.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
PW
  • Rejestracja:ponad 9 lat
  • Ostatnio:4 miesiące
  • Postów:130
0

A czy przypadkiem nie chodzi Ci o coś takiego... detecting graphic formats

flowCRANE
Nie – w tym poście napisał, że chce znać ścieżkę pliku załadowanego do komponentu.
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
furious programming napisał(a):

/ciach/

A jak potrzebujesz porównać zawartość dwóch obrazów, to do tego celu służy metoda Equals.

Nooo... nie.
Metoda Equals został zaimplementowana na poziomie TObject w ten sposób:

Kopiuj
function TObject.Equals(Obj: TObject): Boolean;
begin
  Result := Obj = Self;
end;

I służy do sprawdzenia czy podana referencja na obiekt jest tym samym obiektem z którego wywołujemy metodę Equals.
Ale na pewno nie porównuje ona dwóch obrazów.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
0

Vcl.Graphics.TGraphic.Equals

Compare graphic to another TGraphic object and return true if objects contain same graphic.

Equals compares the contents of two TGraphic objects. Equals returns false if the TGraphic are different classes or if they contain different graphical data.

Dokumentacja kłamie? ;)


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
1
furious programming napisał(a):

Vcl.Graphics.TGraphic.Equals

Compare graphic to another TGraphic object and return true if objects contain same graphic.

Equals compares the contents of two TGraphic objects. Equals returns false if the TGraphic are different classes or if they contain different graphical data.

Dokumentacja kłamie? ;)

Pewnie ;)

TGraphic faktycznie ma inną implementację, ale ona na pewno nie sprawdza obrazów.
Sprawdza typ pliku graficznego i rozmiar strumienia - ale nie porównuje obrazu :)

Innymi słowy - mając ten sam obraz w różnych formatach graficznych, ta metoda zawsze zwróci False.
Mając inne obrazy, w tym samym formacie grafiki i z identycznym rozmiarem, metoda zwróci True.
Czy to jest porównanie obrazów? ;-)

edytowany 2x, ostatnio: wloochacz
flowCRANE
Bez sensu… :D
Stefan_3N
  • Rejestracja:około 6 lat
  • Ostatnio:12 dni
  • Postów:145
1

Nie wiem o co autorowi dokładnie chodzi. Nie znam też wewnętrznych implementacji klas, o których rozmawiacie.
Ale padło tu pytanie jak porównać dwa pliki graficzne czy są takie same.
Jeśli chodzi o bitmapy to stosunkowo proste zadane.
Bitmapy są przechowywane w pamięci w dwóch postaciach:

  1. Albo jako zależne od sprzętu (z uchwytem HBITMAP)
  2. Albo jako bitmapy DIB (niezależne od sprzętu).

W tym drugim przypadku aby manipulować bitmapą trzeba znać dwa adresy:

  1. Adres nagłówka BITMAPINFOHEADER
  2. Adres bajtów stanowiących treść obrazu
    Jeśli bitmapa ma mniej niż 8 bitów na piksel, to bezpośrednio za BITMAPINFOHEADER pamiętana jest tablica kolorów.
    Bajty stanowiące treść obrazu mogą znajdować się bezpośrednio za tablicą kolorów, ale nie muszą.

Żeby porównać dwie bitmapy trzeba:

  1. Porównać ich nagłówki (memcmp(adrHeader1, adrHeader2, sizeof(BITMAPINFOHEADER))
    Jeśli są różne - to na pewno bitmapy są różne.

  2. Sprawdzić pole biBitCount w BITMAPINFOHEADER i jeśli jest osiem lub mniej, to wyliczyć rozmiar tablicy kolorów.
    Tablica kolorów jest pamiętana jako tablica RGBQUAD (cztery bajty na jeden kolor).
    Liczba pozycji w tablicy kolorów to 2 do potęgi biBitCount.
    Znając rozmiar tablicy kolorów, trzeba porównać tablice obu bitmap i jeśli są różne - to bitmapy na pewno są różne.
    BITMAPINFOHEADER + tablica kolorów wzięte razem stanowią strukturę BITMAPINFO.

  3. Porównać bajty zawierające treść obrazu
    Rozmiar tego obszaru - to:
    ScanBytes(header->biWidth, header->biBitCount)*header->biHeight;
    ScanBytes - to funkcja wyliczająca szerokość linii skanowania

Kopiuj
long ScanBytes(long pixWidth, int bitsPixel) {
           return ((pixWidth*bitsPixel+31)>>5)<<2;
}

(linia skanowania w bajtach jest zaokrąglana do najbliższej granicy czterech bajtów w górę).

Jeśli natomiast bitmapa jest pamiętana jako zależna od sprzętu, to mamy do niej uchwyt HBITMAP.
Wtedy trzeba byłoby ją przekonwertować na DIB. Aby to zrobić należy przydzielić dwa obszary pamięci (na BITMAPINFO, tzn. BITMAPINFOHEADER + ewentualnie tablica kolorów i na bajty zawierające treść obrazu), a następnie wykonać funkcję GetDIBits (przed jej wykonaniem należy wypełnić BITMAPINFOHEADER). Po wykonaniu tej funkcji mamy dane w BITMAPINFOHEADER i w obszarze z treścią obrazu i dalej działamy jak opisałem wyżej.


edytowany 2x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12164
1

Jeśli mowa o bitmapach ładowanych do obiektów klasy TBitmap, to porównanie ich zawartości jest bardzo proste. Wystarczy skorzystać z właściwości ScanLine i z faktu, że piksele są 24-bitowe w pamięci.

Kopiuj
function CompareBitmaps(ABitmapA, ABitmapB: TBitmap): Boolean;
var
  LineIndex, LineSize: Integer;
begin
  if ABitmapA.Width <> ABitmapB.Width then Exit(False);
  if ABitmapA.Height <> ABitmapB.Height then Exit(False);

  LineSize := ABitmapA.Width * SizeOf(TRGBTriple);

  for LineIndex := 0 to ABitmapA.Height - 1 do
    if not CompareMem(ABitmapA.ScanLine[LineIndex], ABitmapB.ScanLine[LineIndex], LineSize) then
      Exit(False);

  Result := True;
end;

Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
Stefan_3N
Czy zawsze są 24-bitowe? Chyba nie.
flowCRANE
Po załadowaniu obrazu do klasy TBitmap, alokowany jest blok pamięci, do którego wypakowywane są dane na temat pikseli (dostęp do niego daje właściwość ScanLine). Blok ten zawsze zawiera piksele 24-bitowe, bez względu na to czy załadowano obraz 24-bitowy, czy 4-bitowy – dlatego można ”walić w ciemno”.
flowCRANE
Przynajmniej tak mam w LCL. Choć na tym polu powinien być zgodny z z VCL.
Stefan_3N
A bitmapy z przeźroczystością?
flowCRANE
32-bitowe? Nie wiem – nie używałem jeszcze takich. Pewnie przezroczystość jest ucinana. :P
flowCRANE
Sam używam Lazarusa i klas zawartych w bibliotece komponentów – po to, aby kod był przenośny pomiędzy platformami. Podstawowa klasa TBitmap ma bardzo prostą funkcjonalność, praktycznie ogranicza się do obsługi 24-bitowych obrazów i takich używam np. w swojej gierce. Zawsze traktuję piksele jako 24-bitowe, pomimo tego, że w plikach te obrazy są 4-bitowe (indeksowana paleta kolorów) i skompresowane za pomocą RLE (coby mniej ważyły). Przy ładowaniu do pamięci, obraz jest automatycznie dekompresowany do postaci 24-bitowej i takiego się następnie używa.
flowCRANE
Natomiast do konkretnych edycji obrazów jest np. klasa TFPMemoryImage, która przechowuje dane na temat pikseli w formie 64-bitowej (po 16 bitów na kanał) i pozwala na wszystko (obsługę różnych formatów, zmianę bitowości, obsługę palet kolorów, kompresję itd.). No i też jest wieloplatformowa.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)