Odczyt wielkości ikony

0

Mam plik pojedynczej ikony o rozmiarach 128x128 pikseli w pliku. Jak ten rozmiar odczytać przy pomocy Delphi ? Chodzi mi o to, aby program przed jej wczytaniem do TImage nie akceptował innych rozmiarów oraz multiikon.

0

Nie wiem czy Delphi którego używasz (a którego używasz?) posiada jakiekolwiek wysokopoziomowe API do zarządzania ikonami i ich zawartością (grafikami). Jeśli takowego nie posiada i w sieci nie znajdziesz jakiejś ciekawej biblioteki, to sam system posiada zestaw funkcji służących do tego celu. Dzięki nim możesz określić liczbę grafik w pliku .ico, ich rozmiary czy pobrać uchwyt. W Twoim przypadku wystarczy sprawdzić czy plik zawiera jedną grafikę o konkretnych rozmiarach, więc to co system oferuje powinno wystarczyć.

Pytanie zasadnicze – dlaczego akurat ikony?

0

Dla potrzeb tej aplikacji używam starej Delphi 6 na Windows 10, dzięki czemu uzyskuję mały plik wynikowy, co w tym przypadku jest bardzo ważne. Użycie Delphi 10.1, którą również mam odpada. Stosowanie metody opisanej przez Ciebie jest mi znane, ale z powodów podanych wcześniej też odpada. Liczyłem, że załatwię temat jakąś prostą funkcją typu GetImageSize. Jak widzę nie będzie łatwo...

0

Panie czego ty tu nie wiesz.

Masz nagłówek header i tam jeśli na dwu bajcie wystąpi 1, to masz ico jeśli 2 to cur.

od 6 bajtu masz szerokość w jednym bajcie podaną, a na 7 bajcie wysokość w jednym bajcie.
Na 12 bajcie jest offset do obrazu, w 4 bajtach zapisany.

W jednym takim pliku może być kilka ikon np. w różnej rozdzielczość i header nagłówek jest jeden a iconimage structure może być jeden lub więcej.

0
grino napisał(a):

Dla potrzeb tej aplikacji używam starej Delphi 6 na Windows 10, dzięki czemu uzyskuję mały plik wynikowy, co w tym przypadku jest bardzo ważne.

Mały rozmiar? Malware piszesz, że tak Ci na tym zależy?

Stosowanie metody opisanej przez Ciebie jest mi znane, ale z powodów podanych wcześniej też odpada.

Dlaczego odpada? Kiedy nie było krowiastych bibliotek w stylu VCL, programiści mieli do dyspozycji praktycznie wyłącznie systemowe funkcje i z ich wykorzystaniem pisali kod. Dzięki temu pliki wykonywalne ważyły nierzadko kilkadziesiąt kilobajtów, zamiast kilku megabajtów.

Liczyłem, że załatwię temat jakąś prostą funkcją typu GetImageSize. Jak widzę nie będzie łatwo...

https://msdn.microsoft.com/en-us/library/ms997538.aspx – jest tam przykład odczytu danych nagłówka i pętli iterującej po wszystkich obrazkach, na kilkanaście linijek kodu C. Wymagane typy danych znajdziesz w module Windows.

0

Dzięki Panowie. Poradziłem sobie taką prostą funkcją:

function GetIconSize(Icon: TIcon; var X, Y: integer): boolean;
var
  h: THandle;
  IconInfo: TIconInfo;
  bmpmask: TBitmap;
begin
  result := Icon.Handle <> 0;
  
  if result then
  begin
    bmpmask := TBitmap.Create;
    try
      IconInfo.fIcon := true;
      try
        GetIconInfo(Icon.Handle, IconInfo);
        bmpmask.Handle := IconInfo.hbmMask;
        bmpmask.Dormant; 
      finally
        DeleteObject(IconInfo.hbmMask);
        DeleteObject(IconInfo.hbmColor)
      end;
      
      X := bmpmask.Width;
      Y := bmpmask.Height;
    finally
      bmpmask.Free;
    end;
  end;
end;
0

Spełnia i to doskonale. Chodziło przecież o to, by odrzucić wszystko, co nie ma rozmiarów 128x128 pix. Inne rozmiary oraz multiikony nie spełniają tego warunku (x< >128 and y< >128) i wystarczy. To naprawdę działa ! :)

0

W jaki sposób ten kod odrzuca multiikony? Przecież jedyne co on robi to odczytuje pośrednio te same dane, które zwracają właściwości Width i Height.

Sprawdź co zwróci Twój kod dla ikony z załącznika – system pokazuje, że ikona posiada rozmiary 128x128 pikseli.

0

Ha, tu wywala, że "Parametr jest nieprawidłowy". ale przecież to "Delfinek" 6 i on nie obsługuje ikon powyżej 128 px (resource). Obsługa tego błędu załatwia sprawę. W pozostałych przypadkach multiikon zawsze dostaję 32X32 px. Mnie interesuje, że jeśli 128X128 px to OK, wszystkie inne nie spełniają wymagań i odpadają.

0

Z tego co pamiętam, właściwości TIcon.Width i TIcon.Height zwracają rozmiar najmniejszego obrazu, więc cała Twoja funkcja staje się zbędna. No i pozostaje też jeszcze jeden przypadek – jeśli ikona zawiera np. dwa obrazy o wymaganym rozmiarze (tak, jest to możliwe). Wtedy Twój sposób też ”łyknie” taką ikonkę.

Dlatego sugerowałem skorzystanie z funkcji WinAPI, aby jasno określić ile jest obrazów w danej ikonie i jesli jest jeden, pobrać jego rozmiar już w dowolny sposób.

0

Jeżeli mamy dwie ikonki o tym samym rozmiarze, ale np. True Color i XP (RGB + alpha), bo o tym zapewne piszesz, to mój TImage też to łyknie i nie ma sprawy. Z drugiej strony masz rację, wystarczyło skorzystać TIcon.Width i TIcon.Height. Człowiek uczy się całe życie i zapewne wiesz jaki umiera.

0
grino napisał(a):

Jeżeli mamy dwie ikonki o tym samym rozmiarze, ale np. True Color i XP (RGB + alpha), bo o tym zapewne piszesz […]

W jednej ikonie może być kilka obrazów o takim samym rozmiarze i takiej samej głębi, ale o różnej zawartości. Oczywiście nikt takich ikon nie robi celowo, bo nie ma to sensu, jednak dobrze by było, gdyby Twój program prawidłowo reagował na każdą ikonkę.

Z drugiej strony masz rację, wystarczyło skorzystać TIcon.Width i TIcon.Height.

Jeśli klasa TIcon z Delphi 6 faktycznie zawsze zwraca rozmiar najmniejszego obrazu, to w zupełności wystarczy skorzystanie z tych właściwości.

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