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