Medical Imaging Interaction Toolkit  2018.4.99-18ddd2ed
Medical Imaging Interaction Toolkit
mitkMovieGeneratorWin32.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 #include <GL/gl.h>
15 
17 {
18 }
19 
20 void mitk::MovieGeneratorWin32::SetFileName(const char *fileName)
21 {
22  m_sFile = _T(fileName);
23  if (_tcsstr((char *)m_sFile, _T("avi")) == nullptr)
24  m_sFile += _T( ".avi" );
25 }
26 
28 {
29  m_width = m_renderer->GetRenderWindow()->GetSize()[0]; // changed from glGetIntegerv( GL_VIEWPORT, viewport );
30  m_height = m_renderer->GetRenderWindow()->GetSize()[1]; // due to sometimes strange dimensions
31 
32  m_width -= 10; // remove colored boarders around renderwindows
33  m_height -= 10;
34 
35  m_width -= m_width % 4; // some video codecs have prerequisites to the image dimensions
36  m_height -= m_height % 4;
37 
38  BITMAPINFOHEADER bih;
39  bih.biSize = sizeof(BITMAPINFOHEADER);
40  bih.biWidth = m_width;
41  bih.biHeight = m_height;
42  bih.biPlanes = 1;
43  int imgSize = 3 /* BRG*/ * bih.biWidth * bih.biHeight;
44  bih.biBitCount = 24;
45  bih.biCompression = BI_RGB;
46  bih.biSizeImage = imgSize;
47  bih.biClrUsed = 0;
48  bih.biClrImportant = 0;
49 
50  // ASSERT(bih.biWidth%4==0);
51  // ASSERT(bih.biHeight%4==0);
52 
53  // copying bitmap info structure.
54  memcpy(&m_bih, &bih, sizeof(BITMAPINFOHEADER));
55 }
56 
58 {
60 
61  AVISTREAMINFO strHdr; // information for a single stream
62  AVICOMPRESSOPTIONS opts;
63  AVICOMPRESSOPTIONS FAR *aopts[1] = {&opts};
64 
65  TCHAR szBuffer[1024];
66  HRESULT hr;
67 
68  m_sError = _T("Ok");
69 
70  // Step 0 : Let's make sure we are running on 1.1
71  DWORD wVer = HIWORD(VideoForWindowsVersion());
72  if (wVer < 0x010a)
73  {
74  // oops, we are too old, blow out of here
75  m_sError = _T("Version of Video for Windows too old. Come on, join the 21th century!");
76  return false;
77  }
78 
79  // Step 1 : initialize AVI engine
80  AVIFileInit();
81 
82  // Step 2 : Open the movie file for writing....
83  hr = AVIFileOpen(&m_pAVIFile, // Address to contain the new file interface pointer
84  (LPCTSTR)m_sFile, // Null-terminated string containing the name of the file to open
85  OF_WRITE | OF_CREATE, // Access mode to use when opening the file.
86  nullptr); // use handler determined from file extension.
87  // Name your file .avi -> very important
88 
89  if (hr != AVIERR_OK)
90  {
91  _tprintf(szBuffer, _T("AVI Engine failed to initialize. Check filename %s."), m_sFile);
92  m_sError = szBuffer;
93  // Check it succeded.
94  switch (hr)
95  {
96  case AVIERR_BADFORMAT:
97  m_sError += _T("The file couldn't be read, indicating a corrupt file or an unrecognized format.");
98  break;
99  case AVIERR_MEMORY:
100  m_sError += _T("The file could not be opened because of insufficient memory.");
101  break;
102  case AVIERR_FILEREAD:
103  m_sError += _T("A disk error occurred while reading the file.");
104  break;
105  case AVIERR_FILEOPEN:
106  m_sError += _T("A disk error occurred while opening the file.");
107  break;
108  case REGDB_E_CLASSNOTREG:
109  m_sError += _T("According to the registry, the type of file specified in AVIFileOpen does not have a handler ")
110  _T("to process it");
111  break;
112  }
113 
114  return false;
115  }
116 
117  // Fill in the header for the video stream....
118  memset(&strHdr, 0, sizeof(strHdr));
119  strHdr.fccType = streamtypeVIDEO; // video stream type
120  strHdr.fccHandler = 0;
121  strHdr.dwScale = 1; // should be one for video
122  strHdr.dwRate = static_cast<DWORD>(m_FrameRate); // fps
123  strHdr.dwSuggestedBufferSize = m_bih.biSizeImage; // Recommended buffer size, in bytes, for the stream.
124  SetRect(&strHdr.rcFrame,
125  0,
126  0, // rectangle for stream
127  (int)m_bih.biWidth,
128  (int)m_bih.biHeight);
129 
130  // Step 3 : Create the stream;
131  hr = AVIFileCreateStream(m_pAVIFile, // file pointer
132  &m_pStream, // returned stream pointer
133  &strHdr); // stream header
134 
135  // Check it succeded.
136  if (hr != AVIERR_OK)
137  {
138  m_sError = _T("AVI Stream creation failed. Check Bitmap info.");
139  if (hr == AVIERR_READONLY)
140  {
141  m_sError += _T(" Read only file.");
142  }
143  return false;
144  }
145 
146  // Step 4: Get codec and infos about codec
147  memset(&opts, 0, sizeof(opts));
148 
149  // predefine MS-CRAM as standard codec
150  opts.fccType = streamtypeVIDEO;
151  // creates a video with minor quality! Use different codec (must be installed on local machine) to generate movies
152  // with higher quality
153  opts.fccHandler = mmioFOURCC('M', 'S', 'V', 'C');
154  opts.dwQuality = 90000; // means 90% quality; dwQuality goes from [0...10000]
155 
156 // Poping codec dialog
157 // GUI Codec selection does not work in a vs 2005 compiled mitk, since we do not pass a hwnd as first parameter
158 // of AVISaveOptions
159 #if !(_MSC_VER >= 1400)
160 
161  if (!AVISaveOptions(nullptr, 0, 1, &m_pStream, (LPAVICOMPRESSOPTIONS FAR *)&aopts))
162  {
163  AVISaveOptionsFree(1, (LPAVICOMPRESSOPTIONS FAR *)&aopts);
164  // return false;
165  }
166 
167 #endif
168 
169  // Step 5: Create a compressed stream using codec options.
170  hr = AVIMakeCompressedStream(&m_pStreamCompressed, m_pStream, &opts, nullptr);
171 
172  if (hr != AVIERR_OK)
173  {
174  m_sError = _T("AVI Compressed Stream creation failed.");
175 
176  switch (hr)
177  {
178  case AVIERR_NOCOMPRESSOR:
179  m_sError += _T(" A suitable compressor cannot be found.");
180  break;
181  case AVIERR_MEMORY:
182  m_sError += _T(" There is not enough memory to complete the operation.");
183  break;
184  case AVIERR_UNSUPPORTED:
185  m_sError += _T("Compression is not supported for this type of data. This error might be returned if you try ")
186  _T("to compress data that is not audio or video.");
187  break;
188  }
189 
190  return false;
191  }
192 
193  // releasing memory allocated by AVISaveOptionFree
194  hr = AVISaveOptionsFree(1, (LPAVICOMPRESSOPTIONS FAR *)&aopts);
195  if (hr != AVIERR_OK)
196  {
197  m_sError = _T("Error releasing memory");
198  return false;
199  }
200 
201  // Step 6 : sets the format of a stream at the specified position
202  hr = AVIStreamSetFormat(m_pStreamCompressed,
203  0, // position
204  &m_bih, // stream format
205  m_bih.biSize + // format size
206  m_bih.biClrUsed * sizeof(RGBQUAD));
207 
208  if (hr != AVIERR_OK)
209  {
210  m_sError = _T("AVI Compressed Stream format setting failed.");
211  return false;
212  }
213 
214  // Step 6 : Initialize step counter
215  m_lFrame = 0;
216 
217  return true;
218 }
219 
221 {
222  HRESULT hr = AVIStreamWrite(m_pStreamCompressed, // stream pointer
223  m_lFrame, // time of this frame
224  1, // number to write
225  (BYTE *)data, // image buffer
226  m_bih.biSizeImage, // size of this frame
227  AVIIF_KEYFRAME, // flags....
228  nullptr,
229  nullptr);
230  // updating frame counter
231  m_lFrame++;
232 
233  if (hr == AVIERR_OK)
234  return true;
235  else
236  return false;
237 }
238 
240 {
241  if (m_pStream)
242  {
243  AVIStreamRelease(m_pStream);
244  m_pStream = nullptr;
245  }
246  if (m_pStreamCompressed)
247  {
248  AVIStreamRelease(m_pStreamCompressed);
249  m_pStreamCompressed = nullptr;
250  }
251  if (m_pAVIFile)
252  {
253  AVIFileRelease(m_pAVIFile);
254  m_pAVIFile = nullptr;
255  }
256  // Close engine
257  AVIFileExit();
258  return true;
259 }
virtual void SetFileName(const char *fileName)
filename under which movie is saved
virtual bool TerminateGenerator()
called after the last frame is added
void InitBitmapHeader()
reads out size of current OpenGL context and stores it
virtual bool AddFrame(void *data)
used to add a frame
BITMAPINFOHEADER m_bih
structure contains information for a single stream
_bstr_t m_sError
last error string
virtual bool InitGenerator()
called directly before the first frame is added
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
_bstr_t m_sFile
name of output file
int m_width
InitGenerator() stores movie size in those variables.
BaseRenderer * m_renderer
stores the uses renderer