Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post a reply


In an effort to prevent automatic submissions, we require that you complete the following challenge.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :| :mrgreen: :geek: :ugeek: :arrow: :angel: :clap: :crazy: :eh: :lolno: :problem: :shh: :shifty: :sick: :silent: :think: :thumbup: :thumbdown: :salute: :wave: :wtf: :yawn: :facepalm: :bravo: :dance: :beard: :morebeard: :xmas: :HeHe: :trollface: :cookie: :rainbow: :monkeysee: :monkeysay: :happybday: :headwall: :offtopic: :superhappy: :terms: :beer:
View more smilies

BBCode is ON
[img] is OFF
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 18 Nov 2020, 12:55

Danke für den Tip. Durch Vergleich mit diesen Daten könnte ich die Strukturen vielleicht schneller verstehen. Die Lizenzproblematik umgehe ich derzeit mit Imagemagick. Das Tool kann auch Bilder aus pdf Dateien extrahieren.

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Ahk_fan » 18 Nov 2020, 09:03

Hallo
es gibt zu den o.g. XPDF-Tools einen fork:http://blog.alivate.com.au/poppler-windows/
da gibt es auch das Tool pdfimages.exe mit der Option -list, das listet alle relevanten Infos zu den eingebetteten Bildern auf, evtl ist das ein guter Ansatz um an die Bilddaten dranzukommen...
Zwischenablage-1.jpg
Zwischenablage-1.jpg (30.62 KiB) Viewed 965 times

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 07 Nov 2020, 10:44

Hier noch ein kleiner Nachschlag.
Eine Funktion für's PDF Format isCorruptPDF() und eine Funktion um zu prüfen, ob der Schreib-/Lesezugriff gesperrt ist.

Ich habe beim Einsatz von Tesseract immer wieder defekte PDF Dateien erhalten. Tesseract meldet, jedenfalls bei mir, eine während des Schreibvorgangs fehlerhaft erstellte Datei nicht.
Die Dateigrößen sind auch nicht genau null. Scheinbar hat Tesseract manchmal Probleme, wenn er den Text ins Dokument einbetten will. An diesen Stellen enden die PDF Datein dann.
Da die letzten Zeichen einer PDF Datei, den ASCII-Code EOL gefolgt von keinen weiteren Zeichen oder von \n oder \r\n als Vorgabe haben,
läßt sich auf einfache Weise zumindestens die Vollständigkeit der Dateierstellung ermitteln.

Die zweite Funktion ist hilfreich, wenn man überhaupt prüfen will ob man manipulativ zugreifen kann.

Code: Select all


isCorruptPDF(pdfFilePath)                     	{                            	;-- prüft ob eine PDF Datei defekt ist

	If !(fileobject := FileOpen(pdfFilePath, "r", "CP1252"))
		return 0

	fileobject.seek(fileobject.Length - 6, 1)
	fileobject.RawRead(EndOfFile, 5)

return InStr(StrGet(&EndOfFile, 5, "CP0"), "EOF") ? false : true
}

Code: Select all

FileIsLocked(FullFilePath)                     	{                             	;-- ist die Datei gesperrt?

	f := FileOpen(FullFilePath, "rw")
	LE	:= A_LastError
	iO 	:= IsObject(f)
	If iO
		f.Close()

return LE = 32 ? true : false
}

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 06 Nov 2020, 14:33

Tesseract 4x erstellt eine PDF der Version 1.5. Den folgenden Text (Codebox) habe ich aus einer von tesseract erstellten PDF Datei.

Wie Du siehst wird der erkannte Text als stream-Objekt (10 0 obj) in der PDF gespeichert. Mit zlib_Decompress() (siehe Skript am Anfang) kann man den stream entpacken.
9 0 obj enthält verschiedene Daten für die Handhabung von 10 0 obj.
11 0 obj ist das Bild, welches gescannt wurde. In meinem Beispiel hatte die Fritzbox ein Fax als PDF gespeichert. Das Bild wäre per <CCITTFaxDecode> zu dekodieren.

Code: Select all

9 0 obj
<<
  /Type /Page
  /Parent 2 0 R
  /MediaBox [0 0 2068.08 2943.36]
  /Contents 10 0 R
  /Resources
  <<
    /XObject << /Im1 11 0 R >>
    /ProcSet [ /PDF /Text /ImageB /ImageI /ImageC ]
    /Font << /f-0-0 3 0 R >>
  >>
>>
endobj

10 0 obj
<<
  /Length 8086 /Filter /FlateDecode
>>
stream 
....
endstream
endobj

11 0 obj
<<
  /Length 225440
  /Subtype /Image
  /ColorSpace /DeviceGray
  /Width 8617
  /Height 12264
  /BitsPerComponent 1
  /Filter /CCITTFaxDecode
  /DecodeParms
  <<
    /Predictor 1
    /Colors 1
    /K -1
    /Columns 8617
    /BitsPerComponent 1
  >>
>>
stream
.....
endstream
endobj
Die Antwort ist: Tesseract legt Textdaten mit Positionsangaben wie gewohnt ab. Text läßt sich mit der Maus/Tastatur in jedem PDF Anzeigeprogramm auswählen.

Hat man das text-stream-Objekt entpackt (habe es für mein Beispiel-PDF nicht gemacht) erhält man "Postscript-stream-Befehle".
(Das Beispiel ist von dieser Seite)

Code: Select all

BT (begin a block of text)

/F13 12 Tf                          (Choose Font F13 and set size to 12)

288 720 Td                          (move the location relative from where it now is

(ABC) Tj                            (Draw the Text ABC)

ET                                  (End the text block)
Das Extrahieren von image-streams gestaltet sich schwieriger und darum ging es bei meiner letzten Frage an die Foristen.
Ich konnte jpg Dateien extrahieren, wenn man in einem HEX-Editor am Anfang des streams "JFIF" lesen kann. Ich gehe davon aus, das bei diesen jpg-Bildern die Imageheader im stream gespeichert wurden.

Ob es ein "leider" wert ist oder nicht, kann ich noch nicht sagen, aber leider gibt es diverse Möglichkeiten Bilddaten in einer PDF zu speichern.
Soweit ich es verstanden habe, erreicht man mehr Flexibilität für den PDF-Renderer, wenn Farbtabelle, Filter und anderes in einzelne Objekte gespeichert werden kann.
Wir müssen also zunächst alle Objekte zusammentragen, diverse Sachen generieren (was da alles zugehört, weiß ich noch nicht). Das muss dann wohl zu einem Datei(Image)header zusammengesetzt werden,
an welchen man die Pixeldaten anhängt damit es ein korrektes Dateiformat ergibt.

In der PDF kann man das alles auf die Spitze treiben, indem man Daten in verschachtelte stream-Objekte (gepackte Daten innerhalb gepackter Daten) zusammenlegt. Das läßt sich wohl mit beliebiger Tiefe durchführen.
Das gleiche gilt auch text-streams.
Was ich hier geschrieben habe gilt für die PDF-Spezifikationen V1.3 und V1.5. Andere Spezifikationen habe ich mir noch nicht angeschaut.

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by SOTE » 06 Nov 2020, 04:51

Frosti wrote:
21 Oct 2020, 17:54
Bisher habe ich die Xpdf command line tools benutzt.
Vielleicht wäre ein Blick auf den xpdf-Quellcode hilfreich. Es könnte mehr Hinweise geben.
Bitte entschuldigen Sie mein schlechtes Deutsch.

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Ahk_fan » 04 Nov 2020, 16:00

:bravo: Das klingt echt cool!!!!
Weißt du ob tesseract den Textlayer passend zu den koordinaten über das Bild legt wenn die PDF erzeugt wird? Oder ist es nur ein einfacher Textpart, der angehängt wird?

Ich habe ein Programm für mich privat gemacht, das einen Ordner auf neue Scan-PDFs überwacht und auf Emails mit PDF-Anhang
1) sobald einen neue PDF da ist, wird analysiert
a) gescannte --> JPG mit pdfimages.exe extrahieren
a1) mit API UWP https://www.autohotkey.com/boards/viewtopic.php?f=6&t=72674 OCR erzeugen (sehr schnell, eher ungenau), tesseract war mir zu langsam
a2) Suchen im OCR-Text nach einem Kundennamen aus vorhandener Liste
a3) entsprechend aus einer INI gelernte Daten (noch sehr rudimentär, und kompliziert) in OCR-Text suchen und bereinigen(Bei Rechnung z.B. Betrag, Rechnungsnummer, IBAN, BIC)
a4) PDF mit extra TXT.Datei mit OCR Text in einem Kundenverzeichnis ablegen und eine AHK-Scriptdatei erzeugen, die bei Start die ermittelten
Daten (IBAN, Verwendung, Betrag, Kunde) an die Banking -Seite übergibt.
a) Daten werden in einer SQLite DB abgelegt
b) Eine positscript-erzeugete PDF mit Text inhalt --> mit pdftotext.exe extrahieren
b1) wie a2)
b2) wie a3) usw
Ist alles nicht professionell, aber es tut was es soll...

