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