К оглавлению

С.И.Хашин

Библиотеки jpgs, lzmas


Упрощённая версия библиотеки jpegLib

Работать можно напрямую, просто добавляя необходимый код в свой проект, можно подключить статическую библиотеку (lib).
jpgs.h - заголовочный файл
jpgs.cpp - реализация.

jpeg\*.h, *.c - файлы библиотеки jpeglib (Tom Lane)
lzma\*.h, *.c - файлы библиотеки LzmaLib (Igor Pavlov)

Библиотека скомпилирована в шести вариантах. Это пришлось сделать потому, что нужны отдельные Debug- и Release-версии в режимах x86 и x64. Кроме того, оказалось, что Visual Studio 2010 и Visual Studio 2015 имеют разные форматы библиотек и не понимают друг друга.

Файл Версия Visual Studio x86/x64 Debug/Release
jpgsD8610.lib 2010 x86 Debug
jpgsR8610.lib 2010 x86 Release
jpgsD86.lib 2015 x86 Debug
jpgsR86.lib 2015 x86 Release
jpgsR64.lib 2015 x64 Debug
jpgsD64.lib 2015 x64 Release

Замечание. При компиляции библиотеки можно создавать отдельный файл базы данных программы (PDB), но есть возможность просто включить всё необходимое в lib-файл. Он получится больше по размеру, но при этом не надо заботиться о расположении pdb-файла.
Эта возможность включается в
Project → Properties → C/C++ → General → Debug Information Format → C7 Compatible.

Для включения библиотеки в свой проект вначале подключается заголовочный файл библиотеки:

#include "..\\lib\\jpgs.h"  // работа с jpeg

Затем сообщаем линковщику, где найти саму библиотетку (lib-файл).
Учитывая большое количество версий, это не так просто:

#ifdef _WIN64
    #ifdef _DEBUG
        #pragma comment(lib, "../lib/jpgsD64.lib")
    #else
        #pragma comment(lib, "../lib/jpgsR64.lib")
    #endif
#else
    #if _MSC_VER ==1600 //  Visual C++ 2010
        #ifdef _DEBUG
            #pragma comment(lib, "../lib/jpgsD8610.lib")
        #else
            #pragma comment(lib, "../lib/jpgsR8610.lib")
        #endif
    #else               //  Visual C++ 2015
        #ifdef _DEBUG
            #pragma comment(lib, "../lib/jpgsD86.lib")
        #else
            #pragma comment(lib, "../lib/jpgsR86.lib")
        #endif
    #endif // #if _MSC_VER ==1600   //  Visual C++ 2010
#endif

Структура каталогов при этом предполагается такая:


  Parent\util   \*.h,*.cpp - здесь размещаются все описанные модули 
    └───\lib    \*.lib     - здесь должны лежать все *.lib -файлы

JPEG-файлы

Для работы с jpeg-файлами используется библиотека LibJpeg Тома Лейна (Tom Lane).


// сохранить/прочитать изображение в/из формате jpg
int  jpegs_save( BYTE * buf, int  mx, int  my, const char *filename, int level );
int  jpegs_load( BYTE *&buf, int &mx, int &my, const char *filename );

Параметр качества (level) сжатия - целое число лежащее в пределах от 1 до 100. Число 100 соответствует максимальному качеству, 1 - наименьшему.
Качество 0.60 соответствует стандарту качества ключевых кадров "DVD-видео". В целом изображение очень хорошее, но при внимательном взгляде можно заметить погрешности.
Качество 0.80 вполне достаточно почти всегда. Погрешности можно заметить лишь около резких перепадов цветов и при очень внимательном взгляде.
Если вы собираететь в дальнейшем обрабатывать изображения, есть смысл взять большее качество.

Функции служат для записи RGB-буфера в jpeg-файл и для чтения.

LZMA

Библиотека скомпилирована в шести вариантах. Это пришлось сделать потому, что нужны отдельные Debug- и Release-версии в режимах x86 и x64. Кроме того, оказалось, что Visual Studio 2010 и Visual Studio 2015 имеют разные форматы библиотек и не понимают друг друга.

Файл Версия Visual Studio x86/x64 Debug/Release
lzmaD8610.lib 2010 x86 Debug
lzmaR8610.lib 2010 x86 Release
lzmaD86.lib 2015 x86 Debug
lzmaR86.lib 2015 x86 Release
lzmaR64.lib 2015 x64 Debug
lzmaD64.lib 2015 x64 Release

Замечание. При компиляции библиотеки можно создавать отдельный файл базы данных программы (PDB), но есть возможность просто включить всё необходимое в lib-файл. Он получится больше по размеру, но при этом не надо заботиться о расположении pdb-файла.
Эта возможность включается в
Project → Properties → C/C++ → General → Debug Information Format → C7 Compatible.

