главная продукты downloads форум тех. поддержка

 

Главная страница
 

  www.bousoft.com

   главная страница
   новости СМИ
   ссылки
   о проекте
   добавить в Избранное
   сделать стартовой
 

   наши разработки

   shareware
   freeware
   регистрация
 

справка и FAQ   

   статьи
   книги
   FAQ: WinForms
   FAQ: GDI+
   MS Office
   web-технологии
   wap-технологии
 

   программирование

   visual basic: ActiveX
   visual basic: примеры
   .net framework
   c++
   delphi
   rapidQ
 

   наши компакт-диски

   диск BouSoft #3
   диск Windows PE

Работа с файлами формата AVI.

Часть 5. Создание новых AVI-файлов из отдельных кадров.

 

К этому моменту у Вас должна появиться отличная идея использования функций AVIFile. Последний пример показывает, как создать AVI-файл из последовательности отдельных растровых файлов (BMP). Если у Вас нет карты захвата изображения или коммерческого графического программного обеспечения, Вы можете подготовить серию картинок в стандартном Paint Brush. Просто сохраните несколько разных изображений, имеющих одинаковую ширину, высоту и глубину цвета, и вы получите то, с чем можно экспериментировать в этой программе. Также Вы можете воспользоваться утилитой, созданной нами в третьей статье цикла для создания последовательности изображений из имеющегося AVI-файла. Затем вы можете как угодно перемешать полученные кадры и использовать программу, описанную в этой статье.

 

Единственное новшество в коде этого примера - это то, что я создаю видео-поток из "исходников" (в отличие от копирования из существующего потока) и использую другой способ сохранения потока в AVI-файл (AVISave в этом примере не используется). Код этого примера должен быть понятен Вам, если вы прочли все предыдущие статьи цикла.

 

Поток может создаваться путем инициализации структуры AVI_STREAM_INFO и передачи ее в функцию AVIFileCreateStream. Когда эта функция выполнится, второй параметр будет содержать верный указатель на вновь созданный интерфейс потока:

 

' Заполняем заголовок для видео-потока
With strhdr
    .fccType = mmioStringToFOURCC("vids", 0&)         
'тип видео потока
    .fccHandler = 0&                                  
'ссылка по умолчанию
    .dwScale = 1
    .dwRate = Val(txtFPS)                             
'кадров в секунду
    .dwSuggestedBufferSize = bmp.SizeImage            
'размер одного кадра в пикселах
    Call SetRect(.rcFrame, 0, 0, bmp.Width, bmp.Height)
'
прямоугольник для потока
End With

'
проверяем ввод пользователя
If strhdr.dwRate < 1 Then strhdr.dwRate = 1
If strhdr.dwRate > 30 Then strhdr.dwRate = 30

'и создаем поток
res = AVIFileCreateStream(pfile, ps, strhdr)
If (res <> AVIERR_OK) Then GoTo error

 

Теперь, когда переменная ps указывает на поток, мы можем использовать ее для создания сжатого потока, содержащего всю необходимую информацию для записи его в файл.

 

Прежде всего, пользователь должен выбрать кодек для сжатия потока:

 

'получаем параметры сжатия от пользователя
'Внимание! Эти вызовы API требуют указателя на указатель на структуру

pOpts = VarPtr(opts)
res = AVISaveOptions(Me.hWnd, _
                            ICMF_CHOOSE_KEYFRAME Or ICMF_CHOOSE_DATARATE, _
                            1, _
                            ps, _
                            pOpts)
If res <> 1 Then 'In C TRUE = 1
    Call AVISaveOptionsFree(1, pOpts)
    GoTo error
End If

 

Затем мы передаем эту информацию вместе с самим потоком в функцию AVIMakeCompressedStream:

 

'создаем сжатый поток
res = AVIMakeCompressedStream(psCompressed, ps, opts, 0&)
If res <> AVIERR_OK Then GoTo error

 

