Własny zapis pliku graficznego
Wiem że to jest nie potrzebne bo od czego są Bitmapy, Gify, Jpegi ale głównie dlatego to piszę ponieważ nie mam pomysłów na inne arty, a chce pokazać jak to można zrobić; zresztą to jest biblioteka DLL w moim systemie OS. Ten art jest raczej dla początkujących niż choćby dla średnio-zaawansowanych. Użyję Double-Bufferingu, (Jeśli nie wiesz, co to jest to na końcu wyjaśnię) żeby było szybciej ładować obrazki z pliku.
W kodzie użyje techniki "Block" (jeśli wiesz co to jest, to nie czytaj) czyli
BlockRead i BlockWrite
Składnia:
BlockWrite(var F:file; const Buf; Count:integer);
BlockRead(var F:file; var Buf; Count:integer);
Gdzie:
F = Plik
Buf = Dowolna zmienna (nawet Array)
count = ilość zapisywanych znaków w pliku (więcej niż 1 tylko jeżeli buf to array albo string)
Bardzo się nam to przyda przy zapisywaniu R,G,B czyli 3 Byte'ów.
Jeszcze jedno CMP to jest skrót od Color MaP
Na początku trzeba zadeklarować zmienną globalną (Double-Buffering)
var
db:Tbitmap;
Kliknij na Formę, Na zakładkę, onCreate I wpisz:
Db:=Tbitmap.Create;
Teraz zrobimy procedurkę do zapisu:
Procedure SaveCMP(S:string);
var
X,Y:Integer;
F:File;
RGB:array [1..3] of byte;
W,H:string;
// zaczynamy
begin
//Wiążemy plik ze zmienną
Assignfile(F,S);
Rewrite(F,1);
//Zapisujemy wysokość i szerokość
W:=inttostr(db.width);
H:=inttostr(db.height);
blockwrite(F,W,5);
blockwrite(F,H,5);
// cała funkcja liczenia
For Y:=0 to db.height do
For X:=0 to db.width do
begin
RGB[1]:=getRvalue(db.canvas.pixels[x,y]);
RGB[2]:=getGvalue(db.canvas.pixels[x,y]);
RGB[3]:=getBvalue(db.canvas.pixels[x,y]);
blockwrite(F,RGB,3);
application.processmessages; //żeby było szybciej
end;
// Mniej więcej na podobnej
// zasadzie opiera się BMP, ale dokładnie nie wiem
end;
Oczywiście to wcale nie pójdzie :( . Tylko żartowałem :)
ale przed użyciem tej procedury obrazek typu TImage musi się znaleźć
w zmiennej db.
Proponuje kodzik (zakładając, że twój TImage nazywa się "Image"):
db.width:=image.picture.width;
db.height:=image.picture.height;
db.canvas.CopyRect(rect(0,0,image.picture.width,image.picture.height),image.canvas,rect(0,0,image.picture.width,image.picture.height));
Teraz procedura odczytująca:
Procedure LoadCMP(S:string);
var
X,Y,I:Integer;
F:File;
col:array [1..3] of byte;
num:array [1..5] of byte;
str:string;
// zaczynamy
begin
//Wiążemy plik ze zmienną
Assignfile(F,S);
Reset(F,1);
//Odczytujemy wysokość i szerokość
blockread(F,num,5);
//Zabezpieczenie 1
for I:=1 to 5 do
if (num[I]<>ord('0')) and
(num[I]<>ord('1')) and
(num[I]<>ord('2')) and
(num[I]<>ord('3')) and
(num[I]<>ord('4')) and
(num[I]<>ord('5')) and
(num[I]<>ord('6')) and
(num[I]<>ord('7')) and
(num[I]<>ord('8')) and
(num[I]<>ord('9')) then application.ProcessMessages else
str:=str+chr(num[i]);
db.width:=strtoint(str);
blockread(F,num,5);
//Zabezpieczenie 2
str:='';
for I:=1 to 5 do
if (num[I]<>ord('0')) and
(num[I]<>ord('1')) and
(num[I]<>ord('2')) and
(num[I]<>ord('3')) and
(num[I]<>ord('4')) and
(num[I]<>ord('5')) and
(num[I]<>ord('6')) and
(num[I]<>ord('7')) and
(num[I]<>ord('8')) and
(num[I]<>ord('9')) then application.ProcessMessages else
str:=str+chr(num[i]);
db.height:=strtoint(str);
str:='';
// cała funkcja liczenia
For Y:=0 to db.height do
For X:=0 to db.width do
begin
blockread(F,col,3);
db.canvas.pixels[x,y]:=rgb(col[1],col[2],col[3]);
application.processmessages; //żeby było szybciej
end;
end;
To także od razu nie pójdzie, ale po procedurze napisz:
image.width:=db.width;
image.height:=db.height;
image.canvas.CopyRect(rect(0,0,db.width,db.height),db.canvas,rect(0,0,db.width,db.height));
Więc teraz wytłumaczę Double-Buffering.
To jest nic innego jak tylko odczyt obrazka z pliku
i zapisywanie go w pamięci a jak już się cały załaduje to
Dopiero kopiujemy go z pamięci do TImage.
Jeśli i tak nie rozumiesz to gdzieś w dziale Delphi jest o tym
Artykuł.
Dzięki temu kodowi można zapisać obrazek MAX 99999 x 99999 (wysokość x szerokość) i można uzyskać 256 x 256 x 256 (Red x Green x Blue [Czerwony x Zielony x Niebieski]) kolorów na pixel; Czyli 16777216 kolorów na pixel.
Och aż (ok.) 190 linii.
Bye Bye Psychoszayber.
to już lepiej tak Pomijając że to bez celowe i nie potrzebne :):
Format Nieco inny :)
3 Byte'owy - Nagłówek
4 Byte'owy- Szerokość
4 Byte'owy -Wysokość
Kolejno barwy Pixeli w kolejności BGR
A Lepiej Bo:
1.ScanLine jest szybszy
2.Plik Posiada Nagłówek (identyfikacja)
3.Mamy do dyspozycji cały Integer a nie jakieś słowne '9999'
Czemu daliście mu jednyki? Ten art zasługuje na wyższą ocene, chociaż 4. A co do sposobu CyberKida - koleś, przeca to przepuści na elese wszystko oprócz 1 i 9. Tak jest lepiej
a czy nie lepiej zamiast tego
if (num[I]<>ord('0')) and
(num[I]<>ord('1')) and
(num[I]<>ord('2')) and
(num[I]<>ord('3')) and
(num[I]<>ord('4')) and
(num[I]<>ord('5')) and
(num[I]<>ord('6')) and
(num[I]<>ord('7')) and
(num[I]<>ord('8')) and
(num[I]<>ord('9')) then application.ProcessMessages else
zrobić
if (num[I]<ord('0')) and
(num[I]>ord('9')) then application.ProcessMessages else
?????????
/cyt/ application.processmessages; // żeby było szybciej /cyt/
wierz mi, nie będzie szybciej.. dlaczego ? pomyśl..
Możę ale nie wiem czy będę miał czas.
Ps. Mam już algorytm na GIF
a i AVI ale wątpie czy dałbym radę w Wav
ie albo mp3.Fajnie, ale może napiszesz jeszcze, jak stworzyć swojego GIF'a, Flash'a, AVI, WAV'a, MP3 itp. itd??? ;)