Wielki Canvas i brak miejsca w magazynie.

0

Wykonuję polecenie w Delphi7:
Image1.Canvas.Ellipse(100,100,200.200); I pojawia się na ekranie piękne kółko.
Ale tak fajnie jest tylko wtedy gdy wymiary: Image1.Width i Image1.Height są nieduże (sprawdziłem do 6000/3000), a ja potrzebuję rysować na Canvasie 8000/4000 px i wtedy niestety:
DEBUGGER EXCEPTION NOTIFICATION
Project Proj1.exe raisetexception class EOutOfResources with message 'W magazynie brak miejsca dla wykonania tego polecenia'.Process stopped.....
Co mogę zrobić aby spełniło się moje marzenie o Wielkim Canvasie ??

0

A po co Ci taki ? Masz taki wielki ekran ?

0

Taki canvas zajmuje 8000*4000*3/1024/1024=91.5 MB pamięci.
Po co Ci takie wielkie płótno?

0

Taki duży jest potrzebny bo tyle zajmuje mapa wczytana z pliku do image.
Jest przewijana suwakami.
.

1

Robisz grę korzystając z kontrolek Windowsowych czy co? :P

0

Lekcja na dziś: wyświetla się tylko to, co jest Ci w danej chwili potrzebne - czyli canvas o rozmiarze okna :>

0

EOutOfResources a to nie jest przypadkiem tak że komp nie wydala? Zeżarło ram czy tam procka?

0

Taki duży jest potrzebny bo tyle zajmuje mapa wczytana z pliku do image.
Jest przewijana suwakami.
.
Takiego rozmiaru potrzebuje mapa o rozdzielczości ok 2400px/1??px (Wielkość komponentu Image jest dopasowywana do rozmiaru mapy :właściwość autosize w inspektorze obiektów i tyle to po tym autodopasowaniu wychodzi ok8400/4300 ) .Który fragment jest wyświetlany aktualnie na ekranie jest regulowane suwakami przez użytkownika .Nie wydaje mi się aby była inna możliwość niż wczytanie całej mapy w komponent Image.

Sprawa wydaje się nie do rozwiązania.. przynajmniej w Delphi.
Ale jeszcze sprawdzę co powie Lazarus.

0

Taki duży jest potrzebny bo tyle zajmuje mapa wczytana z pliku do image.
Jest przewijana suwakami.
.
Takiego rozmiaru potrzebuje mapa o rozdzielczości ok8800px/4980px (Wielkość komponentu Image jest dopasowywana do rozmiaru mapy :właściwość autosize w inspektorze obiektów i tyle to po tym autodopasowaniu wychodzi ok8800/5000 ) .Który fragment jest wyświetlany aktualnie na ekranie jest regulowane suwakami przez użytkownika .Nie wydaje mi się aby była inna możliwość niż wczytanie całej mapy w komponent Image.

Sprawa wydaje się nie do rozwiązania.. przynajmniej w Delphi.
Ale jeszcze sprawdzę co powie Lazarus.

0

EOutOfResources is the exception class for unsuccessful attempts to allocate handles.

EOutOfResources is raised when an application attempts to create a Windows or widget handle and there are no more handles to allocate.

Wygląda na to, że skończyła się pamięć do załadowania tak wielkiej kontrolki; Hierarchia wyjątku:

System.Classes.EOutOfResources.png</img>

Więcej informacji: EOutOfResources in Embarcadero;

0

jak chcesz się bawić dużymi obrazkami to zamiast TBitmap zainteresuj się CreateDIBSection - da radę wczytać/stworzyć bitmapy ponad 1GB.

A komunikat może być spowodowany tym, że system nie może zaalokować CIĄGŁEGO bloku o wymaganym rozmiarze. Nie wiem czy nie radzi sobie z tym system czy delphi.

Z drugiej strony na Delphi XE na w7 64b z 2GB RAM spokojnie da się stworzyć bitmapę o rozmiarze 20000x20000x24bity. Program w szczytowym momencie zajmuje ponad 1GB RAM (menadżer zadań windows pokazuje 126 000 MB) a bitmapa po zapisaniu na dysk ma dokładnie 1 200 000 054 bajtów.

Cały kod sprowadza się do

procedure TForm5.Button4Click(Sender: TObject);
var
  bmp: TBitmap;
begin
  bmp := TBitmap.Create;
  bmp.PixelFormat := pf24bit;
  bmp.Width := 20000;
  bmp.Height := 20000;
  bmp.Canvas.Ellipse(10, 10, 9000, 9000);
  bmp.SaveToFile('d:\download\aaa.bmp');
  bmp.Free;
end;

podaj może jaki sprzęt (ile ramu), jaki system i jakie delphi

0

Sprawdź jeszcze czy kod działa z użyciem innego memory-managera (tylko Delphi): http://sourceforge.net/projects/fastmm/

0

powiem tak, że właśnie sprawdzałem na D7 na XP z 3GB RAM i przeszło bez problemu.

Jak już pisali inni WYŚWIETLAĆ należy tylko to co faktycznie jest widoczne a nie ładować do image obrazek, którego nawet 10% nie pokazujesz

0

Dzięki abrakadaber, świetny sposób.

Wypróbowałem twój kod z bitmapą. Wszystko działało pięknie i problem o którym pisałem wczeniej zniknął. Rysuję bitmapę 10000X5000 zapisuję w pliku i ładuję image1 z tego pliku.Działa bez zarzutu.
Pojawił się jednak nowy problem którego nie potrafię rozwiązać.Mianowicie ta bitmapa za nic nie chce się stać się przezroczysta.
Pod spodem mam inny Image to znaczy Image2 w którym załadowana jest mapka topograficzna terenu (z pliku .jpeg) i musi być ona widoczna przez tę bitmapę która jest na wierzchu (coś jak grafika warstwowa).
Bitmapa jest po to aby robić różne zaznaczenia na mapce terenu w postaci kółek .

Wypróbowałem kod

procedure TForm1.BitBtn1Click(Sender: TObject);
var bmp: TBitmap;
begin
bmp := TBitmap.Create;
bmp.PixelFormat := pf8bit;
bmp.Width := 10000;
bmp.Height := 5000;
bmp.Canvas.Rectangle(4,4,10000-4,5000-4);
bmp.Canvas.Ellipse(10, 10, 20, 20);
** bmp.Transparent:=True;**
bmp.SaveToFile('aa.bmp');
bmp.Free;
Image1.Picture.LoadFromFile('aa.bmp');

Niestety bitmapa nie jet przezroczysta i zasłania to co jest pod spodem.
Również nie staje się przezroczysta gdy polecenie "bmp.Transparent:=True;"
umieszczam na końcu powyższej procedury lub w osobnej procedurze.

Konkluzja: wszystko jest pięknie tylko jak zrobić przeźroczystość?

0
glebis napisał(a)

Niestety bitmapa nie jet przezroczysta i zasłania to co jest pod spodem.
Również nie staje się przezroczysta gdy polecenie "bmp.Transparent:=True;"

Taki zapis nic Ci nie da, ponieważ bitmapa jest "przezroczysta" tylko podczas jej obróbki, właściwość ta zostaje utracona po zapisie grafiki do pliku; Dzieje się tak dlatego, że ten typ grafiki rastrowej tak naprawdę nie posiada przezroczystości (właściwie: kanału alpha), stąd takie informacje nie zostają wpisane do pliku i po ponownym wczytaniu grafiki z pliku do kontrolki klasy TImage dalej przezroczystości nie uzyskasz;

Trochę źle się zabierasz do tego, bo obiekt bmp służy jedynie do utworzenia grafiki, a do jej prezentowania (wyświetlenia) służy komponent Image1 i to właśnie w nim musisz ustawić przezroczystość - służy do tego właściwość Image1.Transparent; Ustawiając ją na True usuniesz tło i bitmapa stanie się "przezroczysta";

Podam przykład dla małej bitmapy, bo nie będę czekał godzinę aż mój dziadziuś załaduje spory plik; Aby stworzyć i poprawnie załadować taką bitmapę:

Back.png

i wyświetlić ją w komponencie Image1 trzeba posłużyć się np. takim kodem:

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TBitmap.Create() do
    begin
      PixelFormat := pf8bit;

      Width := 100;
      Height := 100;

      with Canvas do
        begin
          Pen.Color := clWhite;
          Brush.Color := clWhite;

          Rectangle(10, 10, 90, 90);

          Pen.Color := clBlack;
          Brush.Color := clBlue;

          Ellipse(10, 10, 90, 90);
        end;

      SaveToFile('C:\Back.bmp');
      Free();
    end;

  Image1.Picture.Bitmap.LoadFromFile('C:\Back.bmp');
end;

Kod wewnątrz pierwszego bloku zajmuje się jedynie utworzeniem interesującej nas grafiki i zapisanie jej do pliku (tutaj: C:\Back.bmp); Dalej jest już jedynie załadowanie obrazu do komponentu (odświeżać nie trzeba); Taki zabieg da nam poniższy efekt:

NoTransparency.png

Żeby jednak przezroczystość była obsługiwana należy w oknie inspektora obiektów ustawić właściwość Image1.Transparent na True lub zaprogramować to w kodzie przed załadowaniem grafiki do kontrolki:

  Image1.Transparent := True;
  Image1.Picture.Bitmap.LoadFromFile('C:\Back.bmp');

Dzięki temu załadowana bitmapa będzie przedstawiać się następująco:

Transparency.png

Jedyne o czym musisz pamietać to o mechanizmie usuwania tła w grafikach bmp; Działa on na takiej zasadzie, że z całej grafiki usuwany jest kolor piksela z lewego dolnego rogu grafiki; Usuwanie tła z obrazu to nie zwykły rozrost ziarna o początku w lewym dolnym rogu - kolor usuwany jest z całej grafiki bez względu na to, czy jakiś blok o innym kolorze oddziela go od pozostałej części; Więc jeśli w tym punkcie znajduje się kolor clBlack to znaczy, że na całej grafice nie zostanie on wyświetlony; Więcej na ten temat dowiesz się z własnych testów;

0
furious programming napisał(a):

Jedyne o czym musisz pamietać to o mechanizmie usuwania tła w grafikach bmp; Działa on na takiej zasadzie, że z całej grafiki usuwany jest kolor piksela z lewego dolnego rogu grafiki;

Masz rację ale tylko wtedy, gdy pozostawisz domyślne Bitmap.TransparentMode:=tmAuto.
Jeżeli natomiast ustawisz Bitmap.TransparentMode:=tmFixed, to wtedy jawnie deklarujesz Bitmap.TransparentColor:=co_tam_chcesz.

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