2012-02-26 13 views
5

Cerco di caricare un'immagine in imgQInput (che è una TImage), assegnarla a TJpegImage, comprimerla (fattore di compressione 5) e mostrarla in imgQOutput (un'altra TImage). Ma non funziona. L'immagine in imgQOutput è la stessa dell'originale. Dovrebbe sembrare MOLTO pixelato a causa del fattore di compressione! La compressione funziona comunque, perché quando salgo il file JPEG su disco è molto piccolo.Impossibile comprimere l'immagine JPEG e mostrarla sullo schermo

JPG:= TJPEGImage.Create; 
    TRY 
    JPG.CompressionQuality:= trkQuality.Position; 
    JPG.Assign(imgQInput.Picture.Graphic); 
    CompressJpeg(JPG); 
    imgQOutput.Picture.Assign(JPG);   <--------- something wrong here. the shown image is not the compressed image but the original one 
    FINALLY 
    FreeAndNil(JPG); 
    END; 


function CompressJpeg(OutJPG: TJPEGImage): Integer; 
VAR tmpQStream: TMemoryStream; 
begin 
tmpQStream:= TMemoryStream.Create; 
TRY 
    OutJPG.Compress; 
    OutJPG.SaveToStream(tmpQStream); 
    OutJPG.SaveToFile('c:\CompTest.jpg');  <--------------- this works 
    Result:= tmpQStream.Size; 
FINALLY 
    FreeAndNil(tmpQStream); 
END; 
end; 
+2

TJpegImage contiene sia il bitmap DIB che il JPegData, anche se il comprime funziona e il salvataggio in file/stream salva il JPeg compresso, assegnandolo a un TImage.Picture utilizza il DIB invece di lasciarvi con l'immagine originale, Vahid's la risposta funziona perché ha ricaricato lo JPeg indietro dal flusso, cancellando così il DIB. – Dampsquid

+0

Grazie Dampsquid. C'è un altro modo per farlo senza ricaricarlo dal flusso? Come JpegNeeded o così? – Ampere

+0

Non ne ho mai trovato uno, DIBNeeded ne crea uno solo se non ce n'è uno, e assegnando a un nuovo TJPegImage si assegna anche il DIB in modo che non funzioni neanche. – Dampsquid

risposta

6

Non hai utilizzato il JPG compresso.

Change CompressJpeg come seguenti: (! Ricordate, le immagini possono essere di grandi dimensioni)

function CompressJpeg(OutJPG: TJPEGImage): Integer; 
VAR tmpQStream: TMemoryStream; 
begin 
tmpQStream:= TMemoryStream.Create; 
TRY 
    OutJPG.Compress; 
    OutJPG.SaveToStream(tmpQStream); 
    OutJPG.SaveToFile('c:\CompTest.jpg'); // You can remove this line. 
    tmpQStream.Position := 0;    // 
    OutJPG.LoadFromStream(tmpQStream);  // Reload the jpeg stream to OutJPG 
    Result:= tmpQStream.Size; 
FINALLY 
    FreeAndNil(tmpQStream); 
END; 
end; 
+0

Funziona. Grazie. Puoi spiegarlo un po '? – Ampere

+0

Prego. Quando si comprime/salvano un'istanza di TJpegImage, questo non influisce sul buffer originale. Quindi è necessario ricaricare 'OutJPG' con il flusso jpeg appena creato per aggiornare il buffer. –

+0

Ma quando salgo l'OutJPG su disco, l'immagine è compressa. Quindi, qualcosa è stato cambiato. – Ampere

3

Ecco una risposta in competizione per voi, con meno giocoleria dati

type 
    TJPEGExposed = class(TJPEGImage);  // unfortunately, local class declarations are not allowed 

procedure TForm1.FormClick(Sender: TObject); 
var 
    JPEGImage: TJPEGImage; 
const 
    jqCrappy = 1; 
begin 
    Image1.Picture.Bitmap.LoadFromFile(GetDeskWallpaper); 

    Image2.Picture.Graphic := TJPEGImage.Create; 
    JPEGImage := Image2.Picture.Graphic as TJPEGImage; // a reference 
    JPEGImage.Assign(Image1.Picture.Bitmap); 
    JPEGImage.CompressionQuality := jqCrappy; // intentionally 
    JPEGImage.Compress; 
    TJPEGExposed(JPEGImage).FreeBitmap; { confer: TBitmap.Dormant } 
end; 

TJPEGImage.FreeBitmap dismette volatili DIB contenuto all'interno Istanza TJPEGImage. Nel caso illustrato questo fa sì che la classe decodifichi di recente .Compress 'ed JPEG in risposta a TImage ridipintando.

+0

Cosa fa la parte 'FreeBitmap'? (conferire?) –

+0

@LeonardoHerrera, aggiunta osservazione a una risposta. – OnTheFly

+0

Capito, grazie! –

Problemi correlati