Jetzt wollte ich ja deine Funktion von ganz oben mit dem extrahieren integrieren, aber meine Versuche waren bis jetzt erfolglos. Ich bekomme die JPGs einfach nicht raus. Muss noch etwas testen...
Auf jeden Fall kann ich die Seitenzählfunktion gut gebrauchen, ich habe es bis jetzt etwas umständlicher gemacht
--> von @haichen https://www.autohotkey.com/boards/viewtopic.php?f=6&t=78691&p=342288 auf Basis von https://www.autohotkey.com/boards/viewtopic.php?f=9&t=78602

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 04 Nov 2020, 14:49

Okay das Extrahieren von Bildern aus einem stream verwirrt mich noch.

Ich biete Euch aber erstmal zwei Funktionen, die wesentlich schneller sind als der Einsatz von commandline Tools. Allerdings für andere Zwecke.
Der Trick ist das ich die in einer PDF-Datei enthaltenen stream-Objekte überspringen lasse. Getestet und im täglichen Einsatz sind sie mit PDF Dateien der Version 1.3 oder 1.5

isSearchablePDF() - nutze ich seiner Negation um PDF Dateien zu filtern, die noch keine Texterkennung erhalten haben.
Die gefilterten Dateien werden dann Tesseract zugeführt. Dafür muss ich zunächst die enthaltenen Bilder extrahieren (pdftopng.exe).
Dafür benötige ich die Seitenzahl, die ich über GetPDFPages() erhalte.
Ich habe mir eine tesseract OCR Funktion geschrieben die sämtliche Vorgänge von Erstellung eines Backup der Original-PDF über Extraktion der Bilder,
preprocessing durch leptonica, Erstellung eines inFiles (enthält eine Liste der von leptonica vorbereiteten Bilder) und Übergabe mit allen Parametern an tesseract in einem Zuge durchführt.
Tesseract ab Version 4 setzt dann OCR-Text und Bilder wieder zu einer PDF zusammen. Durch Überwachung des PDF Ordners läuft alles automatisch ab. Die Texterkennung während oder nach dem
manuellen Scanvorgang abzuwarten entfällt seitdem. Das spart Zeit und Zeit ist Leben!

Code: Select all

isSearchablePDF(pdfFilePath) {                                              	;-- durchsuchbare PDF Datei?

	If !(fileobject := FileOpen(pdfFilePath, "r", "CP1252"))
		return 0

	while !fileobject.AtEof {
		line := fileobject.ReadLine()
		If RegExMatch(line, "i)\/PDF\s*\/Text") {
			filepos := fileObject.pos
			fileObject.Close()
			return filepos
		}
		else If RegExMatch(line, "Length\s(?<seek>\d+)", file) {    	; binären Inhalt überspringen
			fileobject.seek(fileseek, 1)                                           	; •1 (SEEK_CUR): Current position of the file pointer.
		}
	}

	fileObject.Close()

return 0
}

