2012-04-05 15 views
1

Ich möchte Bilder aus einer PDF extrahieren. Ich benutze iTextSharp jetzt. Einige Bilder können korrekt extrahiert werden, aber die meisten von ihnen haben nicht die richtigen Farben und sind verzerrt. Ich habe einige Experimente mit verschiedenen PixelFormats, aber ich habe keine Lösung für mein Problem ...Extract FlateDecode Bilder mit iTextSharp

Dies ist der Code erhalten, welche die Bildtypen trennt:

if (filter == "/FlateDecode") 
{ 
    // ... 
    int w = int.Parse(width); 
    int h = int.Parse(height); 
    int bpp = tg.GetAsNumber(PdfName.BITSPERCOMPONENT).IntValue; 

    byte[] rawBytes = PdfReader.GetStreamBytesRaw((PRStream)tg); 
    byte[] decodedBytes = PdfReader.FlateDecode(rawBytes); 
    byte[] streamBytes = PdfReader.DecodePredictor(decodedBytes, tg.GetAsDict(PdfName.DECODEPARMS)); 

    PixelFormat[] pixFormats = new PixelFormat[23] { 
     PixelFormat.Format24bppRgb, 
     // ... all Pixel Formats 
    }; 
    for (int i = 0; i < pixFormats.Length; i++) 
    { 
     Program.ToPixelFormat(w, h, pixFormats[i], streamBytes, bpp, images)); 
    } 
} 

Dies ist der Code Speichern Sie das Bild in einem MemoryStream. Das Speichern des Bildes in einem Ordner wird später implementiert.

private static void ToPixelFormat(int width, int height, PixelFormat pixelformat, byte[] bytes, int bpp, IList<Image> images) 
{ 
    Bitmap bmp = new Bitmap(width, height, pixelformat); 
    BitmapData bmd = bmp.LockBits(new Rectangle(0, 0, width, height), 
     ImageLockMode.WriteOnly, pixelformat); 
    Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length); 
    bmp.UnlockBits(bmd); 
    using (var ms = new MemoryStream()) 
    { 
     bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff); 
     bytes = ms.GetBuffer(); 
    } 
    images.Add(bmp); 
} 

Bitte helfen Sie mir.

+0

Überprüfen Sie diese Antwort mit einigen neuen Funktionen in 5.1.3 und höher: http://Stackoverflow.com/a/8511314/231316 –

+0

Es ist richtig, dass die Lösung funktioniert (das erste der Beispiele). Aber die Farben sind immer noch invers oder verzerrt. Danke für deine Antwort. –

Antwort

2

Ich habe eine Lösung für mein eigenes Problem gefunden. Um alle Bilder auf allen Seiten zu extrahieren, ist es nicht notwendig, verschiedene Filter zu implementieren. iTextSharp verfügt über einen Image-Renderer, der alle Bilder in ihrem ursprünglichen Bildtyp speichert.

tun Nur das hier folgende: http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx Sie brauchen nicht Httphandler ...

+0

Die Website antwortet nicht für mich, aber ein Snapshot ist über die Wayback Machine verfügbar: https://web.archive.org/web/20160714220626/http://kuujinbo.info/iTextSharp/CCITTFaxDecodeExtract.aspx –

1

PDF unterstützt eine recht große Auswahl an Bildformaten. Ich glaube nicht, dass ich diesen hier gewählten Ansatz wählen würde. Sie müssen das Bildformat aus den Bytes im Stream selbst bestimmen. Zum Beispiel beginnt JPEG typischerweise mit dem ASCII-Bytes JFIF.

.NET (3.0+) kommt mit einer Methode, die versuchen wird, den richtigen Decoder auszuwählen: BitmapDecoder.Create. Siehe http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapdecoder.aspx

Wenn das nicht funktioniert, sollten Sie einige Bildverarbeitungsbibliotheken von Drittanbietern in Betracht ziehen. Ich habe ImageMagick.NET und LeadTools verwendet (viel zu teuer).

3

selbst zu implementieren gefunden Sie Lösung für Ihr Problem, lassen Sie mich sagen Vorschlag Code oben zu beheben.

Ich glaube, dass das Verzerrungsproblem wegen der Nichtübereinstimmung der Zeilendatengrenze verursacht wird. PdfReader gibt Daten in einer Bytegrenze zurück. Beispielsweise erhalten Sie für 20 Pixel breites Graustufenbild 20 Byte Daten für jede Bildzeile. Bitmap-Klasse arbeitet mit 32-Bit-Grenze. Beim Erstellen einer Bitmap mit einer Breite von 20 Pixeln generiert die Bitmap-Klasse eine Graustufen-Bitmap mit Schrittweite (Bytebreite) = 32 Byte. Das bedeutet, dass Sie die abgerufenen Bytes nicht einfach mithilfe der Marshal.Copy() - Methode aus PdfReader in eine neue Bitmap kopieren können, wie es in ToPixelFormat() der Fall ist.

Das erste Pixel im Quellbyte-Array befindet sich als 21. Byte, aber das Ziel-Bitmap benötigt es als 33. Byte, da die 32-Bit-Grenze des Bitmaps gilt. Um dieses Problem zu lösen, musste ich ein Byte-Array mit einer Größe erstellen, die die 32-Bit-Grenze für jede Datenzeile berücksichtigt.

Daten zeilenweise aus Byte-Array, das aus PdfReader abgerufen wurde, in ein neues Bytearray mit 32-Bit-Zeilengrenze kopieren. Jetzt hatte ich Datenbytes mit einer Grenze, die der Bitmap-Klassengrenze entsprach, sodass ich sie mit Marshal.Copy() in die neue Bitmap kopieren kann.