Как получить цвет пикселя в Avi файле?

Тема в разделе "MS Visual C++", создана пользователем ArtBerry, 30 мар 2007.

Статус темы:
Закрыта.
  1. ArtBerry

    ArtBerry Гость

    Люди добрые, помогите разаобраться в содранной программе.
    Содрал из урока. Но разобраться толком не могу. "Я ведь еще не волшебник, я только учусь...". А надо очень.
    Прошу вас откликнитесь.

    Вопрос такой: Нужно получить цвет пискеля из видео потока, открытого файла.

    Если я правильно понимаю, то поток загружен в память, но ввиде каких данных мне непонятно. Мне говорили, что можно оперировать с data, для получения цветов пикселя, но я ни как не могу понять как? Сам не понял, что написал.

    Вощем текст программы вот. А получить надо цвет пикселя.

    // avi.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"
    #include <windows.h> // Заголовочный файл Windows
    #include <vfw.h> // Заголовочный файл для "Видео для Windows"

    #using <mscorlib.dll>
    using namespace System;

    #pragma comment( lib, "vfw32.lib" ) // Искать VFW32.lib при линковке

    #ifndef CDS_FULLSCREEN // CDS_FULLSCREEN не определяется некоторыми
    #define CDS_FULLSCREEN 4 // компиляторами. Определяем эту константу
    #endif // Таким образом мы можем избежать ошибок

    AVISTREAMINFO psi; // Указатель на структуру содержащую информацию о
    PAVISTREAM pavi; // Дескриптор для открытия потока
    PGETFRAME pgf; // Указатель на объект GetFrame
    BITMAPINFOHEADER bmih; // Заголовочная информация для DrawDibDraw декодирования

    HDC hdc = CreateCompatibleDC(0); // Создание совместимого контекста устройства
    unsigned char* data = 0; // Указатель на наше измененное в размерах изображение
    char *pdata; // Указатель на данные текстуры

    void OpenAVI(LPCSTR szFile) // Вскрытие AVI файла (szFile)
    {
    AVIFileInit(); // Открывает файл

    // Открытие AVI потока
    if (AVIStreamOpenFromFile(&pavi, szFile, streamtypeVIDEO, 0, OF_READ, NULL) !=0)
    {
    // Если ошибка
    MessageBox (HWND_DESKTOP, "Failed To Open The AVI Stream", "Error", MB_OK | MB_ICONEXCLAMATION);
    }

    AVIStreamInfo(pavi, &psi, sizeof(psi)); // Записываем информацию о потоке в psi

    pgf=AVIStreamGetFrameOpen(pavi, NULL); // Создание PGETFRAME с нужными нам параметрами

    }

    void GrabAVIFrame(int frame) // Захват кадра
    {
    LPBITMAPINFOHEADER lpbi; // Содержит BitmapInfoHeader
    // Получение данных из потока
    lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pgf, frame);
    // Указатель на данные возвращенные AVIStreamGetFrame
    // (Пропуск заголовка для получения указателя на данные)
    pdata=(char *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD);
    //flipIt(data); // Перестановка красных и синих байтов
    }


    void CloseAVI(void) // Функция закрытия
    {
    DeleteObject(hBitmap); // Уничтожение устройства растра
    DrawDibClose(hdd); // Закрытие контекста DrawDib устройства
    AVIStreamGetFrameClose(pgf); // Закрытие объекта GetFrame
    AVIStreamRelease(pavi); // Завершение потока
    AVIFileExit(); // Закрытие файла
    }

    int _tmain()
    {
    OpenAVI("c:\\im20\\box.avi");
    GrabAVIFrame(1);
    CloseAVI();
    //Console::WriteLine (data[2]);
    Console::ReadLine ();
    return 0;
    }

    Спасибо.
     
  2. European

    Регистрация:
    4 сен 2006
    Сообщения:
    2.580
    Симпатии:
    0
    Ну если я правильно понял, то pdata - указатель на данные фрейма. Поле biBitCount структуры BITMAPINFOHEADER содержит количество бит, занимаемых одним пикселом. Следовательно, смещение некоторого пиксела от начала массива будет кратно значению этого поля.
     
  3. MechWarrior

    MechWarrior Гость

    Угу, фрейм возращается в виде стандартного DIB-растра (битмапа), характеристики которого хранятся в BITMAPINFOHEADER. На массив пикселов в данном коде указывает pdata. Пикселы в массиве хранятся по строкам (всего строк lpbi->biHeight), в каждой строке хранится lpbi->biWidth пикселов. Пиксел занимает lpbi->biBitCount битов. Например, если битов 24 (3 байта) - то это BGR-пиксел (по байту на синюю (B), зеленую (G), красную ® компоненту в соответствующем порядке), если 32 бита (4 байта) - то это BGRA (добавляется еще компонента A - которая реально обычно не используется).

    Т.е. работа с (неупакованными) пикселами - это то же, что работа с массивом размерности lpbi->biHeight x lpbi->biWidth и с размером элемента lpbi->biBitCount битов. Только надо учитывать то, что размер строки пикселов всегда выравнивается на 32-битную границу, т.е. размер строки в байтах всегда кратен 4. И обычно первая строка массива пикселов отрисовывается снизу, а последняя - сверху, т.е. хранятся они в обратном отрисовке порядке (хотя это зависит от знака biHeight).
     
  4. ArtBerry

    ArtBerry Гость

    Друзья, во-первых - спасибо вам за ответы.

    Только я не особо понял ваши мысли. Мне так и не понятно, как же все таки получить данные из pdata?

    MechWarrior
    "...это то же, что работа с массивом размерности lpbi->biHeight x lpbi->biWidth..." - это значит, что я могу, например, посмотреть на pdata[0][0]? А что там будет?

    Я вот что намудрил на выходных:

    //////////////////////////////////////////////////////////////
    RGBQUAD *pdata;
    pdata = (RGBQUAD *)AVIStreamGetFrame(pgf, frame); // Получение данных из потока

    for (int i=0; i<100; i++)
    {
    // Хочу посмотреть на значения синего цвета в первых 100 пикселях.
    // Я не знаю привильно ли это!

    Console::WriteLine ((*(pdata+i)).rgbBlue);

    // Но программа выводить одно и тоже, независимо от номера кадра.
    };
    //////////////////////////////////////////////////////////////

    Мне непонятно то, как пользоваться pdata. Она может быть и какого-нибудь другого типа, в программе берется LPBITMAPINFOHEADER. Это я изменил ее на RGBQUAD.

    В MSDN о фуекции AVIStreamGetFrame сказано:
    ...
    Return Values
    Returns a pointer to the frame data if successful or NULL otherwise. The frame data is returned as a packed DIB.
    ...

    В переводе на нормальный язык это означает:
    троеточие
    Возвращаемые значения
    Возвращает указатель на данные кадра, если все хорошо или "NULL" (в нормальных языках нет перевода таких слов), если все плохо.
    Данные кадра есть возвращенные, как сжатый DIB.
    троеточие




    Если интересно, то вот http://www.yagodin.narod.ru/ca.rar архив проекта. Создан в VS .NET 2003
     
  5. MechWarrior

    MechWarrior Гость

    Давно тут не появлялся, сорри. Если еще актуально - то зачем результат AVIStreamGetFrame было указывать как RGBQUAD*, если он в самом первом посте был правильный - LPBITMAPINFOHEADER? Эта функция ведь возвращает указатель на DIB-битмап. Данный битмап (DIB) состоит из заголовка (BITMAPINFOHEADER), в котором описывается формат данного битмапа (размеры, количество цветов, палитра и .п.), за которым идет массив пикселов. Соответственно, чтобы получить указатель на массив пикселов, имея указатель на заголовок - надо перескочить через этот заголовок, что и делается в первом постинге (в процедуре GrabAVIFrame).

    Получаем lpbi - указатель на заголовок, затем перескакиваем через него (его размеры lpbi->biSize, плюс к нему может быть подсоединена палитра из lpbi->biClrUsed цветов) и получаем pdata - указатель на массив пискелов. Им и надо пользоваться.

    При этом, как я писал выше, элементами данного массива не обязательно являются 32-битные пикселы RGBQUAD - хотя могут быть и такие, но в общем случае надо смотреть заголовок битмапа и использовать указанные там параметры битмапа.
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей