Jump to content


Photo

Convertir imágenes png a jpg


  • Please log in to reply
6 replies to this topic

#1 robert01

robert01

    Advanced Member

  • Miembros
  • PipPipPip
  • 162 posts
  • LocationArgentina

Posted 21 January 2012 - 07:08 AM

Hola amigos

Hace tiempo que no ando por aquí. Espero que hayan empezado bien el año 2012
Necesito saber si hay alguna forma de convertir imágenes png a jpg sin tener que abrir cada una de las imágenes. Tengo varios miles de imágenes png y me gustaría tenerlas en formato jpg
Gracias y saludos a todos

Roberto

  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 22 January 2012 - 11:44 AM

La forma mas sencilla de realizar conversiones de archivos de imagen, sin usar complicadas librerías gráficas, es usando las capacidades del propio S.O. Windows en su librería GDI+.

Hace unos meses publiqué un truco para leer archivos de varios formatos gráficos usando GDI+.

Para responder a robert01 voy a poner un ejemplo del uso de GDI+ para leer un archivo y codificarlo en jpeg. La pequeña aplicación de ejemplo, copiada en la carpeta que deseamos explorar, convertirá todos los archivos encontrados con extensión ".png" en archivos jpeg con el mismo nombre y nueva extensión ".jpg".

Esta aplicación puede ser adaptada, con algunos cambios y algo de código añadido, para ajustar la calidad de compresión y codificar en otros formatos, además de jpg.

El código es el siguiente, escrito y compilado en Builder C++ 5:
 


cpp
  1. //---------------------------------------------------------------------------
  2. #define STRICT
  3. #include <windows.h>
  4. #include <algorithm>
  5. using std::min;
  6. using std::max;
  7. #include "Gdiplus.h"
  8.  
  9. #include <vcl.h>
  10. #pragma hdrstop
  11.  
  12. #pragma comment(lib, "Gdiplus.lib")
  13. //---------------------------------------------------------------------------
  14.  
  15. Gdiplus::GdiplusStartupInput gdiplusStartupInput;
  16. ULONG_PTR  gdiplusToken;
  17.  
  18. // Encontrar el CLSID para codificar en el formato deseado.
  19. bool GetEncoderClsid(const WCHAR* Format, CLSID* Clsid)
  20. {
  21.   UINT i=0, N=0, Size=0;
  22.  
  23.   Gdiplus::GetImageEncodersSize(&N, &Size);
  24.   if(!Size) return false;
  25.  
  26.   Gdiplus::ImageCodecInfo* ICInfo = new Gdiplus::ImageCodecInfo[Size];
  27.   Gdiplus::GetImageEncoders(N, Size, ICInfo);
  28.  
  29.   while (i<N && wcscmp(ICInfo[i].MimeType, Format)) i++;
  30.   if(i<N) *Clsid = ICInfo[i].Clsid;
  31.   delete [] ICInfo;
  32.  
  33.   return (i<N);
  34. }
  35.  
  36. void ToJpg(WCHAR* FileName)
  37. {
  38.   CLSID Clsid;
  39.   GetEncoderClsid(L"image/jpeg", &Clsid);
  40.   Gdiplus::Bitmap SrcBitmap(FileName, 0);
  41.   wcscpy(&FileName[wcslen(FileName)-4], L".jpg");
  42.   SrcBitmap.Save(FileName, &Clsid, NULL);
  43. }
  44.  
  45. #pragma argsused
  46. WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  47. {
  48.   // Initialize GDI+.
  49.   if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL)) return 0;
  50.  
  51.   HANDLE hFindFile;
  52.   WIN32_FIND_DATAW WFData;
  53.   if((hFindFile = FindFirstFileW(L"*.png", &WFData))!=INVALID_HANDLE_VALUE){
  54.     do{
  55.       ToJpg(WFData.cFileName);
  56.     } while (FindNextFileW(hFindFile, &WFData));
  57.     FindClose(hFindFile);
  58.   }
  59.  
  60.   //shutdown GDI+
  61.   Gdiplus::GdiplusShutdown(gdiplusToken);
  62.   return 0;
  63. }
  64. //---------------------------------------------------------------------------

Para usar el programita, se debe copiar en la carpeta donde se alojan los archivos a convertir, seguidamente se ejecuta, lo hará en segundo plano, convirtiendo todos los archivos png encontrados en jpg.

Espero que sea de utlidad y sirva de respuesta a la pregunta planteada.

Subo un archivo con el código fuente y compilado.



Saludos.

Attached Files


  • 0

#3 robert01

robert01

    Advanced Member

  • Miembros
  • PipPipPip
  • 162 posts
  • LocationArgentina

Posted 22 January 2012 - 12:43 PM

Muy bueno el código.
Muchas gracias Escafandra por haber respondido, sobre todo siendo día domingo

Saludos
  • 0

#4 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1092 posts
  • LocationMurcia, España

Posted 23 January 2012 - 03:44 AM

Yo a nivel personal hago estas cosas con el programa ACDSee, supongo que iFranView o similares hace lo mismo de forma parecida. No tiene nada que ver con programación, pero es muy sencillo cambiar de formato ficheros aunque tengas miles en la carpeta con este tipo de aplicaciones.
  • 0

#5 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 23 January 2012 - 05:53 PM

¿Te parece que lo marquemos como resuelto robert01?


Saludos.
  • 0

#6 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 25 January 2012 - 06:24 PM

Y también en delphi.

En un ratillo libre me he entretenido jugando con la API Flat del GDI plus y he escrito una aplicación muy similar a la que hice en C++ con alguna mejora y en delphi.

La aplicación trabaja en consola, permite establecer la calidad de compresión jpg y va indicando los archivos convertidos.

Se trata de un ejemplo de lo que se puede hacer con la API GDI plus desde versiones antiguas del delphi usando API pura en una aplicación de muy poco peso:
 