Code: Select all


GetPDFPages(pdfFilePath) {                                               	;-- gibt die Anzahl der Seiten einer PDF zurück

	If !(fileobject := FileOpen(pdfFilePath, "r", "CP1252"))
		return 0

	while !fileobject.AtEof {
		line := fileobject.ReadLine()
		If RegExMatch(line, "i)\/Count\s+(\d+)", pages) {
			fileObject.Close()
			return pages1
		}
		else If RegExMatch(line, "Length\s(?<seek>\d+)", file) {    	; binären Inhalt überspringen
			fileobject.seek(fileseek, 1)                                           	; •1 (SEEK_CUR): Current position of the file pointer.
		}
	}

	fileObject.Close()

return 0
}

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 27 Oct 2020, 03:38

Update:
Ich habe die Extraktion von komprimierten PNG streams versucht. In meinen PDF Dateien habe ich nur per FlateDecode Algorithmus zu dekomprimierende PNG streams gefunden. Ein einfaches Anwenden von Flatedecode auf diesen Inhalt erzeugt aber noch kein anzeigbares Format.
Wenn ich es richtig verstehe, muss ich einen PNG Header erzeugen. Die notwendigen Informationen sind in anderen PDF-Objekten hinterlegt.
Die Bitzahl und Farbkodierung (8bit grey oder 8bit RGB) steht direkt vor dem PNG stream. Dann gibt es mitunter noch Angaben zur Komprimierungstiefe.
Bei RGB-PNG brauche ich die zugehörige Farbtabelle die in einem der anderen stream-Objekte komprimiert abgelegt wurde.
FlateDecode, DCTDecode werden als Filter bezeichnet und können verschachtelt sein. Mitunter werden weitere Verschachtelungen erst nach dem Dekomprimieren sichtbar, weil diese innerhalb eines komprimierten streams enthalten sind.
Ich verstehe jetzt den Aufwand den ich betreiben muss um weiter zu kommen.
Meine Frage: Sind PNG Daten als Bitmap-Streams zu behandeln? Was unterscheidet Binärdaten und data-streams?

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 23 Oct 2020, 17:13

Danke das ist schon mal sehr aufschlussreich. Die PDF Spezifikationen sind für mich zu umfangreich um diese Problematik entdecken zu können.
Da ich Dokumente entweder von der FritzBox erhalte oder über einen Fujitsu ScanSnap Scanner und Abby FineReader erstellt werden, habe ich mir eine schöne Speziallösung erstellt.
Also scheinbar recht zwecklos im allgemeinem Einsatz. Ich werde noch ein paar Forschungen dazu betreiben, weil es mir gerade Freude bereitet und das Ganze wohl einstellen wenn es dies nicht mehr tut.

Das sich ein JPEG Bild nicht extrahieren läßt erstaunt mich. Möglichweise ist das Bild zusätzlich komprimiert worden, was meines Erachtens wenig Sinn macht. Das Skript bekommt es bei mir ja hin.
TIFF extrahieren kann das Skript nicht. Das Skript sollte per OCR hinzugefügten Text allerdings extrahieren können.

Ich werde zunächst mal TIFF und "Word"-Text Extraktion hinzufügen und die Beschreibung des Skriptes ausführlicher gestalten.

Re: Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Ahk_fan » 23 Oct 2020, 05:42

