Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > С++ и Jpeg (или BMP) в Windows


Автор: Zhbert 29.8.2011, 13:35
Приветствую всех. Помогите разобраться с 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? Перегуглил уже половину инета, что-то ничерта не получается.

Специалисты, вся надежда на вас!

Автор: BorisVorontsov 29.8.2011, 18:40
Цитата(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

Автор: Zhbert 30.8.2011, 08:27
Спасибо. *ушел разбираться*

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)