#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})
--- /dev/null
+#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);
+}
--- /dev/null
+#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
#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
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]);
// 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();