Hi,
Danke für das Script.
ich bin auch schon lange (ca 8 Jahre) mit PDFs beschäftigt, bisher habe ich noch nichts gefunden dass alles richtig extrahiert, bis auf die genannten Xpdf Tools.
pdftk (PdfToolKit, nur die pdftk.exe) kann recht viel, z.B. die PDFs dekompirimieren usw. aber den Text extrahieren ist schwierig.
Meine Erkenntniss: Lass es :-D! jeder doofe PDF Drucker verwendet andere Kodierungstabellen, z.b. wird beim erzeugen einer PDF durch PostScript errechnet, welche Zeichen nicht vorkommen und dann wird eine Kodierungtabelle angelegt, die die Zeichen anhand der Häufigkeit definiert. Das ist cool und besch.. gleichzeitig. Das sieht man schon an den Ergebnissen bei gleichen Daten:
- Word 3 Zeilen Text --> gespeichert --> 36 kb
- Word 3 Zeilen Text --> Microsoft PDF Printer --> 290 kb
- Word 3 Zeilen Text --> PDF Creator --> 4 kb
- Word 3 Zeilen Text --> XChange PDF Printer --> 174 kb

ausserdem werden Bilder mal in zip, mal in zip2 usw. gepackt.

Ich habe dein Programm mal getestet:
1) Word --> Text geschrieben --> als PDF gespreichert PDF/A v1.7 !!!! --> Text-Daten werden nicht extrahiert
2) Word --> Text geschrieben --> als PDF gedruckt 1.3 mit MS PDF Printer --> Text-Daten werden nicht extrahiert
2) Word --> Text geschrieben --> als PDF gedruckt 1.3 mit PDF Creator Printer --> Text-Daten werden nicht extrahiert
2) gescannte PDF (1.3) --> JPEG Bild --> keine Daten extrahiert
3) gescannte PDF (1.3) --> TIFF Bild --> keine Daten extrahiert

Literatur: PDFReference16.pdf bei ADOBE
LInk Projektarbeits: https://www.google.de/url?sa=t&rct=j&q= ... Kk760gcPSV
PDF und PS Bibel: http://docplayer.org/46281655-Die-postscript-pdf-bibel.html

Versuch einer nahezu nativen Autohotkey PDF2Text und PDF2JPG Lösung

Post by Frosti » 21 Oct 2020, 17:54

Liebe Foristen,

vorgestern hatte ich plötzlich eine Idee für eine technische Umsetzung eines eigentlich nicht vorhandenen Problems.
Ich bin kein allzu großer Fan der Ausführung von command-line-tools in meinen Autohotkey-Skripten.
Es dauert mir einfach zu lange bis alle Operationen durchgeführt sind, da die Tools bei jedem Durchlauf von der Festplatten ins RAM geladen werden um ausgeführt werden zu können.
Die Daten die ich erhalten möchte, lassen sich auch leider nie direkt in der Konsole ausgeben, so daß zig Schreibzugriffe erfolgen.
Bisher habe ich die Xpdf command line tools benutzt. Sind tolle kleine Tools.
Was mich trotz Open Source und der GPL Lizenz stört ist das vorhandene Copyright der Firma Glyph & Cog.
Es gibt noch andere "freie" PDF-Bibliotheken, aber soweit mir bekannt, gibt es keine wirklich freie Software für Windows ohne den genannten Background.

Langer Vorspann, unbedingt nicht kürzer gehaltene Anfrage!
Könntet Ihr den Skript-Code mit verschiedenen PDF-Versionen testen. Ich habe ausschließlich PDF 1.3 oder 1.4 auf meinen Festplatten. Kein PDF/A oder irgendwas anderes.
Das Skript kann noch nicht viel, da ich derzeit nur an den OCR-Text, Metadaten und enthalten Bilddateien kommen wollte.
Allerdings bin ich verdammt erstaunt, das ich das in verhältnismäßig kurzer Zeit hinbekommen habe, zumal alle Daten in einem "Rutsch" extrahiert werden und ich keine 3 einzelnen Programme dafür einsetzen muss.
Der Inhalt einer 1-seitigen PDF Datei wird bei mir im Durchschnitt in 0.35s auf Festplatte ausgegeben (die Festplattenausgabe ist nur für Testzwecke hier im Forum geschrieben).
Ich würde gern wissen ob das tatsächlich so problemlos auch mit allen möglichen PDF Dateien funktioniert.
Ein paar Ungereimtheiten gibt es bei mir bezüglich der genutzten Datenlängen. Es funktioniert bei mir und allzu viel Zeit für detailliertes Nachforschen habe ich seit Monaten nicht mehr.

Ich freue mich auf Eure Hinweise.

Code: Select all


; nearly native Autohotkey PDF2Text and PDF2jpg solution (very useless version!)
; not so quick but very dirty version
; version date: 21.10.2020
;
; you need a copy of zlib1.dll (gz compression and decompression library) for deflating some PDF stream contents
; download link: http://www.winimage.com/zLibDll/zlib123.zip
;
; Autohotkey zlib1 wrapper functions are developed by shajul
; link: https://autohotkey.com/board/topic/63343-zlib/
;
; tested with Autohotkey V1.1.33.2 64bit Unicode on Windows 10
; works with some PDF Version 1.3 & 1.5 files

#NoEnv
SetBatchLines, -1

inflates  	:= Object()
picnr     	:= 1
pdfPath 	:= A_ScriptDir "\test1.pdf"
savePath	:= A_ScriptDir
SplitPath, pdfPath, pdfname

If !(pdfFile	:= FileOpen(pdfPath, "r", "CP1252")) {
	MsgBox, % "can't open PDF File:`n" pdfPath
	ExitApp
}

savefile  	:= FileOpen(savePath "\"  "-decoded.txt", "w", "UTF-8")

while !pdfFile.AtEof {

	If (StrLen(line := StrReplace(pdfFile.ReadLine(), "`r`n")) = 0)
		continue

	If RegExMatch(line, "\>stream$") {

		RegExMatch(line, "Length\s(?<seek>\d+)", file)
		maxbytes := pdfFile.RawRead(tmpvar, fileseek)
		out := ""

		If      	RegExMatch(line, "\/Image")   	{

			If RegExMatch(line, "\/DCTDecode") {
				out := "jpeg image (Filter: DCTDecode) , filename: pic" picnr ".jpg"
				picfile := FileOpen(A_ScriptDir "\pic" picnr ".jpg", "w")
				picfile.RawWrite(tmpvar, fileseek)
				picfile.Close()
			}

		}
		else if 	RegExMatch(line, "\/Metadata")	{

			out := StrGet(&tmpvar, fileseek, "CP1252")

		}
		else                                                   	{

			osize     	:= zlib_Decompress(deflate, tmpvar, maxbytes*4)
			deflate     	:= StrGet(&deflate, maxbytes*4, "CP1252")

			If RegExMatch(deflate, "\(.*\)") {

				rxpos := 1
				out := "<<hocr_data>>`n" deflate "`n`n<<plain_text>>`n"
				while, (fpos := RegExMatch(deflate, "\((?<word>[^\)]+)\)", m, rxpos)) {
					out 	 .= mword (RegExMatch(mword, "\.\s*$") ? "`n" : " ")
					rxpos := fpos + StrLen(mword)
				}
				out := RTrim(out, "`n<<plain_text>>`n")
				out := RegExReplace(out, "`n`n", "`n")

			}
			else {

				out := deflate

			}

		}

		savefile.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------")
		savefile.WriteLine(RegExReplace(line, "(\>)stream$", "$1"))
		savefile.WriteLine("file pointer: " SubStr("00000" pdfFile.pos, -4))
		savefile.WriteLine("<< datastream bytes -pdf data: " fileseek " / -fileread: "maxbytes ">> | StrLen -deflated string: " StrLen(deflate) ", tmpvar: " StrLen(tmpvar))
		savefile.WriteLine("<<original size: " osize " , datastream bytes -pdf data: " fileseek " / -fileread: "maxbytes ">> | StrLen -deflated string: " StrLen(deflate) ", tmpvar: " StrLen(tmpvar))
		savefile.WriteLine("-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------")
		savefile.WriteLine(out "`n")

	}

}

pdfFile.Close()
saveFile.Close()


ExitApp

/*
Return codes for the compression/decompression functions. Negative values are errors, positive values are used for special but normal events.
#define Z_OK            0
#define Z_STREAM_END    1
#define Z_NEED_DICT     2
#define Z_ERRNO        (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR   (-3)
#define Z_MEM_ERROR    (-4)
#define Z_BUF_ERROR    (-5)
#define Z_VERSION_ERROR (-6)

Compression levels.
#define Z_NO_COMPRESSION         0
#define Z_BEST_SPEED             1
#define Z_BEST_COMPRESSION       9
#define Z_DEFAULT_COMPRESSION  (-1)
*/

zlib_Compress(Byref Compressed, Byref Data, DataLen, level = -1) {

	; http://www.autohotkey.com/forum/viewtopic.php?t=68170

	nSize := DllCall("zlib1\compressBound", "UInt", DataLen, "Cdecl")
	VarSetCapacity(Compressed,nSize)
	ErrorLevel := DllCall("zlib1\compress2", "ptr", &Compressed, "UIntP", nSize, "ptr", &Data, "UInt", DataLen, "Int"
				   , level    ;level 0 (no compression), 1 (best speed) - 9 (best compression)
				   , "Cdecl") ;0 means Z_OK

return ErrorLevel ? 0 : nSize
}

zlib_Decompress(Byref Decompressed, Byref CompressedData, DataLen, OriginalSize = -1) {

	; http://www.autohotkey.com/forum/viewtopic.php?t=68170

	OriginalSize := (OriginalSize > 0) ? OriginalSize : DataLen*10 ;should be large enough for most cases
	VarSetCapacity(Decompressed,OriginalSize)
	ErrorLevel := DllCall("zlib1\uncompress", "Ptr", &Decompressed, "UIntP", OriginalSize, "Ptr", &CompressedData, "UInt", DataLen)

return ErrorLevel ? 0 : OriginalSize
}

gz_compress(infilename, outfilename) {

	; http://www.autohotkey.com/forum/viewtopic.php?t=68170

	VarSetCapacity(sOutFileName, 260)
	DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", outfilename, "int", -1, "str", sOutFileName, "int", 260, "Uint", 0, "Uint", 0)
	infile := FileOpen(infilename, "r")
	outfile := DllCall("zlib1\gzopen", "Str" , sOutFileName , "Str", "wb", "Cdecl")
	if (!infile || !outfile)
	   return 0
	nBufferLen := 8192 ; can be increased if gzbuffer function is called beforehand
	VarSetCapacity(inbuffer,nBufferLen)
	while ((num_read := infile.RawRead(inbuffer, nBufferLen)) > 0)
	   DllCall("zlib1\gzwrite", "UPtr", outfile, "UPtr", &inbuffer, "UInt", num_read, "Cdecl")
	infile.Close()
	DllCall("zlib1\gzclose", "UPtr", outfile, "Cdecl")

return 1
}

gz_decompress(infilename, outfilename) {

	;http://www.autohotkey.com/forum/viewtopic.php?t=68170

	VarSetCapacity(sInFileName, 260)
	DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "str", infilename, "int", -1, "str", sInFileName, "int", 260, "Uint", 0, "Uint", 0)
	infile := DllCall("zlib1\gzopen", "Str" , sInFileName , "Str", "rb", "Cdecl")
	outfile := FileOpen(outfilename, "w")
	if (!infile || !outfile)
	   return 0
	VarSetCapacity(buffer,8192) ;can be increased after calling gzbuffer beforehand
	num_read = 0
	while ((num_read := DllCall("zlib1\gzread", "UPtr", infile, "UPtr", &buffer, "UInt", 8192, "Cdecl")) > 0)
	   outfile.RawWrite(buffer, num_read)
	DllCall("zlib1\gzclose", "UPtr", infile, "Cdecl")
	infile.Close()

return 1
}


Top