Delphi - Redimensionar imagen a tamaño en bytes

 
Vista:

Redimensionar imagen a tamaño en bytes

Publicado por M@rceloL (42 intervenciones) el 05/10/2007 21:58:12
A ver si alguno sabe cómo se hace esto.

Tengo una imagen y lo que quiero hacer es poder calcular el tamaño al que yo debería achicarla para que el archivo midax cantidad de bytes.

Es decir, me dan una imagen y el tamaño final del archivo, y yo tengo que decidir cúanto achicar/agrandar la imagen para que el tamaño final del archivo sea la cantidad exacta que me direron...

¿Alguna idea?

Gracias, gente.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Redimensionar imagen a tamaño en bytes

Publicado por BigLuis (713 intervenciones) el 05/10/2007 22:46:50
De entrada yo no se como hacerlo, pero como me gustan los retos y este me gusta voy a hacer lo siguiente. Yo se redimensionar proporcionalmente una imagen al tamaño que yo quiera y posteriormente saber su tamaño, por lo tanto si hago un bucle en el que vaya redimensionando por ejemplo decreciendo de uno en uno y comparando el nuevo tamaño con que yo quiero conseguir, cuando llegue a el, hago un break y ya tengo la imagen con las dimensiones adecuadas para el tamaño deseado.
Tengo que probarlo porque no se el consumo de la cpu o de la memoria y si derá rentable pero nada cuenta intentarlo.
Ya te dire cosas porque ahora viene el fin de semana y ya sabes....
Suerte
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Redimensionar imagen a tamaño en bytes

Publicado por M@rceloL (42 intervenciones) el 06/10/2007 02:00:22
¡Gracias, Luis! No te pido que me lo programes, si querés mandarme la idea básica para que yo me complique la vida, no hay problemas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Redimensionar imagen a tamaño en bytes

Publicado por BigLuis (713 intervenciones) el 06/10/2007 15:30:47
Nunca interpreté que quisieras que te lo programara ni yo pensaba hacerlo. Lo unico que haré, para mi, porque me interesa, es intentar solucionarlo pero solamente para entretenerme nunca para ocupar tu lugar. La idea basica es la que te comenté anteriormente:
1.- Tienes una imagen jpg. de por ejemplo 800x600 con un tamaño determinado.
2.- La reduces proporcionalmente a 700x y obtienes otro tamaño.
Bien esta es la idea : como tienes un tamaño fijo que tienes que conseguir se podria hacer un bucle decreciendo el tamaño a cada pado y comparando el nuevo tamaño con que que tienes que lograr. No se si me entiendes o tengo la cabeza demasiado liada.
por ejemplo
for I:=800 DOWNTO 30 DO
begin
reduzcolaimagen con la dimension de I;
obtengo el tamaño;
if (elnuevotamaño>tamañoconstante-5 and elnuevotamaño<tamañoconstante+5 ) [para dejar un margen por si no conseguimos el tamaño exacto] then Break
end;
Si necesitas alguna funcion para hacerlo dilo aunque estoy seguro que las tendras y bastante mas optimizadas que las mias.
Suerte
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ya lo consegui mas o menos

Publicado por BigLuis (713 intervenciones) el 07/10/2007 17:56:24
No hice el bucle pero ya tengo las funciones adecuadas. El siguiente paso es el bucle, ya veremos pero creo el el margen de tamaño va a tener que ser un poco mas amplio de 5.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

El bucle tambien

Publicado por BigLuis (713 intervenciones) el 08/10/2007 15:09:36
Al principio va un poco lento con un fotograma jpg de 2048 x 1536 pero al ir bajando la resolucion corre bastante. Tarda en conseguir un fotograma de 30000 bytes unos 15 o 20 segundos.
Saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:El bucle tambien

Publicado por M@rceloL (42 intervenciones) el 09/10/2007 00:22:27
Bueno, yo también me puse a probar de una forma bastante (bueno, muy) cruda usando StretchDraw del TCanvas.

Con ciclo y todo que me compara el tamaño del TStream anda razonablemente bien. Claro que no he probado con alguna función para escalar más decente, que seguramente va a tardar más.

Muy así nomás, sin excepciones y sin "estilo":

var
jpg,orig:tjpegimage;
bmp:tbitmap;
scale:double;
s:tmemorystream;
val:integer;

begin
..jpg := TJpegImage.Create;
..orig:=tjpegimage.create;
..orig.Loadfromfile(od.FileName);
..jpg.Assign(orig);
..bmp := TBitmap.Create;
..val:=jpg.width;
..repeat
....scale := val / jpg.Width;
....bmp.Width := Round(jpg.Width * scale);
....bmp.Height := Round(jpg.Height * scale);
....bmp.canvas.StretchDraw(bmp.Canvas.Cliprect, orig);
....jpg.Assign(bmp);
....s:=tmemorystream.Create;
....jpg.SaveToStream(s);
....val:=val - 100;
..until s.Size<1048576;
..jpg.SaveToFile(ChangeFileext(od.filename, '_thumb.JPG') );
..bmp.free;
..jpg.Free;
..orig.free;
end;

La verdad es que no garantiza que la imagen tenga justo 1MB pero bueno, qué le vamos a hacer...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 65
Oro
Ha mantenido su posición en Delphi (en relación al último mes)
Gráfica de Delphi

RE:El bucle tambien

Publicado por E.T. (1244 intervenciones) el 09/10/2007 01:39:51
En realidad, para cambiar el tamaño de la imagen y que mantenga es "aspect ratio", ademas del tamaño que requieres, es complicado, y raras veces se te puede presentar, puedes modificar el tamaño de ancho y alto, uno por uno, pero al final puede distorcionarse la imagen, lo que yo haria, y es una cuestion muy personal para cada uno es:

modificar la imagen hasta que ( manteniendo el "aspect ratio") se aproxime al tamaño que deseamos hasta que ya no se pueda mas, luego en la dimensión mas pequeña de la imagen, hacer otra modificación pero sólo de esa dimensión ( para no distorcionar tanto la imagen) de esta manera el tamaño final se acerca un poco mas al que necesitarias.

Pero esto claro es, mi punto de vista.

Tambien estoy tabajando en una pequeña función que te calcule, respecto al tamaño origina con el requerido, una proporción del tamaño, y así partir de ese punto para hacer mas pequeño el bucle de redimensionamiento, si tengo exito lo publico aqui mismo
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:El bucle tambien

Publicado por M@rceloL (42 intervenciones) el 10/10/2007 04:29:23
Yo no te considero un novato (yo sí me considero bastante novatón), para nada...

De echo, me has dado la pista de la calidad del JPEG, que yo no había encontrado.

También lo del Alto>Ancho, que yo dejé afuera por ser fotos de cámara digital... Y pensé que no habría problema...

ET: Sí que es raro que se me presente... Pero se me presentó, el programita es para alguien que no sabe mucho de compus, así que hay que facilitarle las cosas. ¿Me pregunto porqué todos los programitas que vi para hacer esto eran tan poco amigables? Realmente se ve que nadie tiene este tipo de problemas (o que saben cómo resolverlo bien).
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:El bucle tambien

Publicado por BigLuis (713 intervenciones) el 09/10/2007 11:01:21
Basicamente es lo que yo hice, con pequeñas modificaciones y separando los trabajos en funciones (que al final es lo mismo). Lo del tamaño yo tambien tuve el mismo problema por eso te decia en el mensaje anterior que lo comparaba en +- 5 o 10 o 20.
Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Yo lo hice asi

Publicado por BigLuis (713 intervenciones) el 09/10/2007 14:56:16
Se pueden mejorar con parametros etc, pero yo solo queria ver si era capaz de lograrlo.
¿ Como se nota que tengo tiempo eh Marcelo? el triple de lineas que tu para hacer lo mismo. Los novatos somos asi jejeje.
//****************************************************************************
FUNCTION GetFileSize(CONST Filename: STRING): INTEGER;
VAR
FileStream: TFileStream;
BEGIN
TRY
FileStream := TFileStream.Create(Filename, fmOpenRead + fmShareDenyNone);
RESULT := FileStream.Size;
FileStream.Free;
EXCEPT
RESULT := 0
END
END {GetFileSize};
//****************************************************************************
//Procedimiento que crea el thumbnail
procedure ReduceJPG(Imagen:TJPEGImage;Lado:Integer=75);
var
bmp: TBitmap;
escala: Double;
begin
if Imagen.Height > Imagen.Width then
escala := Lado / Imagen.Height
else
escala := Lado / Imagen.Width;
bmp := TBitmap.Create;
try
//Crear el thumbnail
bmp.Width := Round(Imagen.Width * escala);
bmp.Height := Round(Imagen.Height * escala);
bmp.Canvas.StretchDraw(bmp.Canvas.Cliprect, Imagen);
Imagen.Assign(Bmp);
finally
bmp.free;
end;
end;
//****************************************************************************
PROCEDURE TForm1.LoadBucle(CONST Filename: STRING);
var
JPEGImage : TJPEGImage; // in-memory version of what's on screen
JpgStream:TMemoryStream;
I:Integer;
NewTamano:Integer;
Ancho,Alto:Integer;
BEGIN
ParaBucle:=False;
JPGBytes := GetFileSize(Filename);

JPEGImage := TJPEGImage.Create;
try
JPEGImage.Performance:=jpBestQuality;
JPEGImage.LoadFromFile(EditJPG.Text);
Ancho:=JPEGImage.Width;
Alto:=JPEGImage.Height;

//Igualo I al lado mas largo para empezar a decrecer proporcionalmente
//con respecto a ese lado.
if Ancho>Alto then I:=Ancho else I:=Alto;

While (ParaBucle=False) do //de esta forma controlo el bucle desde el exterior
BEGIN
dec(I,strtoint(Edit5.Text));//Edit5.text es la cadencia para decrecer Ejm.(10,20 etc)
Label9.Caption:=INTTOSTR(i);//voy controlando el decrecimiento
Application.ProcessMessages;
ReduceJPG(JPEGImage,I);//Funcion que quea el thumbnail proporcional
//Calculo el nuevo tamaño tras la reduccion
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
JpgStream:=TMemoryStream.Create;
try
JPEGImage.SaveToStream(JpgStream);
//Valores de control mientras trabaja
Label1.Caption := 'Thumbnail : '+FormatFloat('#,', JPGStream.Size) + ' bytes';
Label3.Caption := 'Thumbnail : '+inttostr(JPEGImage.Width) +' x '+inttostr(JPEGImage.Height) ;
NewTamano:=JPGStream.Size;
finally
JpgStream.Free;
end; //Try
Application.ProcessMessages;
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
if NewTamano<=strtoint(Edit4.Text) //Si el thumbnail es menor que el valor fijo, paro el bucle
then
begin
ParaBucle:=True;
//Necesario recargar y reducir la imagen porque si se obtiene del
//procesamiento anterior sale distorsionada.
JPEGImage.LoadFromFile(EditJPG.Text);
ReduceJPG(JPEGImage,I-35);
ImageJPG.Picture.Graphic := nil;
ImageJPG.Picture.Graphic := JPEGImage;
end;
END;
finally
JPEGImage.Free;
end;//try
END {LoadJPEG};

//****************************************************************************
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Yo lo hice asi

Publicado por M@rceloL (42 intervenciones) el 11/10/2007 03:06:26
Yo no te considero un novato, BL. De hecho me diste un par de pistas sobre la calidad del JPEG (que no había podido encontrar) y lo del problema del Ancho<Alto que no se me había ocurrido...

ET: Cierto, es un poco extraña. Pero es para alguien que no sabe mucho sobre compus, así que hay que hacerle la vida fácil. Se ve que no es para nada común porque no encontré ningún programa que hiciera esto y que fuera amigable.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar