1// tImageICO.h 
2// 
3// This class knows how to load windows icon (ico) files. It loads the data into multiple tPixel arrays, one for each 
4// frame (ico files may be multiple images at different resolutions). These arrays may be 'stolen' by tPictures. The 
5// loading code is a modificaton of code from Victor Laskin. In particular the code now: 
6// a) Loads all frames of an ico, not just the biggest one. 
7// b) Supports embedded png images. 
8// c) Supports widths and heights of 256. 
9// Victor Laskin's header/licence in the original ico.cpp is shown below. 
10// 
11// Copyright (c) 2020 Tristan Grimmer. 
12// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
13// granted, provided that the above copyright notice and this permission notice appear in all copies. 
14// 
15// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
17// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
18// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
19// PERFORMANCE OF THIS SOFTWARE. 
20// 
21// Includes modified version of code from Victor Laskin. 
22// Code by Victor Laskin (victor.laskin@gmail.com) 
23// Rev 2 - 1bit color was added, fixes for bit mask. 
24// 
25// THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
26// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
27// THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
28// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
29// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31// POSSIBILITY OF SUCH DAMAGE. 
32 
33#pragma once 
34#include <Foundation/tString.h> 
35#include <Math/tColour.h> 
36#include <Image/tPixelFormat.h> 
37namespace tImage 
38
39 
40 
41class tImageICO 
42
43public
44 // Creates an invalid tImageICO. You must call Load manually. 
45 tImageICO() { } 
46 tImageICO(const tString& icoFile) { Load(icoFile); } 
47 
48 virtual ~tImageICO() { Clear(); } 
49 
50 // Clears the current tImageICO before loading. If false returned object is invalid. 
51 bool Load(const tString& icoFile); 
52 
53 // After this call no memory will be consumed by the object and it will be invalid. 
54 void Clear(); 
55 bool IsValid() const { return (GetNumFrames() >= 1); } 
56 int GetNumFrames() const { return Frames.GetNumItems(); } 
57 tPixelFormat GetBestSrcPixelFormat() const
58 
59 struct Frame : public tLink<Frame
60
61 int Width = 0
62 int Height = 0
63 tPixel* Pixels = nullptr
64 tPixelFormat SrcPixelFormat = tPixelFormat::Invalid
65 }; 
66 
67 // After this call you are the owner of the frame and must eventually delete it. The frame you stole will no 
68 // longer be a valid frame of the tImageICO, but the remaining ones will still be valid. 
69 Frame* StealFrame(int frameNum); 
70 Frame* GetFrame(int frameNum); 
71 
72private
73 bool PopulateFrames(const uint8* buffer, int numBytes);  
74 Frame* CreateFrame(const uint8* buffer, int width, int height, int numBytes); 
75 
76 tList<Frame> Frames
77}; 
78 
79 
80// Implementation only below. 
81 
82 
83inline tImageICO::Frame* tImage::tImageICO::StealFrame(int frameNum
84
85 Frame* p = GetFrame(frameNum); 
86 if (!p
87 return nullptr
88 
89 return Frames.Remove(p); 
90
91 
92 
93inline tImageICO::Frame* tImage::tImageICO::GetFrame(int frameNum
94
95 if ((frameNum >= Frames.GetNumItems()) || (frameNum < 0)) 
96 return nullptr
97 
98 Frame* f = Frames.First(); 
99 while (frameNum--) 
100 f = f->Next(); 
101 
102 return f
103
104 
105 
106inline void tImageICO::Clear() 
107
108 while (Frame* frame = Frames.Remove()) 
109
110 delete[] frame->Pixels
111 delete frame
112
113
114 
115 
116inline tPixelFormat tImageICO::GetBestSrcPixelFormat() const 
117
118 tPixelFormat bestFormat = tPixelFormat::Invalid
119 for (Frame* frame = Frames.First(); frame; frame = frame->Next()) 
120
121 if (frame->SrcPixelFormat == tPixelFormat::Invalid
122 continue
123 if (frame->SrcPixelFormat == tPixelFormat::R8G8B8A8
124 return tPixelFormat::R8G8B8A8
125 else if (frame->SrcPixelFormat < bestFormat
126 bestFormat = frame->SrcPixelFormat
127
128  
129 return bestFormat
130
131 
132 
133
134