Ptal jsem se aji v sekci Delphi, ale vzhledem k tomu, že je to spíš obecně otázka k Pascalu...
V rámci jednoho algoritmu chci otevřít fotku *.jpg jako text, pomocí stringu to překopírovat do dalšího souboru typu text a ten pak uložit opět s příponou *.jpg. Když jsem se o to pokoušel u *.bmp, nebyl v tom problém, ALE, *.jpg používá pro svoje uchování v textové podobě i znaky EOF (end of file, tedy konec souboru, tedy znak s ordinální hodnotou 26) i v prostřed souboru, tudíž, pokud mám cyklus while not(eof(soubor)), skončí mi to někdy i hned na začátku, protože narazí na symbol EOF. Nevíte, jak to nějak obejít?
Fórum › Pascal
Znak EOF před koncem souboru
Co říkáte třeba na to, abych nepoužíval textový soubor, ale file of byte a pracoval s nimi jako s čísly, fungovalo by to pak? Šlo by pak while not(eof(soubor))?
Keď ho chceš iba čo najrýchlejšie prekopírovať, otvor ten jpeg súbor ako netypový, zisti celkovú veľkosť súboru, alokuj dostatočne veľký buffer, blockread-om naraz celý súbor načítaj do bufferu a blockwrite-om ho potom zas z neho ulož do druhého netypového súboru.
Přesně tak - cokoli binárního. Tedy file of něco jednobytového nebo jenom file.
Když si v TP/BP otevřeš nápovědu k heslu Blockread nebo Blockwrite, je tam jako příklad napsané kompletní a funkční kopírování jakéhokoli souboru - stačí zkopírovat.
Moje stránka.
To Mircosoft : Zrovna o kopírování mi nejde. Potřebuju i číst, ale file of byte je příšerně pomalej, takže si budu muset doplnit svoje znalosti o netypových souborech. Přemýšlím totiž o jednoduchém komprimovacím algoritmu.
To Garret Raziel : Platí to čo som spomínal vyššie, ideálne je vopred načítať čo najviac dát do pamäte. Napr. obrázky a súbory do pár desiatok MB môžeš načítať celé jedným blockread-om. Kompresia je zaujímavá oblasť (robím na dvoch video kodekoch) - nejaké podrobnosti, na čo sa chystáš?
Jenom jednoduše, nijak profesionálně, pouze amatérsky. Je to spíš pokus "jestli to půjde". Začalo to tak, že jsem se naučil v Delphi pomocí komponent komunikovat přes internet, ale pouze pro posílání čísel nebo stringů. Pro všechno ostatní tady jsou streamy, ale nechtělo se mi je zatím učit a tak jsem to zkoušel vyřešit tak, že když chci poslat soubor, otevřu ho jako textovej, odešlu zprávu o tom, že odesílám soubor, jaký má název, jakou má příponu a relativní cestu a pak pošlu přes stringy onen soubor. Když jsem zjistil, že to naprosto bezpečně funguje, zkoušel jsem "balit" více souborů do jednoho (15 bytová hlavička, s názvem souboru, příponou a počtem bytů pro blockread (aby skočil na další hlavičku)). A pak jsem se podíval na "text" souboru bmp a zjistil, že obsahuje spoustu znaků "@" a "€" a skoro nic jiného. Napadlo mě tedy, co kdybych' v tom souboru vyhledal všechny dvojce "@€" a "€€" (kterýchžto tam bylo nejvíc), a nahradil je "X" a "Y"? Dosáhl jsem souboru o více jak poloviční velikosti, s tím, že po opětovném nahrazení znaků byl soubor naprosto funkční a bez chyb. Napadlo mě tedy, co toho třeba nevyužít u komprese souborů obecně, najít algoritmus, který výhodně nahradí stejné sekvence znaků jinýmy (menšímy) a na konec souboru akorát připíše "slovník". Zjistil jsem ale, že 1) ten algoritmus bude milionkrát obtížnější, než přijít na to, jak komprimovat, 2) to, že se dá tak jednoduše nahradit, je vlastností snad pouze bmp, zkoušel jsem mp3, exe či jpg a nebyly žádné volné znaky pro nahrazení (všechny znaky byly použité) a stejné tam byli pouze dvojce (jenže pokud nemám samostatný symbol, kterým můžu nahrazovat, musím nahrazovat alespoň dvěma (nepoužitejma) symbolama, a nahradit dvojici dvojicí a pak ještě připsat slovník je lehce kontraproduktvní). Tudíž, asi se to pokusím dokončit ten komprimátor, ale bude hloupoučkej a navíc asi nebude nakonec mít žádný efekt.
Ale zajímalo by mě, co mi k tomu řeknete, co myslíte, má to cenu?
Tá kompresia, čo používaš pre bmp je http://en.wikipedia.org/wiki/Byte_pair_encoding. Bmp s 24 bitovou farebnou hĺbkou (alebo 8-bit bez RLE enkódovania) je nekomprimovaný formát. Podľa toho, čo je na obrázku, sa tam môžu vyskytovať dlhé opakujúce sa reťazce (napr. screenshot browsera, kde je otvorené toto fórum: veľa bielych/sivých/oranžových pixelov za sebou)., preto sa dá ľahko skomprimovať. Tú výmenu za čísla, kt. nie sú v súbore použité, ale nebude možné vykonať pri takých bmp súboroch, kde sú použité pixely s hodnotou v celom rozsahu 0-255.
Ten druhý spôsob enkódovania je slovníková kompresia http://en.wikipedia.org/wiki/Dictionary_coder. Je to asi najzaužívanejší spôsob bezstratovej kompresie: zip, rar a pod. formáty určite poznáš, fungujú práve na princípe vyhľadávania opakujúcich sa reťazcov a ich substitúciou za kratšie reťazce zo "slovníka" (zjednodušene). Takže sa to využiť dá :) Jpeg a mp3 sú komprimované formáty, v súbore je distribúcia symbolov / čísel úplne náhodná (preto tam voľné znaky nenájdeš), ďalej ich nie je možné komprimovať (až na pár extrémnych prípadov). Komprimovať stále dokola sa nedá, v jednom bode určite dostaneš väčší výstup ako vstup. Spustiteľné súbory sú väčšinou tiež dosť náhodné, opakujúce sa znaky sa často vyskytujú v data sekcii a tabuľke symbolov, *ak* nejde o už skomprimovaný exe súbor.
Cenu to má, ak sa pri tom niečo naučíš, kompresia je zaujímavý subjekt imho. Napr. pri kompresii obrázkov sa dá použiť kopa rôznych postupov, ako čo najviac zmenšiť veľkosť.
Asi nejjednodušší na pochopení a implementaci jsou komprese typu RLE. Pro inspiraci:
Komprimovaná sekvence vypadá tak, že nejdřív je tam nějaký příznak, podle kterého zjistíš, jestli za ním následují komprimovaná nebo nekomprimovaná data. Následuje údaj o délce (tj. buď kolikrát se má následující byte zopakovat nebo kolik následuje nekomprimovaných bytů) a nakonec vlastní data a tak pořád dokola. Jako příznak "zkomprimováno/nezkomprimováno" se dá výhodně použít nejvyšší bit té délky, takže se ti obojí vejde do jednoho bytu.
Dekomprese je jednodušší, tou začneme:
Opakuj
- Načti jeden byte zkomprimovaného souboru, řekněme D.
- Nejvyšší bit si izoluj (D shr 7) a ulož do nové proměnné, třeba K, nejlépe boolean.
- V D ten nejvyšší bit vynuluj (D and 127).
- Když je K=1, načti ze souboru jeden byte a na výstup ho zapiš Dkrát.
- Když je K=0, načti ze souboru D bytů a zapiš je na výstup tak, jak jsou.
dokud nejsi na konci vstupního souboru.
Komprese je trošku komplikovanější:
Nastav se na začátek souboru, pozici si ulož řekněme do proměnné P1.
Opakuj:
- P2:=P1, teď pozici P2 posouvej po vstupních datech tak daleko, dokud nenarazíš na bajt jiný než jaký je na pozici P1. Čili P1 bude ukazovat na první byte "jednobarevného" úseku, P2 na poslední.
- Z rozdílu P2 a P1 spočítej délku úseku, řekněme D.
- Jestli D<3, komprese se nevyplatí. Pokračuj v posouvání P2 tak dlouho, dokud nenarazíš na delší "jednobarevný" úsek (P2 zastav na posledním bytu před jeho začátkem). Na výstup zapiš D a za něj úsek dat od P1 po P2 bez jakýchkoli úprav.
- Jestli D>=3 a D<=127, zapiš na výstup hodnotu D or 128 (čili D s nejvyšším bitem nastaveným na 1) a pak jeden byte z pozice P1 (nebo cokolikoli mezi P1 a P2, všechny jsou stejné).
- Jestli D>127, nevejde se ti délka úseku do jednoho bytu, tak ho budeš muset zapsat navíckrát, postup je podobný (zde pro přehlednost nerozepisuju).
- V souboru se přesuň za právě zpracovaný úsek: P1:=P2+1
dokud nejsi na konci vstupního souboru.
Význam toho bitu může být klidně opačný, záleží na tobě.
Obrázky PCX jsou komprimovány tak, že když jsou horní dva bity bytu 1, znamená zbytek čísla počet opakování následujícího pixelu. Když jsou 0, je ten byte přímo hodnota pixelu. Problém je, že když je tam hodně nekomprimovatelných pixelů s hodnotou >63, pak se obrázek místo komprese naopak nafukuje.
GIF, PNG a TIF používají slovníkové algoritmy. Diskrétní cosinová transformace pro JPG byla dobře popsána na PCsvětě (http://www.pcsvet.cz), ale bohužel už se na tu stránku delší dobu nemůžu dostat (BTW, nevíte někdo, co s ní je? :smile11: :smile10: ).
Moje stránka.
Neviem síce čo je s tou stránkou, ale dobrý popis JPEG aj s ilustráciami je aj na anglickej a českej wikipédii. Podrobná séria článkov vyšla aj na root.cz pod názvom "Programujeme jpeg". Mimochodom princípy použité v JPEG sa využívajú aj v kompresii videa v MPEG-like štandartoch - konverzia do yuv farebného priestoru, DCT transformácia, kvantizácia, RLE a Huffmanovo enkódovanie (alebo skôr VLC).
PNG ešte pred kompresiou aplikuje filter (prediktor) - hodnota aktuálneho pixelu je odvodená od predchádzajúcich, ukladá sa len chyba (rozdiel medzi odvodenou a skutočnou hodnotou), ktorá je často veľmi malá, príp. žiadna.
Tak, nestvořil jsem vlastní komprimovací metodu, ale spoustu jsem se o tom dozvěděl, danke schön!
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Znak EOF před koncem souboru — založil Garret Raziel
Čtení z textového souboru po řádcích a EOF — založil Petr
Průchod textového souboru znak po znaku — založil SOULATORii
Getchar() a EOF — založil dreamer
C getchar EOF — založil Poki
Moderátoři diskuze