ďťż

Ładny brzuch

Wczytuję sobie do TImage obrazek (np. jpeg lub bmp). Załóżmy że ma on dośc wysoką rozdzielczość (np. 2048x1536). Chcę ten obrazek zmniejszyć np. do wymiarów 800x600, a następnie zapisać go (jako jpeg). O ile ze zmniejszaniem w TImage sobie poradziłem (Stretch->true), udaje mi się także ten plik zapisać (Image1->Picture->SaveToFile();) to niestety - nie mogę zapisać przeskalowanego obrazka. Zapisuje mi obrazek w takiej rozdzielczości, w jakiej został on odczytany. Czy jest może jakiś prosty sposób, żeby to zrobić? Gdzieś na pl.comp.lang.c znalazłem coś z użyciem TBitmap oraz Canvas, ale to jakoś mi to nie bardzo wychodziło. Jeśli ktoś wie jak sobie poradzić z moim problemem, to b. proszę o odpowiedź. Z góry dziękuję.



Tworzysz drugi TImage, przechwytujesz z pierwszego przeskalowany obraz (była to chba funckja Image2->Picture->Attach( Image1->Picture->Bitmap );, nie jestem pewny więc poszukaj) i zapisujesz :)

procedure TForm1.Button1Click(Sender: TObject); var b:tbitmap; j:tjpegimage; r:trect; begin b:=tbitmap.Create; b.Width:=Image1.Width; b.Height:=Image1.Height; r.Left:=Image1.Left; r.Top:=Image1.Top; r.Right:=Image1.Left+Image1.Width; r.Bottom:=Image1.Top+Image1.Height; b.Canvas.CopyRect(b.Canvas.ClipRect,Canvas,r); b.SaveToFile('b.bmp'); //jeżeli zapisujemy do jpg: j:=tjpegimage.Create; j.Assign(B); j.SaveToFile('b.jpg'); j.Free; // b.Free; end;


(...)Picture->Attach
Niestety - nie znalazłem nigdzie funkjci Attach. Ten pomysł z kopiowaniem może być niegłupi, ale nie wiem jak to zrobić. Jeśli masz jakiś pomysł, to proszę o odp.
Co do metody Cyrkla - niewykluczone, że działa, ale... w Delphi. Ja piszę w c++ ;). Próbowałem to podobnie zapisać w c++, ale nic z tego nie wychodziło.



Image2->Picture->Assign(Image1->Picture);


Niestety - nie znalazłem nigdzie funkjci Attach. Ten pomysł z kopiowaniem może być niegłupi, ale nie wiem jak to zrobić. Jeśli masz jakiś pomysł, to proszę o odp.
Co do metody Cyrkla - niewykluczone, że działa, ale... w Delphi. Ja piszę w c++ ;). Próbowałem to podobnie zapisać w c++, ale nic z tego nie wychodziło.

Później spróbuję przerobić na c++.


Image2->Picture->Assign(Image1->Picture);
Tak - to kopiuje obrazek z Image1 do Image2, ale jak zapisuje to co jest w Image2 to i tak mam pierwotny rozmiar.
Jak chcę się odwołaś do wysokości Image1 albo Image2 to mi wyskakuje błąd:
E2247 'TPicture::Height' is not accessible.

Co robić?

Tak by mi się to widziało, ale nie mam pod ręką bcb, a z cpp raczej cienki jestem ;)
RECT r; TBitmap* b = new TBitmap; b -> Width = Image1 -> Width; b -> Height = Image1 -> Height; r.Left = Image1 -> Left; r.Top = Image1 -> Top; r.Right = Image1 -> Left + Image1 -> Width; r.Bottom = Image1 -> Top + Image1 -> Height; b -> Canvas -> CopyRect(b -> Canvas -> ClipRect,Canvas,r); b -> SaveToFile("pliczek.bmp");

Ok. Dzięki. Próbowałem właśnie coś z Canvas, ale słabo to raczej wychodziło. To działa. Spróbuje coś wymyśleć, żeby zapisywał to do jpeg, ale to już na jutro. Jak nic nie wymyśle to wtedy napiszę. Też chcę pokombinować, żeby nie było, że tylko was wykorzystuje :) W każdym razie wielkie dzięki.


a z cpp raczej cienki jestem
dobra, dobra ;)
Użytkownik sopel edytował ten post 18 kwiecień 2005, 21:32

Ok. Dzięki. Próbowałem właśnie coś z Canvas, ale słabo to raczej wychodziło. To działa. Spróbuje coś wymyśleć, żeby zapisywał to do jpeg, ale to już na jutro. Jak nic nie wymyśle to wtedy napiszę. Też chcę pokombinować, żeby nie było, że tylko was wykorzystuje :) W każdym razie wielkie dzięki.
dobra, dobra ;)

To, co napisałem działa? :D Jak Ci nie wyjdzie jpeg, napisz ;)


Jak Ci nie wyjdzie jpeg
Nie wychodzi

napisz
...ok

A więc tak:
Słabo wiem, jak zmniejszyć obrazek bez użycia bitmap. Zrobiłem tak:
TJPEGImage* jpg = new TJPEGImage
i potem jak chciałem się odwołać do jpg->Height to program mi się kompilował, ale podczas działania wyrzucało mi błąd:

