Конференция "Media" » TBitmap -> Jpeg без использования tjpegimage [WinXP]
 
  • Amper (22.03.09 22:00) [0]
    Здравствуйте уважаемые мастера.
    Есть необходимость перевода битмапа в жпег. Вцл модуль использовать в приложении размер которого без него составляет порядка 30кб не слишком целесообразно. поэтому хотелось бы найти способ поэкономичнее.
    Просьба не говорить 'используй gdi+' или еще что-то в этом роде, интересует конкретный код. Видел реализации на с++, перевести на паскаль не смог...
    Заранее огромное спасибо тому, кто реально поможет.
    Версия среды - 2009, винХП
  • DVM © (22.03.09 23:42) [1]
  • Sapersky (23.03.09 00:38) [2]
    Если приложение рассчитано на "винХП" и далее, то наиболее экономичный вариант - это именно GDI+, нужная DLL в XP присутствует изначально.
    Можно ещё посмотреть KOLJpegObj ( http://kolmck.net/rindex.htm ), там получается что-то около 70 кб к exe'шнику.
    IJL1.5 примечательна скорее скоростью (одна из самых быстрых библиотек), чем малым размером (370 кб). Другой вопрос - какой смысл сейчас экономить...
  • Amper (23.03.09 12:42) [3]
    Спасибо за предложенные варианты
    но решение нашел сам

    procedure SavetoFile(aFile: string;Bitmap: tbitmap);
    var
     imgFile          : GPIMAGE;
     mem              : TMemoryStream;
     aptr             : IStream;
     encoderClsid     : TGUID;
     input: TGdiplusStartupInput;
     token: dword;
    begin
     mem     := TMemoryStream.Create;
     Bitmap.SaveToStream(mem);
     mem.Seek(0, soFromBeginning);
     aptr    := TStreamAdapter.Create(mem, soReference) as IStream;
     imgFile := nil;
     FillChar(input, SizeOf(input), 0);
     input.GdiplusVersion := 1;
     GdiplusStartup(token, @input, nil);
     GdipLoadImageFromStream(aptr, imgFile);
     GetEncoderClsid('image/jpeg', encoderClsid);
     GdipSaveImageToFile(imgFile, pwchar(aFile), @encoderClsid, nil);
     GdiplusShutdown(token);
     aptr := nil;
     mem.Free;
    end;



    и юнит:
    unit JpgGDIP;

    interface

    const WINGDIPDLL = 'gdiplus.dll';

    type
     Status = (
       Ok,
       GenericError,
       InvalidParameter,
       OutOfMemory,
       ObjectBusy,
       InsufficientBuffer,
       NotImplemented,
       Win32Error,
       WrongState,
       Aborted,
       FileNotFound,
       ValueOverflow,
       AccessDenied,
       UnknownImageFormat,
       FontFamilyNotFound,
       FontStyleNotFound,
       NotTrueTypeFont,
       UnsupportedGdiplusVersion,
       GdiplusNotInitialized,
       PropertyNotFound,
       PropertyNotSupported
     );

     TStatus = Status;
     GpStatus          = TStatus;

     ImageCodecInfo = packed record
       Clsid             : TGUID;
       FormatID          : TGUID;
       CodecName         : PWCHAR;
       DllName           : PWCHAR;
       FormatDescription : PWCHAR;
       FilenameExtension : PWCHAR;
       MimeType          : PWCHAR;
       Flags             : DWORD;
       Version           : DWORD;
       SigCount          : DWORD;
       SigSize           : DWORD;
       SigPattern        : PBYTE;
       SigMask           : PBYTE;
     end;

     TImageCodecInfo = ImageCodecInfo;
     PImageCodecInfo = ^TImageCodecInfo;
     GpImage = Pointer;
     DebugEventLevel = (
       DebugEventLevelFatal,
       DebugEventLevelWarning
     );

     DebugEventProc = procedure(level: DebugEventLevel; message: PChar); stdcall;
     GdiplusStartupInput = packed record
       GdiplusVersion          : Cardinal;       // Must be 1
       DebugEventCallback      : DebugEventProc; // Ignored on free builds
       SuppressBackgroundThread: BOOL;           // FALSE unless you're prepared to call
                                                 // the hook/unhook functions properly
       SuppressExternalCodecs  : BOOL;           // FALSE unless you want GDI+ only to use
     end;                                        // its internal image codecs.
     TGdiplusStartupInput = GdiplusStartupInput;
     PGdiplusStartupInput = ^TGdiplusStartupInput;
     NotificationHookProc = function(out token: ULONG): Status; stdcall;
     NotificationUnhookProc = procedure(token: ULONG); stdcall;
     GdiplusStartupOutput = packed record
       NotificationHook  : NotificationHookProc;
       NotificationUnhook: NotificationUnhookProc;
     end;
     TGdiplusStartupOutput = GdiplusStartupOutput;
     PGdiplusStartupOutput = ^TGdiplusStartupOutput;
     EncoderParameterValueType = Integer;
     TEncoderParameterValueType = EncoderParameterValueType;
     EncoderParameter = packed record
       Guid           : TGUID;   // GUID of the parameter
       NumberOfValues : ULONG;   // Number of the parameter values
       Type_          : ULONG;   // Value type, like ValueTypeLONG  etc.
       Value          : Pointer; // A pointer to the parameter values
     end;
     TEncoderParameter = EncoderParameter;
     PEncoderParameter = ^TEncoderParameter;
     EncoderParameters = packed record
       Count     : UINT;               // Number of parameters in this structure
       Parameter : array[0..0] of TEncoderParameter;  // Parameter values
     end;
     TEncoderParameters = EncoderParameters;
     PEncoderParameters = ^TEncoderParameters;
     function GdipGetImageEncodersSize(out numEncoders: UINT; out size: UINT): GPSTATUS; stdcall;
     function GdipGetImageEncoders(numEncoders: UINT; size: UINT; encoders: PIMAGECODECINFO): GPSTATUS; stdcall;
     function GdiplusStartup(out token: ULONG; input: PGdiplusStartupInput; output: PGdiplusStartupOutput): Status; stdcall;
     procedure GdiplusShutdown(token: ULONG); stdcall;
     function GdipLoadImageFromFile(filename: PWCHAR; out image: GPIMAGE): GPSTATUS; stdcall;
     function GdipLoadImageFromStream(Stream: IStream; out image: GPIMAGE): GPSTATUS; stdcall;
     function GdipSaveImageToFile(image: GPIMAGE; filename: PWCHAR; clsidEncoder: PGUID; encoderParams: PENCODERPARAMETERS): GPSTATUS; stdcall;
     function GetImageEncodersSize(out numEncoders, size: UINT): TStatus;
     function GetImageEncoders(numEncoders, size: UINT; encoders: PImageCodecInfo): TStatus;
     function GetEncoderClsid(format: String; out pClsid: TGUID): integer;
    implementation
    function GdipGetImageEncodersSize; external WINGDIPDLL name '
    GdipGetImageEncodersSize';
    function GdipGetImageEncoders; external WINGDIPDLL name '
    GdipGetImageEncoders';
    function GdiplusStartup; external WINGDIPDLL name '
    GdiplusStartup';
    procedure GdiplusShutdown; external WINGDIPDLL name '
    GdiplusShutdown';
    function GdipLoadImageFromFile; external WINGDIPDLL name '
    GdipLoadImageFromFile';
    function GdipLoadImageFromStream; external WINGDIPDLL name '
    GdipLoadImageFromStream';
    function GdipSaveImageToFile; external WINGDIPDLL name '
    GdipSaveImageToFile';
    function GetImageEncodersSize(out numEncoders, size: UINT): TStatus;
     begin
       result := GdipGetImageEncodersSize(numEncoders, size);
     end;
     function GetImageEncoders(numEncoders, size: UINT; encoders: PImageCodecInfo): TStatus;
     begin
       result := GdipGetImageEncoders(numEncoders, size, encoders);
     end;
    function GetEncoderClsid(format: String; out pClsid: TGUID): integer;
    var
     num, size, j: UINT;
     ImageCodecInfo: PImageCodecInfo;
    Type
     ArrIMgInf = array of TImageCodecInfo;
    begin
     num  := 0; // number of image encoders
     size := 0; // size of the image encoder array in bytes
     result := -1;
     GetImageEncodersSize(num, size);
     if (size = 0) then exit;
     GetMem(ImageCodecInfo, size);
     if(ImageCodecInfo = nil) then exit;
     GetImageEncoders(num, size, ImageCodecInfo);
     for j := 0 to num - 1 do
     begin
       if( ArrIMgInf(ImageCodecInfo)[j].MimeType = format) then
       begin
         pClsid := ArrIMgInf(ImageCodecInfo)[j].Clsid;
         result := j;  // Success
       end;
     end;
     FreeMem(ImageCodecInfo, size);
    end;
    end.

  • Eraser © (23.03.09 18:52) [4]
    > [0] Amper   (22.03.09 22:00)


    > Вцл модуль использовать в приложении размер которого без
    > него составляет порядка 30кб не слишком целесообразно.

    а что за цели у проекта, если не секрет? )
  • Palladin © (25.03.09 19:02) [5]
    Занять как можно меньше места на диске.
  • Louter (04.03.10 02:41) [6]
    Странно -- с одной стороны автор сказал

    > Просьба не говорить 'используй gdi+'

    , но использует его.
    Вообще спецификацию jpeg можно найти на его родном сайте, но кодек писать -- психоз в высшей степени. Поэтому код интересен (хотя маль-мальски излишен и перегружен).
  • Вася (04.03.10 12:45) [7]
    > но кодек писать -- психоз в высшей степени

    почему?я подумывал...
    а что вы подразумевали под кодеком(может я как-то не так понял)?
 
Конференция "Media" » TBitmap -> Jpeg без использования tjpegimage [WinXP]
Есть новые Нет новых   [120149   +140][b:0][p:0.004]