2012-02-26 9 views
5

Intento cargar una imagen en imgQInput (que es un TImage), asignarla a TJpegImage, comprimirla (factor de compresión 5) y mostrarla en imgQOutput (otro TImage). Pero no funciona. La imagen en imgQOutput es la misma que en el original. ¡Debería verse MUY pixelado debido al factor de compresión! La compresión funciona sin embargo, porque cuando guardo el JPEG en el disco, es realmente pequeño.No puedo comprimir una imagen JPEG y mostrarla en la pantalla

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 tanto DIB de mapa de bits como JPegData, aunque la compresión funciona y el guardar en archivo/secuencia guarda el JPeg comprimido, asignándolo a un TImage.Picture utiliza el DIB en lugar de dejarle la imagen original, Vahid's La respuesta funciona porque ha vuelto a cargar el JPeg desde la transmisión, borrando así el DIB. – Dampsquid

+0

Gracias Dampsquid. ¿Hay otra forma de hacerlo sin volver a cargarlo desde la transmisión? Al igual que JpegNeeded o así? – Ampere

+0

Nunca encontré una, DIBNeeded solo crea una si ya no hay una, y la asignación a una nueva TJPegImage también asigna DIB para que no funcione tampoco. – Dampsquid

Respuesta

6

No usaste el JPG comprimido en absoluto.

Cambio CompressJpeg como de seguidores: (recuerde, las imágenes pueden ser grandes)

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

Funciona. Gracias. ¿Puedes explicarlo un poco? – Ampere

+0

De nada. Cuando comprime/guarda una instancia de TJpegImage, no afecta el búfer original. Por lo tanto, debe volver a cargar 'OutJPG' con la secuencia jpeg recién creada para actualizar el búfer. –

+0

Pero cuando guardo el OutJPG en el disco, la imagen está comprimida. Entonces, algo fue cambiado. – Ampere

3

Aquí es una respuesta que compiten por usted, con menos de malabares de datos

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 dispone volátil DIB contenida dentro de Instancia de TJPEGImage. En el caso ilustrado, esto hace que la clase decodifique recientemente .Compress 'ed JPEG en respuesta al repintado TImage.

+0

¿Qué hace la parte 'FreeBitmap'? (¿confiere?) –

+0

@LeonardoHerrera, agregó una observación a una respuesta. – OnTheFly

+0

¡Lo tengo, gracias! –

Cuestiones relacionadas