1// tImageGIF.h 
2// 
3// This knows how to load gifs. It knows the details of the gif file format and loads the data into multiple tPixel 
4// arrays, one for each frame (gifs may be animated). These arrays may be 'stolen' by tPictures. 
5// 
6// Copyright (c) 2020 Tristan Grimmer. 
7// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
8// granted, provided that the above copyright notice and this permission notice appear in all copies. 
9// 
10// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
11// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
12// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
13// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
14// PERFORMANCE OF THIS SOFTWARE. 
15 
16#pragma once 
17#include <Foundation/tString.h> 
18#include <Math/tColour.h> 
19#include <Image/tPixelFormat.h> 
20namespace tImage 
21
22 
23 
24class tImageGIF 
25
26public
27 // Creates an invalid tImageGIF. You must call Load manually. 
28 tImageGIF() { } 
29 tImageGIF(const tString& gifFile) { Load(gifFile); } 
30 
31 virtual ~tImageGIF() { Clear(); } 
32 
33 // Clears the current tImageGIF before loading. If false returned object is invalid. 
34 bool Load(const tString& gifFile); 
35 
36 // After this call no memory will be consumed by the object and it will be invalid. 
37 void Clear(); 
38 bool IsValid() const { return (GetNumFrames() >= 1); } 
39 
40 int GetWidth() const { return Width; } 
41 int GetHeight() const { return Height; } 
42 int GetNumFrames() const { return Frames.GetNumItems(); } 
43 
44 struct Frame : public tLink<Frame
45
46 tPixel* Pixels = nullptr
47 float Duration = 0.0f; // Frame duration in seconds. Converted from the gif 10ms count. 
48 }; 
49 
50 // After this call you are the owner of the frame and must eventually delete it. The frame you stole will no 
51 // longer be a valid frame of the tImageGIF, but the remaining ones will still be valid. 
52 Frame* StealFrame(int frameNum); 
53 Frame* GetFrame(int frameNum); 
54 tPixelFormat SrcPixelFormat = tPixelFormat::Invalid
55 
56private
57 static void FrameCallbackBridge(void* imgGifRaw, struct GIF_WHDR*); 
58 void FrameCallback(struct GIF_WHDR*); 
59 
60 // Variables used during callback processing. 
61 int FrmLast = 0
62 tPixel* FrmPict = nullptr
63 tPixel* FrmPrev = nullptr
64 
65 int Width = 0
66 int Height = 0
67 tList<Frame> Frames
68}; 
69 
70 
71// Implementation only below. 
72 
73 
74inline void tImageGIF::FrameCallbackBridge(void* imgGifRaw, struct GIF_WHDR* whdr
75
76 tImageGIF* imgGif = (tImageGIF*)imgGifRaw
77 imgGif->FrameCallback(whdr); 
78
79 
80 
81inline tImageGIF::Frame* tImage::tImageGIF::StealFrame(int frameNum
82
83 Frame* f = GetFrame(frameNum); 
84 if (!f
85 return nullptr
86 
87 return Frames.Remove(f); 
88
89 
90 
91inline tImageGIF::Frame* tImage::tImageGIF::GetFrame(int frameNum
92
93 if ((frameNum >= Frames.GetNumItems()) || (frameNum < 0)) 
94 return nullptr
95 
96 Frame* f = Frames.First(); 
97 while (frameNum--) 
98 f = f->Next(); 
99 
100 return f
101
102 
103 
104inline void tImageGIF::Clear() 
105
106 Width = 0
107 Height = 0
108 while (Frame* frame = Frames.Remove()) 
109
110 delete[] frame->Pixels
111 delete frame
112
113 SrcPixelFormat = tPixelFormat::Invalid
114
115 
116 
117
118