]> Creatis software - clitk.git/blob - vv/vvAnimatedGIFWriter.cxx
Debug RTStruct conversion with empty struc
[clitk.git] / vv / vvAnimatedGIFWriter.cxx
1 #include "vvAnimatedGIFWriter.h"
2 #include "clitkDD.h"
3
4 #include <vtkVersion.h>
5 #include <vtkStreamingDemandDrivenPipeline.h>
6 #include <vtkInformation.h>
7 #include <vtkImageData.h>
8 #include <vtkImageQuantizeRGBToIndex.h>
9 #include <vtkImageAppend.h>
10 #include <vtkImageCast.h>
11 #include <vtkObjectFactory.h>
12 #include <vtkLookupTable.h>
13
14 #include "ximagif.h"
15
16 //---------------------------------------------------------------------------
17 vtkStandardNewMacro(vvAnimatedGIFWriter);
18
19 //---------------------------------------------------------------------------
20 vvAnimatedGIFWriter::vvAnimatedGIFWriter()
21 {
22   Rate = 5;
23   Loops = 0;
24   Dither = false;
25 }
26
27 //---------------------------------------------------------------------------
28 vvAnimatedGIFWriter::~vvAnimatedGIFWriter()
29 {
30 }
31
32 //---------------------------------------------------------------------------
33 void vvAnimatedGIFWriter::Start()
34 {
35   // Create one volume with all slices
36   RGBvolume = vtkSmartPointer<vtkImageAppend>::New();
37   RGBvolume->SetAppendAxis(2);
38   RGBslices.clear();
39 }
40
41 //---------------------------------------------------------------------------
42 void vvAnimatedGIFWriter::Write()
43 {
44   // get the data
45 #if VTK_MAJOR_VERSION <= 5
46   this->GetInput()->UpdateInformation();
47   int *wExtent = this->GetInput()->GetWholeExtent();
48   this->GetInput()->SetUpdateExtent(wExtent);
49   this->GetInput()->Update();
50 #elif VTK_MAJOR_VERSION >= 8 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION >= 1)
51   this->UpdateInformation();
52   int *wExtent = this->GetInput()->GetInformation()->Get(vtkDataObject::DATA_EXTENT());
53   this->UpdateExtent(wExtent);
54   this->Update();
55 #else
56   this->UpdateInformation();
57   int *wExtent = this->GetInput()->GetInformation()->Get(vtkDataObject::DATA_EXTENT());
58   this->SetUpdateExtent(wExtent);
59   this->Update();
60 #endif
61
62   RGBslices.push_back( vtkSmartPointer<vtkImageData>::New() );
63   RGBslices.back()->ShallowCopy(this->GetInput());
64 #if VTK_MAJOR_VERSION <= 5
65   RGBvolume->AddInput(RGBslices.back());
66 #else
67   RGBvolume->AddInputData(RGBslices.back());
68 #endif
69 }
70
71 //---------------------------------------------------------------------------
72 void vvAnimatedGIFWriter::End()
73 {
74   RGBvolume->Update();
75
76   // Quantize to 8 bit colors
77   vtkSmartPointer<vtkImageQuantizeRGBToIndex> quant = vtkSmartPointer<vtkImageQuantizeRGBToIndex>::New();
78   quant->SetNumberOfColors(256);
79 #if VTK_MAJOR_VERSION <= 5
80   quant->SetInput(RGBvolume->GetOutput());
81 #else
82   quant->SetInputConnection(RGBvolume->GetOutputPort());
83 #endif
84   quant->Update();
85
86   // Convert to 8 bit image
87   vtkSmartPointer<vtkImageCast> cast =  vtkSmartPointer<vtkImageCast>::New();
88 #if VTK_MAJOR_VERSION <= 5
89   cast->SetInput( quant->GetOutput() );
90 #else
91   cast->SetInputConnection( quant->GetOutputPort() );
92 #endif
93   cast->SetOutputScalarTypeToUnsignedChar();
94   cast->Update();
95
96   // Create palette for CxImage => Swap r and b in LUT
97   RGBQUAD pal[256];
98   memcpy(pal, (RGBQUAD*)(quant->GetLookupTable()->GetPointer(0)), sizeof(RGBQUAD)*256);
99   for(unsigned int j=0; j<256; j++)
100     std::swap(pal[j].rgbBlue, pal[j].rgbRed);
101
102   // Create a stack of CxImages
103   DWORD width = cast->GetOutput()->GetExtent()[1]-cast->GetOutput()->GetExtent()[0]+1;
104   DWORD height = cast->GetOutput()->GetExtent()[3]-cast->GetOutput()->GetExtent()[2]+1;
105   std::vector<CxImage*> cximages( RGBslices.size() );
106   for(unsigned int i=0; i<RGBslices.size(); i++) {
107     cximages[i] = new CxImage;
108     cximages[i]->SetFrameDelay(100/Rate);
109     if(Dither) {
110       cximages[i]->CreateFromArray((BYTE *)RGBvolume->GetOutput()->GetScalarPointer(0,0,i),
111                                    width, height, 24, width*3, false);
112       cximages[i]->SwapRGB2BGR();
113       cximages[i]->DecreaseBpp(8, true, pal);
114     }
115     else {
116       cximages[i]->CreateFromArray((BYTE *)cast->GetOutput()->GetScalarPointer(0,0,i),
117                                    width, height, 8, width, false);
118       cximages[i]->SetPalette(pal);
119     }
120   }
121
122   // Create gif
123   FILE * pFile;
124   pFile = fopen (this->FileName, "wb");
125   if(pFile==NULL) {
126     vtkErrorMacro("Error in vvAnimatedGIFWriter::End: could not open " << this->FileName );
127     return;
128   }
129   CxImageGIF cximagegif;
130   cximagegif.SetLoops(Loops);
131   bool result = cximagegif.Encode(pFile,&(cximages[0]), (int)RGBslices.size(), true);
132
133   // Cleanup
134   fclose(pFile);
135   for(unsigned int i=0; i<RGBslices.size(); i++)
136     delete cximages[i];
137   if(!result) {
138     vtkErrorMacro("Error in CxImage: " << cximagegif.GetLastError() );
139   }
140 }
141
142 //---------------------------------------------------------------------------
143 void vvAnimatedGIFWriter::PrintSelf(ostream& os, vtkIndent indent)
144 {
145   this->Superclass::PrintSelf(os, indent);
146 }