Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> С++ и Jpeg (или BMP) в Windows, Как грамотно работать с изображениями? 
:(
    Опции темы
Zhbert
Дата 29.8.2011, 13:35 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 2.12.2010

Репутация: нет
Всего: нет



Приветствую всех. Помогите разобраться с Jpeg и BMP в Windows.

На работе пришлось заниматься разработкой приложения, работающего с профессиональной технической видеокамерой нашенского производства. К камере прилагается динамическаябиблиотека *.dll и пара заголовочных файлов. Собственно, изображение с камеры я получил, но отдает она его в специфичном формате RAW, а по идее надо сделать из всего этого видео. Как я решил делать? Так как видео не обязательно должно быть в реалтайме, а просто записаться, я решил консольным демоном (да да, я гентушник, мне это роднее) надергать с камеры 24 кадра в секенду, а потом сжать их менкодером в *.avi.  И вот в этом-то моменте у меня и возникла проблема.

Итак, что я имею? Имею массив пикселей, представляющий собой мое изображение. Код:

Код

DWORD dwRealSize;
    DWORD dwResult = sdu_read_data(g_pSDUCameraDevice, BufImg, bufsize, &dwRealSize);    // чтение данных из камеры

    if ((dwResult != SDU_SUCCESS) || (dwRealSize != bufsize)) {   //Проверка на исключения
        cout << endl << "Data read failure , error code = " << dwResult;
        sdu_close_interface (g_pSDUCameraDevice); //Если фэйл - закрываем интерфейс и чистим память
        delete[] BufImg;
        delete[] bufparams;
        exit(-1);
    }

    int OutSize;    // размер результирующего изображения
    char OutName[32]; // массив для названия файла

    //Вот, а теперь приступаем к самой мистической и непонятной части программы, остро завязанной на
    //астральные связи с потусторонним миром и телепатические связи с инопланетянами - мы начинаем
    //декодировать полученный массив в понятный формат, а также пытаться собрать из пачек этого всего
    //видео, чтоб показать потом юзерам. Смотреть код аккуратно, возможны трэш, угар и содомия!

    // обработка изображения - 8 бит ч/б
    if (!color_id && !RealEncoding) {
        OutSize = Real_h_size * Real_v_size;
        BufOut8 = new UCHAR[OutSize];
        Gamma8_BW = new UCHAR[256];        // массив гамма-коррекции

        if (BufOut8 && Gamma8_BW)
            sdu_make_gamma_lut_8to8(Gamma8_BW, GAMMA_BW);    // формирование массива гамма-коррекции

        //  выполнение гамма-коррекции
        sdu_bw_convert_8to8(BufImg, BufOut8, Gamma8_BW, Real_h_size, Real_v_size);

        // here is an example of using RWW stuff (<ccd> format actually is <rww> with just one frame)
        strcpy(OutName,"BW_image_8bpp.ccd");    // имя файла для сохранения
        // caller is responsible to allocate and then destroy the Cam_RWWStruct
        Cam_RWWStruct * pCam_RWWStruct = new Cam_RWWStruct;
        if (pCam_RWWStruct) {
            cout << '\n' << "Saving as ccd:" << OutName << '\n';
            memset(pCam_RWWStruct, 0, sizeof(Cam_RWWStruct));
            pCam_RWWStruct->m_nDataOffset = sizeof(Cam_RWWStruct); // == 1024
            pCam_RWWStruct->m_nSizeV = Real_v_size;
            pCam_RWWStruct->m_nSizeH = Real_h_size;
            pCam_RWWStruct->m_nEncoding = RealEncoding;
            pCam_RWWStruct->m_nBinning = Real_Binning;
            pCam_RWWStruct->m_nTrigmode = TrigMode;
            pCam_RWWStruct->m_nExp = Real_Exp;
            pCam_RWWStruct->m_nGain = Real_Gain;
            pCam_RWWStruct->m_nGainR = Real_R_offset;
            pCam_RWWStruct->m_nGainG = Real_G_offset;
            pCam_RWWStruct->m_nMax_Gain = Real_Gain + 100;
            pCam_RWWStruct->m_nColor = color_id;
            pCam_RWWStruct->m_nFrameSize = OutSize;
            pCam_RWWStruct->m_nScale = 2; // 1:1 scale
            pCam_RWWStruct->m_nGammaR = 1000; // float values are stored in int multiplied by 1000
            pCam_RWWStruct->m_nGammaG = 1000;
            pCam_RWWStruct->m_nGammaB = 1000;
            pCam_RWWStruct->m_nGammaGray = 1000;
            pCam_RWWStruct->m_nBalanceCoeffR = 1000;
            pCam_RWWStruct->m_nBalanceCoeffG = 1000;
            pCam_RWWStruct->m_nBalanceCoeffB = 1000;

            // open rww file for writing
            dwResult = sdu_open_file_rww(OutName, pCam_RWWStruct, 1, 0);
            if (dwResult == SDU_SUCCESS) {
                dwResult = sdu_file_rww_write_frame(pCam_RWWStruct, dwRealSize, BufImg);
                if (dwResult == SDU_SUCCESS)    
                    cout << " ---> Success"  << '\n';
                else    
                    cout << " ---> Failure"  << '\n';
                sdu_close_file_rww(pCam_RWWStruct);
            }
            delete pCam_RWWStruct;
        }

        strcpy(OutName, "BW_image_8bpp.raw");    // имя файла для сохранения
    }
    else if (!color_id && RealEncoding == 1) {    // обработка изображения - 12 бит ч/б 
        OutSize = Real_h_size * Real_v_size;
        BufOut16 = new USHORT [OutSize];
        Gamma16_BW = new USHORT[4096];    // массив гамма-коррекции

        if (BufOut16 && Gamma8_BW)
            sdu_make_gamma_lut_12to16(Gamma16_BW, GAMMA_BW);    // формирование массива гамма-коррекции

        // распаковка изображения из формата камеры в 16 bpp, выполнение гамма-коррекции
        sdu_bw_convert_12to16( BufImg, BufOut16, NULL/*Gamma16_BW*/, Real_h_size, Real_v_size);

        strcpy(OutName,"BW_image_16bpp.raw");    // имя файла для сохранения
    }
    else if (color_id && !RealEncoding) { // обработка изображения - 8 бит цветн.
        OutSize = Real_h_size * Real_v_size * 3;        // по 3 байта/пиксел
        BufOut8 = new UCHAR [OutSize];
        Gamma8_R = new UCHAR [256];    // массивы гамма-коррекции для каждого из цветов
        Gamma8_G = new UCHAR [256];
        Gamma8_B = new UCHAR [256];

        if (Gamma8_R)
            sdu_make_gamma_lut_8to8(Gamma8_R, GAMMA_R);        // формирование массивов гамма-коррекции
        if (Gamma8_G)
            sdu_make_gamma_lut_8to8(Gamma8_G, GAMMA_G);
        if (Gamma8_B)
            sdu_make_gamma_lut_8to8(Gamma8_B, GAMMA_B);

        // декодирование цвета BAYER->RGB, выполнение гамма-коррекции 
        // последовательность цветов в результате - RGB
        // метод декодирования - HQ
        sdu_demosaic_8to8(BufImg, BufOut8, Gamma8_R, Gamma8_G, Gamma8_B, Real_h_size
                , Real_v_size, SDU_COLORSEQ_RGB, color_id, SDU_METHOD_HQ);

        strcpy(OutName,"Color_image_8bpp.raw");    // имя файла для сохранения
    }
    else if (color_id && RealEncoding == 1) {    // обработка изображения - 12 бит цветн.
        OutSize = Real_h_size * Real_v_size * 3;        // по 3 слова/пиксел
        BufOut16 = new USHORT [OutSize];
        Gamma16_R = new USHORT[4096];        // массивы гамма-коррекции для каждого из цветов
        Gamma16_G = new USHORT[4096];
        Gamma16_B = new USHORT[4096];

        if (Gamma16_R)
            sdu_make_gamma_lut_12to16(Gamma16_R, GAMMA_R);        // формирование массивов гамма-коррекции
        if (Gamma16_G)
            sdu_make_gamma_lut_12to16(Gamma16_G, GAMMA_G);
        if (Gamma16_B)
            sdu_make_gamma_lut_12to16(Gamma16_B, GAMMA_B);

        // распаковка изображения из формата камеры в 16 bpp, декодирование цвета BAYER->RGB,
        // выполнение гамма-коррекции 
        // последовательность цветов в результате - RGB
        // метод декодирования - HQ
        sdu_demosaic_12to16(BufImg, BufOut16, Gamma16_R, Gamma16_G, Gamma16_B, Real_h_size
                , Real_v_size, SDU_COLORSEQ_RGB, color_id, SDU_METHOD_HQ);
        strcpy(OutName,"Color_image_16bpp.raw");    // имя файла для сохранения
    }

    FILE * out = 0;
    if (!(out = fopen(OutName,"w+b"))) {        // выходной файл
        printf("Can't open output file\n");
        sdu_close_interface(g_pSDUCameraDevice);
        delete [] bufparams;
        if (BufImg)
            delete [] BufImg, BufImg = 0;
        if (BufOut8)
            delete [] BufOut8, BufOut8 = 0;
        if (BufOut16)
            delete [] BufOut16, BufOut16 = 0;
        if (BufOut16)
            delete [] BufOut16, BufOut16 = 0;
        if (Gamma8_G)
            delete [] Gamma8_G, Gamma8_G = 0;
        if (Gamma8_B)
            delete [] Gamma8_B, Gamma8_B = 0;
        if (Gamma8_BW)
            delete [] Gamma8_BW, Gamma8_BW = 0;
        if (Gamma16_R)
            delete [] Gamma16_R, Gamma16_R = 0;
        if (Gamma16_G)
            delete [] Gamma16_G, Gamma16_G = 0;
        if (Gamma16_B)
            delete [] Gamma16_B, Gamma16_B = 0;
        if (Gamma16_BW)
            delete [] Gamma16_BW, Gamma16_BW = 0;
        exit(-1);
    } 
    if (RealEncoding)
        fwrite(BufOut16, 2, OutSize, out);    // сохранение результата в формате 16 bpp
    else
        fwrite(BufOut8, 1, OutSize, out);    // сохранение результата в формате 8 bpp


Как видно из кода, изображение хранится в формате массива точек, видимо, в переменной BufOut8, из которой оно и пишется напрямую в файл RAW. Вопрос - каким образом программно переконвертить его в BMP или Jpeg? Перегуглил уже половину инета, что-то ничерта не получается.

Специалисты, вся надежда на вас!
PM MAIL   Вверх
BorisVorontsov
Дата 29.8.2011, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Thinker
**


Профиль
Группа: Комодератор
Сообщений: 714
Регистрация: 3.11.2005
Где: Молдавия, г. Киши нёв

Репутация: 4
Всего: 10



Цитата(Zhbert @  29.8.2011,  13:35 Найти цитируемый пост)
Вопрос - каким образом программно переконвертить его в BMP или Jpeg?

Формат BMP для 16, 24 и 32-битных изображений представляет собой все тот же массив пикселей, предваряемый заголовками BITMAPINFOHEADER и BITMAPFILEHEADER. А у тебя на выходе записывается 16-битный растр BufOut16. Полная спецификация формата описана в MSDN: http://msdn.microsoft.com/en-us/library/dd162461.aspx

Пример сохранения в Windows Bitmap: http://forum.sources.ru/index.php?showtopic=208226


--------------------
[code=cpp]
const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;
[/code]
PM MAIL ICQ GTalk   Вверх
Zhbert
Дата 30.8.2011, 08:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 2.12.2010

Репутация: нет
Всего: нет



Спасибо. *ушел разбираться*
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0881 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.