Когда эта функция завершается успешно, переменная psCompressed указывает на интерфейс сжатого потока, который может записывать сжатый видео-поток в формате, заданном структурами AVI_STREAM_INFO и AVI_COMPRESS_OPTIONS. Все, что мы должны сделать далее - установить параметры DIB? которые должны быть переданы в поток. Это требует использования структуры BITMAPINFO, что означает переменную изменяющегося размера, которую достаточно трудно использовать в VB. К счастью, здесь нам поможет класс cDIB. В этом классе имеется функция, принимающая файл с диска. Ранее я вызывал эту функцию для считывания первого кадра потока из файла для того, чтобы получить размер буфера для структуры AVI_STREAM_INFO:

 

'получаем первый кадр потока из файла
Set bmp = New cDIB
lstDIBList.ListIndex = 0
If bmp.CreateFromFile(lstDIBList.Text) <> True Then
    MsgBox "Could not load first bitmap file in list!", vbExclamation, App.title
    GoTo error
End If

 

Сейчас мы можем использовать ту же структуру для установки формата видео-потока. Прежде всего нам необходимо записать всю необходимую информацию в структуру BITMAPINFO:

 

With BI
    .biBitCount = bmp.BitCount
    .biClrImportant = bmp.ClrImportant
    .biClrUsed = bmp.ClrUsed
    .biCompression = bmp.Compression
    .biHeight = bmp.Height
    .biWidth = bmp.Width
    .biPlanes = bmp.Planes
    .biSize = bmp.SizeInfoHeader
    .biSizeImage = bmp.SizeImage
    .biXPelsPerMeter = bmp.XPPM
    .biYPelsPerMeter = bmp.YPPM
End With

 

И затем передаем эту структуру вместе с потоком в функцию AVIStreamSetFormat:

 

'устанавливаем формат сжатого потока
res = AVIStreamSetFormat(psCompressed, 0, ByVal bmp.PointerToBitmapInfo, bmp.SizeBitmapInfo)
If (res <> AVIERR_OK) Then GoTo error

 

Если эта функция завершается успешно, то сжатый поток полностью инициализирован и готов принять несколько DIB для записи. Вы сделаете это путем передачи этого потока и позиции, с которой нужно начать запись, в функцию AVIStreamWrite. Обратите внимание, что здесь вновь используется класс cDIB, так как он содержит метод, который возвращает прямой указатель на биты, которые нужно передать в функцию:

 

'Записываем каждый кадр видео
For i = 0 To lstDIBList.ListCount - 1
    lstDIBList.ListIndex = i
    bmp.CreateFromFile (lstDIBList.Text)
'считываем растр
    res = AVIStreamWrite(psCompressed, _
                                    i, _
                                    1, _
                                    bmp.PointerToBits, _
                                    bmp.SizeImage, _
                                    AVIIF_KEYFRAME, _
                                    ByVal 0&, _
                                    ByVal 0&)
    If res <> AVIERR_OK Then GoTo error
    'Show user feedback
    imgPreview.Picture = LoadPicture(lstDIBList.Text)
    imgPreview.Refresh
    lblStatus = "Frame number " & i & " saved"
    lblStatus.Refresh
Next
lblStatus = "Finished!"

 

Как только этот цикл завершит запись изображений, Вам нужно освободить все ресурсы и файловые указатели. Файл, созданный Вами в начале этой процедуры, теперь содержит обычный видео-поток, и его можно воспроизвести в Windows Media Player или в другом проигрывателе. Чтобы лучше разобраться в работе примера, изучите код программы. Когда Вы запустите этот пример, вы должны будете выбрать несколько файлов изображений, один за другим, и указать частоту кадров от 1 до 30 кадров в секунду. Полный текст примера можно скачать здесь.

 

На этом цикл статей, посвященных обработке AVI-файлов, завершен. Как обычно, со всеми комментариями и вопросами вы можете обращаться по адресу: bousoft@mail.ru.

 

   Перевод и редактура: Буторкин Сергей  Источник: http://www.shrinkwrapvb.com

 

e-mail:

 

bousoft@mail.ru