]> Creatis software - clitk.git/commitdiff
Added animated GIF video snapshot (CLITK_EXPERIMENTAL yet)
authorSimon Rit <simon.rit@creatis.insa-lyon.fr>
Thu, 22 Mar 2012 17:56:50 +0000 (18:56 +0100)
committerSimon Rit <simon.rit@creatis.insa-lyon.fr>
Thu, 22 Mar 2012 21:52:09 +0000 (22:52 +0100)
vv/CMakeLists.txt
vv/vvAnimatedGIFWriter.cxx [new file with mode: 0644]
vv/vvAnimatedGIFWriter.h [new file with mode: 0644]
vv/vvMainWindow.cxx

index ccfe267078ef37e5d43e3f994fbd6c715dd86b70..6b0af0747dd31698426d9de01be68d32fc06098e 100644 (file)
@@ -204,9 +204,19 @@ endforeach(tool)
 #on them)
 SET(foundationLibraries clitkCommon ${ITK_LIBRARIES} QVTK vtkHybrid)
 
+#=========================================================
+# Use CxImage to create animated gifs
+IF(CLITK_EXPERIMENTAL)
+  SET(vvCxImage clitkCxImage)
+  SET(vv_SRCS ${vv_SRCS} vvAnimatedGIFWriter.cxx)
+  INCLUDE_DIRECTORIES(${CLITK_SOURCE_DIR}/utilities/CxImage)
+  ADD_SUBDIRECTORY(${CLITK_SOURCE_DIR}/utilities/CxImage ${PROJECT_BINARY_DIR}/utilities/CxImage)
+ENDIF(CLITK_EXPERIMENTAL)
+#=========================================================
+
 #=========================================================
 #Create binary and libs for tests
-SET(vvExternalLibs ${QT_QTNETWORK_LIBRARY} clitkSegmentationGgoLib clitkDicomRTStruct ${toolLibs} ${foundationLibraries})
+SET(vvExternalLibs ${QT_QTNETWORK_LIBRARY} clitkSegmentationGgoLib clitkDicomRTStruct ${toolLibs} ${foundationLibraries} ${vvCxImage})
 # QtNetwork is required by vvRegisterForm
 
 ADD_LIBRARY(vvLib ${vv_SRCS} ${vv_UI_CXX})
diff --git a/vv/vvAnimatedGIFWriter.cxx b/vv/vvAnimatedGIFWriter.cxx
new file mode 100644 (file)
index 0000000..75352ac
--- /dev/null
@@ -0,0 +1,100 @@
+#include "vvAnimatedGIFWriter.h"
+#include "clitkDD.h"
+
+#include "ximagif.h"
+
+#include <vtkImageData.h>
+#include <vtkImageQuantizeRGBToIndex.h>
+#include <vtkImageAppend.h>
+#include <vtkImageCast.h>
+#include <vtkObjectFactory.h>
+#include <vtkLookupTable.h>
+
+//---------------------------------------------------------------------------
+vtkStandardNewMacro(vvAnimatedGIFWriter);
+
+//---------------------------------------------------------------------------
+vvAnimatedGIFWriter::vvAnimatedGIFWriter()
+{
+  Rate = 5;
+  Loops = 0;
+}
+
+//---------------------------------------------------------------------------
+vvAnimatedGIFWriter::~vvAnimatedGIFWriter()
+{
+}
+
+//---------------------------------------------------------------------------
+void vvAnimatedGIFWriter::Start()
+{
+  // Create one volume with all slices
+  RGBvolume = vtkSmartPointer<vtkImageAppend>::New();
+  RGBvolume->SetAppendAxis(2);
+  RGBslices.clear();
+}
+
+//---------------------------------------------------------------------------
+void vvAnimatedGIFWriter::Write()
+{
+  // get the data
+  this->GetInput()->UpdateInformation();
+  int *wExtent = this->GetInput()->GetWholeExtent();
+  this->GetInput()->SetUpdateExtent(wExtent);
+  this->GetInput()->Update();
+
+  RGBslices.push_back( vtkSmartPointer<vtkImageData>::New() );
+  RGBslices.back()->ShallowCopy(this->GetInput());
+  RGBvolume->AddInput(RGBslices.back());
+}
+
+//---------------------------------------------------------------------------
+void vvAnimatedGIFWriter::End()
+{
+  RGBvolume->Update();
+
+  // Quantize to 8 bit colors
+  vtkSmartPointer<vtkImageQuantizeRGBToIndex> quant = vtkSmartPointer<vtkImageQuantizeRGBToIndex>::New();
+  quant->SetNumberOfColors(256);
+  quant->SetInput(RGBvolume->GetOutput());
+  quant->Update();
+
+  // Convert to 8 bit image
+  vtkSmartPointer<vtkImageCast> cast =  vtkSmartPointer<vtkImageCast>::New();
+  cast->SetInput( quant->GetOutput() );
+  cast->SetOutputScalarTypeToUnsignedChar();
+  cast->Update();
+
+  // Create a stack of CxImages
+  DWORD width = cast->GetOutput()->GetExtent()[1]-cast->GetOutput()->GetExtent()[0]+1;
+  DWORD height = cast->GetOutput()->GetExtent()[3]-cast->GetOutput()->GetExtent()[2]+1;
+  std::vector<CxImage*> cximages( RGBslices.size() );
+  for(unsigned int i=0; i<RGBslices.size(); i++) {
+    cximages[i] = new CxImage;
+    cximages[i]->CreateFromArray((BYTE *)cast->GetOutput()->GetScalarPointer(0,0,i),
+                                 width, height, 8, width, false);
+    cximages[i]->SetFrameDelay(100/Rate);
+    cximages[i]->SetPalette((RGBQUAD*)(quant->GetLookupTable()->GetPointer(0)));
+  }
+
+  // Create gif
+  FILE * pFile;
+  pFile = fopen (this->FileName, "wb");
+  CxImageGIF cximagegif;
+  cximagegif.SetLoops(Loops);
+  bool result = cximagegif.Encode(pFile,&(cximages[0]), (int)RGBslices.size(), true);
+
+  // Cleanup
+  fclose(pFile);
+  for(unsigned int i=0; i<RGBslices.size(); i++)
+    delete cximages[i];
+  if(!result) {
+    vtkErrorMacro("Error in CxImage: " << cximagegif.GetLastError() );
+  }
+}
+
+//---------------------------------------------------------------------------
+void vvAnimatedGIFWriter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os, indent);
+}
diff --git a/vv/vvAnimatedGIFWriter.h b/vv/vvAnimatedGIFWriter.h
new file mode 100644 (file)
index 0000000..8242779
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __vvAnimatedGIFWriter_h
+#define __vvAnimatedGIFWriter_h
+
+#include <vector>
+
+#include <vtkGenericMovieWriter.h>
+#include <vtkSmartPointer.h>
+
+class vtkImageAppend;
+
+class VTK_IO_EXPORT vvAnimatedGIFWriter : public vtkGenericMovieWriter
+{
+public:
+  static vvAnimatedGIFWriter *New();
+  vtkTypeMacro(vvAnimatedGIFWriter,vtkGenericMovieWriter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // These methods start writing an Movie file, write a frame to the file
+  // and then end the writing process.
+  void Start();
+  void Write();
+  void End();
+
+  // Description:
+  // Set/Get the frame rate, in frame/s.
+  vtkSetClampMacro(Rate, int, 1, 5000);
+  vtkGetMacro(Rate, int);
+
+  // Description:
+  // Set/Get the number of loops,  0 means infinite
+  vtkSetClampMacro(Loops, int, 0, 5000);
+  vtkGetMacro(Loops, int);
+
+protected:
+  vvAnimatedGIFWriter();
+  ~vvAnimatedGIFWriter();
+
+  int Rate;
+  int Loops;
+
+  vtkSmartPointer<vtkImageAppend> RGBvolume;
+  std::vector< vtkSmartPointer<vtkImageData> > RGBslices;
+
+private:
+  vvAnimatedGIFWriter(const vvAnimatedGIFWriter&); // Not implemented
+  void operator=(const vvAnimatedGIFWriter&); // Not implemented
+};
+
+#endif
index 986d7b93cfd76cbf727c716d5966250ae5da6a4d..9dbd407e4168aee728bc700f638ca0695bc0bd42 100644 (file)
@@ -71,6 +71,9 @@
 #include <vtkPNGWriter.h>
 #include <vtkJPEGWriter.h>
 #include <vtkGenericMovieWriter.h>
+#ifdef CLITK_EXPERIMENTAL
+#  include <vvAnimatedGIFWriter.h>
+#endif
 #ifdef VTK_USE_VIDEO_FOR_WINDOWS
 #  include <vtkAVIWriter.h>
 #endif
@@ -2735,11 +2738,14 @@ void vvMainWindow::SaveScreenshot(QVTKWidget *widget)
   Extensions += "Images( *.bmp);;";
   Extensions += "Images( *.tif);;";
   Extensions += "Images( *.ppm)";
-#ifdef VTK_USE_FFMPEG_ENCODER
-  Extensions += "Images( *.avi)";
+#if defined(VTK_USE_FFMPEG_ENCODER) || defined(VTK_USE_VIDEO_FOR_WINDOWS)
+  Extensions += ";;Video( *.avi)";
 #endif
 #ifdef VTK_USE_MPEG2_ENCODER
-  Extensions += "Images( *.mpg)";
+  Extensions += ";;Video( *.mpg)";
+#endif
+#ifdef CLITK_EXPERIMENTAL
+  Extensions += ";;Video( *.gif)";
 #endif
 
   int smIndex=GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
@@ -2779,6 +2785,25 @@ void vvMainWindow::SaveScreenshot(QVTKWidget *widget)
 
     // Video
     vtkGenericMovieWriter *vidwriter = NULL;
+#ifdef CLITK_EXPERIMENTAL
+    if (!strcmp(ext, ".gif")) {
+      vvAnimatedGIFWriter *gif = vvAnimatedGIFWriter::New();
+      vidwriter = gif;
+
+      // FPS
+      bool ok;
+      int fps = QInputDialog::getInt(this, tr("Number of frames per second"),
+                                     tr("FPS:"), 5, 0, 1000, 1, &ok);
+      if(ok)
+        gif->SetRate(fps);
+
+      // Loops
+      int loops = QInputDialog::getInt(this, tr("Loops"),
+                                     tr("Number of loops (0 means infinite):"), 0, 0, 1000000000, 1, &ok);
+      if(ok)
+        gif->SetLoops(loops);
+    }
+#endif
 #ifdef VTK_USE_VIDEO_FOR_WINDOWS
     if (!strcmp(ext, ".avi")) {
       vtkAVIWriter *mpg = vtkAVIWriter::New();