Для включения библиотеки в свой проект вначале подключается заголовочный файл библиотеки:

#include "..\\lib\\lzmas.h"  // работа с lzma

Затем сообщаем линковщику, где найти саму библиотетку (lib-файл).
Учитывая большое количество версий, это не так просто:

#ifdef _WIN64
    #ifdef _DEBUG
        #pragma comment(lib, "../lib/lzmaD64.lib")
    #else
        #pragma comment(lib, "../lib/lzmaR64.lib")
    #endif
#else
    #if _MSC_VER ==1600 //  Visual C++ 2010
        #ifdef _DEBUG
            #pragma comment(lib, "../lib/lzmaD8610.lib")
        #else
            #pragma comment(lib, "../lib/lzmaR8610.lib")
        #endif
    #else               //  Visual C++ 2015
        #ifdef _DEBUG
            #pragma comment(lib, "../lib/lzmaD86.lib")
        #else
            #pragma comment(lib, "../lib/lzmaR86.lib")
        #endif
    #endif // #if _MSC_VER ==1600   //  Visual C++ 2010
#endif

Структура каталогов при этом предполагается такая:


  Parent\util   \*.h,*.cpp - здесь размещаются все описанные модули 
    └───\lib    \*.lib     - здесь должны лежать все *.lib -файлы

В библиотеку включены всего две функци:

// buf(size) сжать в lzma-буфер z_buf длины z_len
int  lzma_code(BYTE * buf, int  size, BYTE *&z_buf, int &z_len);

// buf(size) распаковать из lzma-буфера z_buf длины z_len
int  lzma_decode(BYTE *&buf, int &size, BYTE * z_buf, int  z_len);

Приведем небольшой пример программы.

В начале файла подключение библиотеки:

#include "..\\lib\\lzmas.h"// функции библиотеки
#ifdef _WIN64
#ifdef _DEBUG
#pragma comment(lib, "../lib/lzmaD64.lib")
#else
#pragma comment(lib, "../lib/lzmaR64.lib")
#endif
#else
#if _MSC_VER ==1600 //  Visual C++ 2010
#ifdef _DEBUG
#pragma comment(lib, "../lib/lzmaD8610.lib")
#else
#pragma comment(lib, "../lib/lzmaR8610.lib")
#endif
#else               //  Visual C++ 2015
#ifdef _DEBUG
#pragma comment(lib, "../lib/lzmaD86.lib")
#else
#pragma comment(lib, "../lib/lzmaR86.lib")
#endif
#endif // #if _MSC_VER ==1600   //  Visual C++ 2010
#endif
//----------------------

При таком подключении в свойствах проекта указывать библиотеку не требуется.

А теперь пример работы с библиотекой:

    const int N = 1000000;
    BYTE *b = new BYTE[N], *z_buf, *b2;
    int z_len, code, N2;
    for (int i = 0; i < N; i++) b[i] = 3 + i + i*i;
    printf("%3d %3d %3d %3d %3d %3d \n", b[0], b[1], b[N / 2], b[2 * N / 3], b[N - 2], b[N - 1]);
    code = h_graph_code_lzma(b, N, z_buf, z_len);   // сжимаем b в буфер z_buf
    printf("z_len = %d\n", z_len);

    code = h_graph_deco_lzma(b2, N2, z_buf, z_len); // распаковываем z_buf в b2
    printf("%3d %3d %3d %3d %3d %3d \n", b2[0], b2[1], b2[N / 2], b2[2 * N / 3], b2[N - 2], b2[N - 1]);

    delete[]b2;
    delete[]z_buf;
    delete[]b;

И результат работы:

  3   5  35  17  69 195
z_len = 489
  3   5  35  17  69 195

jpeg с матрицами

Библиотека jpgs ничего не знает про матрицы.
Модуль imatr_jpg дает интерфейс библиотеки с классами матриц:
imatr_jpg.h - заголовочный файл
imatr_jpg.cpp - реализация.

Чтение jpeg-файлов в матрицу:

int loadGrey(matr &a, const char *fname);
int loadRGB(matr &a, const char *fname);            // упакован RGB цвет в один элемент матрицы
int loadRGB(matr3 &a, const char *fname);           // прочитать в 3-матрицу
int saveGrey(matr &a, const char *fname, int q);    // сохранить с качеством q, 0 <=q <=100
int saveRGB(matr &a, const char *fname, int q);     // сохранить из упакованной матрицы
int saveRGB(matr3 &a, const char *fname, int q);    // сохранить 3-матрицу

Замечание.Во всех указанных выше фунциях можно в имени файла задать файл с расширением bmp. При этом при сохранении файла параметр q (качество) игнорируется.


К оглавлению


free counters