Cannot change the size if a JPEG image . Więc najpierw zrobiłem Twoim sposobem, potem bitmapę przerzuciłem do jpeg (jpg->Assign()) no i się zapisywało.
Wszystko pięknie, z jednym tylko ale: ponieważ obrazek znajdujący się w Image jest na początku od niego (Image'a) dużo większy jest skalowany. Po skalowaniu obrazek jest dopasowany do Image, ale nie zajmuje całego jego obszaru - po bokach zostaje szare miejsce - tam nic nie ma, ale to szare miejsce zapisuje się w pliku. No i właśnie tutaj się gubie. Czy da się jakoś to szare miejsce wyeliminować?
Ja trochę próbowałem zmieniać Twój kod, ale nie przyniosło to najlepszych efektów.
Nie wiem do czego się odwołać. Jak się odwołuje do Image1->Picture->Width to mi wychodzi szerokość obrazka przed skalowaniem. Próbowałem dzielić też te rozmiary ale wtedy wychodziły mi straszne czerwone punkty na obrazku, jego jakość drastycznie spadała i ogólnie było źle ;)
Aha - kończąc ten mój już przydługi post chciałbym powiedzieć o pewnej ciekawostce (jeśli można tak powiedzieć). Być może nie odkryłem nic ciekawego, ale mnie to zdziwiło. Jeśli zrobimy tak:
Image1->Left=-16; to po zapisaniu pliku zapisze nam się kawałek formy - w tym przypadku lewa jej krawędź. To samo się stanie jak na powierzchni Image umieści się jakiś inny komponent - zostanie on zapisany na obrazku. Przynajmniej tą metodą.
Ale chyba trochę zmieniłem temat. Wciąż nie wiem jak pozbyć się tego szarego miejsca z boków. Gdybyś wiedział co i jak to weź mnie poinstruuj ;).. Dzięki.
Użytkownik sopel edytował ten post 19 kwiecień 2005, 07:04


Heh, ten program po prostu robi zrzut ekranu (a właściwie tylko formy) w miejscu, gdzie jest obrazek. W żadnym miejscu nie korzystam z image1 :D Na jpeg to będzie chyba tak ;)
//napisz to po tamtym kodzie: TJPEGImage* j = new TJPEGImage; j -> Assign(b); j -> SaveToFile("jpeggggg.jpg"); j -> Free;
TImage powiększa obrazek, dopiero przy rysowaniu i nie wiem, jak to wyciągnąć :mellow:

Looknij tutaj


Looknij tutaj
Sposób opisany tutaj działa (dlaczego miałby nie działać? ;)). O ile udało mi się już dojść jak zapisać to jako jpg a nie bmp, to niestety dalej nie wychodzi mi samo skalowanie. Obrazek zostaje oczywiście zmniejszony, ale traci swoje proporcje. Jeśli jest mniejszy to jest powiększany. Zdarza się, że jest po prostu źle ustawiony no i niestety znaczy, że dobrze nie jest. Czy da się coś z tym zrobić? Chodzi mi o samo przeskalowanie obrazka. Jest taka funkjca w irfan view. To chyba nie jest takie trudne... No właśnie - jak dla kogo. Ja nie mam pomysłu. Gdyby ktoś wiedział i chciałby się tą wiedzą ze mną podzielić, to by było nieźle :)
Z góry dzięki.

Od dawna w tym temacie nic ciekawego się nie pojawiało, ale ponieważ udało mi się uzyskać odpowiedź na moje pytanie, postanowiłem, że się nią podziele z innymi interneutami. Zwłaszcza, że tejże odpowiedzi szukałem dość długo, ale do rzeczy. Zakładam, że wysokość i szerokość Image1=200, właściwość Proportional i Stretch Image1 ustawiam na true. A kod, który skaluje obrazek zamieszczam poniżej. if (OpenDialog1->Execute())    {        Image1->Picture->LoadFromFile(OpenDialog1->FileName);        Graphics::TBitmap* StretchedBitmap = new Graphics::TBitmap();        //kawalek mojego kodu        float dzielnik;        int szerokosc, wysokosc;        if(Image1->Picture->Width > Image1->Picture->Height)         dzielnik=(float) (Image1->Picture->Width) / (float) (Image1->Width);        if(Image1->Picture->Width < Image1->Picture->Height)         dzielnik=(float) (Image1->Picture->Height) / (float) (Image1->Height);        else         dzielnik=(float) (Image1->Picture->Height) / (float) (Image1->Height);        szerokosc=Image1->Picture->Width / dzielnik;        wysokosc=Image1->Picture->Height / dzielnik;        StretchedBitmap->Width = szerokosc;        StretchedBitmap->Height = wysokosc;        Label1->Caption=CurrToStr(dzielnik);        //koniec mojego kodu         StretchedBitmap->Canvas->StretchDraw( Rect(0, 0, StretchedBitmap->Width, StretchedBitmap->Height), Image1->Picture->Bitmap );        StretchedBitmap->SaveToFile("stretchedImage.bmp");        StretchedBitmap->FreeImage();    }

Cały kod (poza tym ujętym między komentarze) jest autorstwa jednej z osób, które redagują Eksperta. Nie wiem, czy powinienem podawać jego nazwisko. W każdym razie mogę tylko napisać: "Dziękuję Panie Pawle".

P.S.1. Uważam, że temat jest do zamknięcia.
P.S.2. Nie umieszczałem kodu na specjalnym serwerze, bo sądzę, że nie jest go tutaj tak dużo oraz dzięki temu, że jest bezpośrenio w temacie - jest lepiej ;) Oczywiśćie na prośbę moderatorów mogę przenieść go na serwer ;)

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •