Ĺadny brzuch
Witam,
mam mały problem z moim programikiem.
Otóż mam problem z napisaniem programu, który powinien zrobić zrzut ekranu, skompresować go do jpg i przechowywać jego zawartość w zmiennej np. typu string w taki sposób, żeby program nie zapisywał nic do pliku.
jak na razie mam taki kod:
uses jpeg; [...] var ScreenDC: HDC; Bitmap:TBitmap; FJpeg:TJpegImage; begin Bitmap:=TBitmap.Create; FJpeg := TJpegImage.Create; Bitmap.Width:=GetSystemMetrics(SM_CXSCREEN); Bitmap.Height:=GetSystemMetrics(SM_CYSCREEN); ScreenDC:=GetDC(0); BitBlt(Bitmap.Canvas.Handle,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), ScreenDC, 0 , 0, SRCCOPY); ReleaseDC(0, ScreenDC); FJpeg.Assign(Bitmap); Bitmap.Free; FJpeg.CompressionQuality:=20; FJpeg.Compress; //FJpeg.SaveToFile('D:\test.jpg'); FJpeg.Free; end;
nie wiem co mam zrobić dalej.... najłatwiej byłoby zapisać jpega do pliku a później go odczytać i zapisać tą wartość w stringu, ale tak zrobić nie mogę...
Proszę o pomoc i pozdrawiam
Możesz mi wyjaśnić co dokładnie rozumiesz pod "skompresować go do jpg i przechowywać jego zawartość w zmiennej np. typu string" ?
Użytkownik p1101 edytował ten post 06 maj 2007, 11:23
Możesz mi wyjaśnić co dokładnie rozumiesz pod "skompresować go do jpg i przechowywać jego zawartość w zmiennej np. typu string" ?
Chodzi mi o to, żeby w jakieś zmiennej (np string) była przechowywana zawartość tego obrazka w taki sposób, że jeśli zawartość tej zmiennej zapiszę do pliku, a następnie go otworzę, ujrzę zwykły obrazek.
Można to zrobić np. w taki sposób:
zapisać jpg do pliku, a później ten plik odczytać i jego zawartość przypisać zmiennej - ale chce to zrobić tak, żeby nie zapisywać nic do pliku (operować na samej pamięci)
hmm nie wiem jak to łatwiej wytłumaczyć :P
// ps wiem że trzeba to zrobić na TStream
// ps2 ulepszyłem troche kod:
uses jpeg; [...] var ScreenDC: HDC; Bitmap:TBitmap; FJpeg:TJpegImage; FStream:TStream; begin Bitmap:=TBitmap.Create; FJpeg := TJpegImage.Create; Bitmap.Width:=GetSystemMetrics(SM_CXSCREEN); Bitmap.Height:=GetSystemMetrics(SM_CYSCREEN); ScreenDC:=GetDC(0); BitBlt(Bitmap.Canvas.Handle,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), ScreenDC, 0 , 0, SRCCOPY); ReleaseDC(0, ScreenDC); FStream := TStringStream.Create(''); FJpeg.Assign(Bitmap); Bitmap.Free; FJpeg.CompressionQuality:=20; FJpeg.Compress; //FJpeg.SaveToFile('D:\test.jpg'); Fjpeg.SaveToStream(FStream); FJpeg.Free; end;
teraz zawartość obrazka mam zapisaną w zmiennej FStream,
jednak muszę przekonwertować to do zmiennej typu string...
Użytkownik tsukuyomi_reload edytował ten post 06 maj 2007, 11:43
Hm, ja chyba czegos nie rozumiem ;)
Chcesz przechowywac ten obrazek w pamieci, to przechowuj w go w TJPEGImage, po co string? ;)
niestety jest to potrzebne, gdyż dalej programik ma wysyłać ów obrazek przez internet :)
niestety jest to potrzebne, gdyż dalej programik ma wysyłać ów obrazek przez internet :)
bylo tak od razu :)
najlatwiej zapisac do strumienia i wysylac po fragmencie zawartosc tego strumienia
(stream.Memory)
Jeśli chodzi o obrazek jako tekst to wykombinowałem z helpem coś takiego za pomocą ObjectBinartToText() i ObjectTextToBinary(). Niestety wymaga utworzenia to sobie TImage, gdyż działa tylko dla zapisu komponentu w strumieniu TMemoryStream.
var StringImage: string; //zmienna globalna. Tu bedzie nasza tekstowa reprezentacja obrazu {...} var BMP: TBitmap; //do tego właduj swoj zrzut ekranu img: TImage; StrStream:TStringStream; BinStream: TMemoryStream; s: string; begin {tu sobie wczytasz do BMP swoj zrzut} img := TImage.Create(nil); //bez parenta img.Picture.Bitmap := BMP; BinStream := TMemoryStream.Create; try StrStream := TStringStream.Create(s); try BinStream.WriteComponent(img); BinStream.Seek(0, soFromBeginning); ObjectBinaryToText(BinStream, StrStream); StrStream.Seek(0, soFromBeginning); StringImage := StrStream.DataString; finally StrStream.Free; end; finally BinStream.Free end; img.Free;
Teraz odczyt:
var StrStream:TStringStream; BinStream: TMemoryStream; img: TImage; begin img := TImage.Create(nil); //znowu 'wirtualny obrazek' StrStream := TStringStream.Create(StringImage); try BinStream := TMemoryStream.Create; try ObjectTextToBinary(StrStream, BinStream); BinStream.Seek(0, soFromBeginning); (BinStream.ReadComponent(img) as TImage).Picture.SaveToFile('C:\plik.bmp'); //zapis finally BinStream.Free; end; finally StrStream.Free; end; img.free;
Mam nadzieję, że trybi :) Idealnie byłoby wyciągnąć sobie samo PictureData z zapisu tekstowego, ale nie wiem jak to zrobić.
Użytkownik p1101 edytował ten post 06 maj 2007, 13:29
hmm no w sumie wszystko jest spoko, ale jak zrobić to samo z kompresją do jpg
Tak samo jak robiłeś wcześniej.
JPG.Assign((BinStream.ReadComponent(img) as TImage).Picture.Bitmap); //połączenie do JPG
Użytkownik p1101 edytował ten post 06 maj 2007, 16:09
miałem na myśli najpierw skompresować do jpg a później odczytać stringimage ;)
Pomyśl! Schemat działania jest analogiczny. Próbowałeś chociaż? W procedurze zamiany obrazka na tekst, mając go wczytanego do BMP:
... JPG.Assign(BMP); img.Picture.Graphic := JPG;
Oczywiście że próbowałem... i miałem bodajże access volation, tylko nie pamiętam w którym miejscu
w każdym bądź razie znalazłem bardzo fajny kod do wysyłania obrazków:
http://www.delphi300...le_2313.asp?SK=
dla tych co się tam nie zarejestrowali:
Question/Problem/Abstract: How can I send files using TClientSocket & TServerSocket? Sending files with TClientSocket/TServerSocket Answer: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Image1: TImage; Image2: TImage; ClientSocket1: TClientSocket; ServerSocket1: TServerSocket; Button1: TButton; procedure Image1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); private { Private declarations } Reciving: boolean; DataSize: integer; Data: TMemoryStream; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Image1Click(Sender: TObject); begin // This is the procedure to open the socket for RECEIVING. // Button1.Click is this procedure as well. ClientSocket1.Active:= true; end; procedure TForm1.FormCreate(Sender: TObject); begin // Open the SENDING socket. ServerSocket1.Active:= true; end; procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); begin // Send command to start the file sending. Socket.SendText('send'); end; procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); var s, sl: string; begin s:= Socket.ReceiveText; // If we're not in recieve mode: if not Reciving then begin // Now we need to get the length of the data stream. SetLength(sl, StrLen(PChar(s))+1); // +1 for the null terminator StrLCopy(@sl[1], PChar(s), Length(sl)-1); DataSize:= StrToInt(sl); Data:= TMemoryStream.Create; // Delete the size information from the data. Delete(s, 1, Length(sl)); Reciving:= true; end; // Store the data to the file, until we've received all the data. try Data.Write(s[1], length(s)); if Data.Size = DataSize then begin Data.Position:= 0; Image2.Picture.Bitmap.LoadFromStream(Data); Data.Free; Reciving:= false; Socket.Close; end; except Data.Free; end; end; procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var ms: TMemoryStream; begin // The client wants us to send the file. if Socket.ReceiveText = 'send' then begin ms:= TMemoryStream.Create; try // Get the data to send. Image1.Picture.Bitmap.SaveToStream(ms); ms.Position:= 0; // Add the length of the data, so the client // will know how much data to expect. // Append #0 so it can determine where the size info stops. Socket.SendText(IntToStr(ms.Size) + #0); // Send it (the socket owns the stream from now on). Socket.SendStream(ms); except // So only free the stream if something goes wrong. ms.Free; end; end; end; end.
Dawno napisany programik (w sumie dwa, klient i serwer) do przesyłania na żądanie zrzutów ekranu. Wystarczy mała modyfikacja :)
http://cyrkiel.webpark.pl/scrnnn.zip
zanotowane.pl doc.pisz.pl pdf.pisz.pl zsf.htw.pl
mam mały problem z moim programikiem.
Otóż mam problem z napisaniem programu, który powinien zrobić zrzut ekranu, skompresować go do jpg i przechowywać jego zawartość w zmiennej np. typu string w taki sposób, żeby program nie zapisywał nic do pliku.
jak na razie mam taki kod:
uses jpeg; [...] var ScreenDC: HDC; Bitmap:TBitmap; FJpeg:TJpegImage; begin Bitmap:=TBitmap.Create; FJpeg := TJpegImage.Create; Bitmap.Width:=GetSystemMetrics(SM_CXSCREEN); Bitmap.Height:=GetSystemMetrics(SM_CYSCREEN); ScreenDC:=GetDC(0); BitBlt(Bitmap.Canvas.Handle,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), ScreenDC, 0 , 0, SRCCOPY); ReleaseDC(0, ScreenDC); FJpeg.Assign(Bitmap); Bitmap.Free; FJpeg.CompressionQuality:=20; FJpeg.Compress; //FJpeg.SaveToFile('D:\test.jpg'); FJpeg.Free; end;
nie wiem co mam zrobić dalej.... najłatwiej byłoby zapisać jpega do pliku a później go odczytać i zapisać tą wartość w stringu, ale tak zrobić nie mogę...
Proszę o pomoc i pozdrawiam
Możesz mi wyjaśnić co dokładnie rozumiesz pod "skompresować go do jpg i przechowywać jego zawartość w zmiennej np. typu string" ?
Użytkownik p1101 edytował ten post 06 maj 2007, 11:23
Możesz mi wyjaśnić co dokładnie rozumiesz pod "skompresować go do jpg i przechowywać jego zawartość w zmiennej np. typu string" ?
Chodzi mi o to, żeby w jakieś zmiennej (np string) była przechowywana zawartość tego obrazka w taki sposób, że jeśli zawartość tej zmiennej zapiszę do pliku, a następnie go otworzę, ujrzę zwykły obrazek.
Można to zrobić np. w taki sposób:
zapisać jpg do pliku, a później ten plik odczytać i jego zawartość przypisać zmiennej - ale chce to zrobić tak, żeby nie zapisywać nic do pliku (operować na samej pamięci)
hmm nie wiem jak to łatwiej wytłumaczyć :P
// ps wiem że trzeba to zrobić na TStream
// ps2 ulepszyłem troche kod:
uses jpeg; [...] var ScreenDC: HDC; Bitmap:TBitmap; FJpeg:TJpegImage; FStream:TStream; begin Bitmap:=TBitmap.Create; FJpeg := TJpegImage.Create; Bitmap.Width:=GetSystemMetrics(SM_CXSCREEN); Bitmap.Height:=GetSystemMetrics(SM_CYSCREEN); ScreenDC:=GetDC(0); BitBlt(Bitmap.Canvas.Handle,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), ScreenDC, 0 , 0, SRCCOPY); ReleaseDC(0, ScreenDC); FStream := TStringStream.Create(''); FJpeg.Assign(Bitmap); Bitmap.Free; FJpeg.CompressionQuality:=20; FJpeg.Compress; //FJpeg.SaveToFile('D:\test.jpg'); Fjpeg.SaveToStream(FStream); FJpeg.Free; end;
teraz zawartość obrazka mam zapisaną w zmiennej FStream,
jednak muszę przekonwertować to do zmiennej typu string...
Użytkownik tsukuyomi_reload edytował ten post 06 maj 2007, 11:43
Hm, ja chyba czegos nie rozumiem ;)
Chcesz przechowywac ten obrazek w pamieci, to przechowuj w go w TJPEGImage, po co string? ;)
niestety jest to potrzebne, gdyż dalej programik ma wysyłać ów obrazek przez internet :)
niestety jest to potrzebne, gdyż dalej programik ma wysyłać ów obrazek przez internet :)
bylo tak od razu :)
najlatwiej zapisac do strumienia i wysylac po fragmencie zawartosc tego strumienia
(stream.Memory)
Jeśli chodzi o obrazek jako tekst to wykombinowałem z helpem coś takiego za pomocą ObjectBinartToText() i ObjectTextToBinary(). Niestety wymaga utworzenia to sobie TImage, gdyż działa tylko dla zapisu komponentu w strumieniu TMemoryStream.
var StringImage: string; //zmienna globalna. Tu bedzie nasza tekstowa reprezentacja obrazu {...} var BMP: TBitmap; //do tego właduj swoj zrzut ekranu img: TImage; StrStream:TStringStream; BinStream: TMemoryStream; s: string; begin {tu sobie wczytasz do BMP swoj zrzut} img := TImage.Create(nil); //bez parenta img.Picture.Bitmap := BMP; BinStream := TMemoryStream.Create; try StrStream := TStringStream.Create(s); try BinStream.WriteComponent(img); BinStream.Seek(0, soFromBeginning); ObjectBinaryToText(BinStream, StrStream); StrStream.Seek(0, soFromBeginning); StringImage := StrStream.DataString; finally StrStream.Free; end; finally BinStream.Free end; img.Free;
Teraz odczyt:
var StrStream:TStringStream; BinStream: TMemoryStream; img: TImage; begin img := TImage.Create(nil); //znowu 'wirtualny obrazek' StrStream := TStringStream.Create(StringImage); try BinStream := TMemoryStream.Create; try ObjectTextToBinary(StrStream, BinStream); BinStream.Seek(0, soFromBeginning); (BinStream.ReadComponent(img) as TImage).Picture.SaveToFile('C:\plik.bmp'); //zapis finally BinStream.Free; end; finally StrStream.Free; end; img.free;
Mam nadzieję, że trybi :) Idealnie byłoby wyciągnąć sobie samo PictureData z zapisu tekstowego, ale nie wiem jak to zrobić.
Użytkownik p1101 edytował ten post 06 maj 2007, 13:29
hmm no w sumie wszystko jest spoko, ale jak zrobić to samo z kompresją do jpg
Tak samo jak robiłeś wcześniej.
JPG.Assign((BinStream.ReadComponent(img) as TImage).Picture.Bitmap); //połączenie do JPG
Użytkownik p1101 edytował ten post 06 maj 2007, 16:09
miałem na myśli najpierw skompresować do jpg a później odczytać stringimage ;)
Pomyśl! Schemat działania jest analogiczny. Próbowałeś chociaż? W procedurze zamiany obrazka na tekst, mając go wczytanego do BMP:
... JPG.Assign(BMP); img.Picture.Graphic := JPG;
Oczywiście że próbowałem... i miałem bodajże access volation, tylko nie pamiętam w którym miejscu
w każdym bądź razie znalazłem bardzo fajny kod do wysyłania obrazków:
http://www.delphi300...le_2313.asp?SK=
dla tych co się tam nie zarejestrowali:
Question/Problem/Abstract: How can I send files using TClientSocket & TServerSocket? Sending files with TClientSocket/TServerSocket Answer: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ScktComp, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Image1: TImage; Image2: TImage; ClientSocket1: TClientSocket; ServerSocket1: TServerSocket; Button1: TButton; procedure Image1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); private { Private declarations } Reciving: boolean; DataSize: integer; Data: TMemoryStream; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Image1Click(Sender: TObject); begin // This is the procedure to open the socket for RECEIVING. // Button1.Click is this procedure as well. ClientSocket1.Active:= true; end; procedure TForm1.FormCreate(Sender: TObject); begin // Open the SENDING socket. ServerSocket1.Active:= true; end; procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket); begin // Send command to start the file sending. Socket.SendText('send'); end; procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket); var s, sl: string; begin s:= Socket.ReceiveText; // If we're not in recieve mode: if not Reciving then begin // Now we need to get the length of the data stream. SetLength(sl, StrLen(PChar(s))+1); // +1 for the null terminator StrLCopy(@sl[1], PChar(s), Length(sl)-1); DataSize:= StrToInt(sl); Data:= TMemoryStream.Create; // Delete the size information from the data. Delete(s, 1, Length(sl)); Reciving:= true; end; // Store the data to the file, until we've received all the data. try Data.Write(s[1], length(s)); if Data.Size = DataSize then begin Data.Position:= 0; Image2.Picture.Bitmap.LoadFromStream(Data); Data.Free; Reciving:= false; Socket.Close; end; except Data.Free; end; end; procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var ms: TMemoryStream; begin // The client wants us to send the file. if Socket.ReceiveText = 'send' then begin ms:= TMemoryStream.Create; try // Get the data to send. Image1.Picture.Bitmap.SaveToStream(ms); ms.Position:= 0; // Add the length of the data, so the client // will know how much data to expect. // Append #0 so it can determine where the size info stops. Socket.SendText(IntToStr(ms.Size) + #0); // Send it (the socket owns the stream from now on). Socket.SendStream(ms); except // So only free the stream if something goes wrong. ms.Free; end; end; end; end.
Dawno napisany programik (w sumie dwa, klient i serwer) do przesyłania na żądanie zrzutów ekranu. Wystarczy mała modyfikacja :)
http://cyrkiel.webpark.pl/scrnnn.zip