delphi
  1. program PngToJpg;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses
  6.   Windows;
  7.  
  8. type
  9. TCLSID = TGUID;
  10. PCLSID = ^TCLSID;
  11. TImageCodecInfo = packed record
  12.   Clsid:            TCLSID;
  13.   FormatID:          TGUID;
  14.   CodecName:        PWCHAR;
  15.   DllName:          PWCHAR;
  16.   FormatDescription: PWCHAR;
  17.   FilenameExtension: PWCHAR;
  18.   MimeType:          PWCHAR;
  19.   Flags:            DWORD;
  20.   Version:          DWORD;
  21.   SigCount:          DWORD;
  22.   SigSize:          DWORD;
  23.   SigPattern:        PBYTE;
  24.   SigMask:          PBYTE;
  25. end;
  26. PImageCodecInfo = ^TImageCodecInfo;
  27.  
  28. TEncoderParameter = packed record
  29.   Guid:          TGUID;
  30.   NumberOfValues: ULONG;
  31.   Type_:          ULONG;
  32.   Value:          Pointer;
  33. end;
  34. PEncoderParameter = ^TEncoderParameter;
  35.  
  36. TEncoderParameters = packed record
  37.   Count    : UINT;
  38.   Parameter : array[0..0] of TEncoderParameter;
  39. end;
  40. PEncoderParameters = ^TEncoderParameters;
  41.  
  42. function  atoi(str: PCHAR): Integer; cdecl external 'crtdll';
  43. function  wcscpy(wstr1, wstr2: PWCHAR): Integer; cdecl external 'crtdll';
  44. function  wcscmp(wstr1, wstr2: PWCHAR): Integer; cdecl external 'crtdll';
  45. function  wcslen(wstr: PWCHAR): Integer; cdecl external 'crtdll';
  46. function  GdiplusStartup(var GdiToken: DWORD; Startup, Output: PBYTE): Cardinal; stdcall external 'gdiplus';
  47. procedure GdiplusShutdown(GdiToken: DWORD); stdcall external 'gdiplus';
  48. function  GdipCreateHBITMAPFromBitmap(GBitmap: THANDLE; var hBitmap: HBITMAP; BKColor: DWORD): Cardinal; stdcall external 'gdiplus';
  49. function  GdipGetImageEncodersSize(var numEncoders: DWORD; var size: DWORD): Cardinal; stdcall external 'gdiplus';
  50. function  GdipGetImageEncoders(numEncoders, size: DWORD; encoders: PImageCodecInfo): Cardinal; stdcall external 'gdiplus';
  51. function  GdipSaveGraphics(graphics: Pointer; state: Pointer): Cardinal; stdcall external 'gdiplus';
  52. function  GdipLoadImageFromFile(filename: PWCHAR; var image: THANDLE): Cardinal; stdcall external 'gdiplus';
  53. function  GdipSaveImageToFile(image: THANDLE; filename: PWCHAR; var clsidEncoder: TCLSID; encoderParams: Pointer): Cardinal; stdcall external 'gdiplus';
  54.  
  55. // Calidad de imagen y factor de compresión
  56. // Quality = 100 es la maxima calidad.
  57. procedure GetEncoderParameters(EP: PEncoderParameters; Quality: PULONG);
  58. const
  59.   EncoderQuality: TGUID = '{1d5be4b5-fa4a-452d-9cdd-5db35105e7eb}';
  60. begin
  61.   EP.Count:= 1;
  62.   EP.Parameter[0].Guid:= EncoderQuality;
  63.   EP.Parameter[0].Type_:= 4; //Gdiplus::EncoderParameterValueTypeLong;
  64.   EP.Parameter[0].NumberOfValues:= 1;
  65.   EP.Parameter[0].Value:= Quality;
  66. end;
  67.  
  68. // Obtener el CLSID para la codificación de un formato gráfico
  69. function GetEncoderClsid(Format: PWCHAR; var Clsid: TCLSID): boolean;
  70. var
  71.   i, N, Size: Cardinal;
  72.   ICInfo: array of TImageCodecInfo;
  73. begin
  74.   Result:= false;
  75.   i:= 0; N:= 0; Size:= 0;
  76.   GdipGetImageEncodersSize(N, Size);
  77.   if Size > 0 then
  78.   begin
  79.     SetLength(ICInfo, Size);
  80.     GdipGetImageEncoders(N, Size, @ICInfo[0]);
  81.     while (i<N) and (wcscmp(ICInfo[i].MimeType, Format)<>0) do inc(i);
  82.     if i<N then Clsid:= ICInfo[i].Clsid;
  83.   end;
  84.   Result:= boolean(i<N);
  85. end;
  86.  
  87. // La conversión de formato
  88. procedure _ToJpg(FileName: PWCHAR; Parameters: PEncoderParameters);
  89. var
  90.   Clsid: TCLSID;
  91.   Image: THANDLE;
  92. begin
  93.   GetEncoderClsid('image/jpeg', Clsid);
  94.   GdipLoadImageFromFile(FileName, Image);
  95.   wcscpy(@FileName[wcslen(FileName)-4], '.jpg');
  96.   GdipSaveImageToFile(Image, FileName, Clsid, Parameters);
  97. end;
  98.  
  99.  
  100. var
  101. gdiplusToken: DWORD;
  102. GdiPlusStartupInput: array[0..2] of int64;
  103. hFindFile: Cardinal;
  104. WFData:  WIN32_FIND_DATAW;
  105. EP: TEncoderParameters;
  106. Quality: ULONG;
  107. buffer: array [0..20] of char;
  108.  
  109. begin
  110.   // Inicializamos GDI+.
  111.   GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0;
  112.   if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) <> 0 then
  113.   begin
  114.     Write('GDI+ Error.');
  115.     exit;
  116.   end;
  117.  
  118.   // Ajustamos Calidad de compresión
  119.   Write('Choose Quality 1-100:  ');
  120.   Readln(buffer);
  121.   Quality:= atoi(buffer);
  122.   GetEncoderParameters(@EP, @Quality);
  123.  
  124.   // Buscamos los archivos png y los convertimos
  125.   hFindFile:= FindFirstFileW('*.png', WFData);
  126.   if(hFindFile <> INVALID_HANDLE_VALUE) then
  127.   repeat
  128.     _ToJpg(WFData.cFileName, @EP);
  129.     WriteLn(WFData.cFileName);
  130.   until not FindNextFileW(hFindFile, WFData);
  131.   FindClose(hFindFile);
  132.  
  133.   // Terminamos la la aplicación
  134.   Write('Press Enter to continue...');
  135.   Readln;
  136.  
  137.   //shutdown GDI+
  138.   GdiplusShutdown(gdiplusToken);
  139. end.

Subo el fuente y el binario. Espero que sea de utilidad, o al menos de curiosidad.



Saludos.

 

Attached Files


  • 0

#7 robert01

robert01

    Advanced Member

  • Miembros
  • PipPipPip
  • 162 posts
  • LocationArgentina

Posted 26 January 2012 - 06:31 PM

Hola

Discúlpa Escafandra, no se porque no me llegó a mi correo ninguna notificación de que hubiera más mensajes para el problema planteado

Voy a ingresar diariamente al foro par evitar que vuelva a ocurrir

Saludos

Roberto
  • 0




IP.Board spam blocked by CleanTalk.