1// tImageWEBP.cpp 
2// 
3// This knows how to load WebPs. It knows the details of the webp file format and loads the data into multiple tPixel 
4// arrays, one for each frame (WebPs 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#include <Foundation/tStandard.h> 
17#include <Foundation/tString.h> 
18#include <System/tFile.h> 
19#include "Image/tImageWEBP.h" 
20#ifdef PLATFORM_WINDOWS 
21#include "WebP/Windows/include/demux.h" 
22#elif defined(PLATFORM_LINUX) 
23#include "WebP/Linux/include/demux.h" 
24#endif 
25using namespace tSystem
26namespace tImage 
27
28 
29 
30bool tImageWEBP::Load(const tString& webpFile
31
32 Clear(); 
33 
34 if (tSystem::tGetFileType(webpFile) != tSystem::tFileType::WEBP
35 return false
36 
37 if (!tFileExists(webpFile)) 
38 return false
39 
40 int numBytes = 0
41 uint8* webpFileInMemory = tLoadFile(webpFile, nullptr, &numBytes); 
42 
43 // Now we load and populate the frames. 
44 WebPData webpData
45 webpData.bytes = webpFileInMemory
46 webpData.size = numBytes
47 
48 WebPDemuxer* demux = WebPDemux(&webpData); 
49 uint32 width = WebPDemuxGetI(demux, WEBP_FF_CANVAS_WIDTH); 
50 uint32 height = WebPDemuxGetI(demux, WEBP_FF_CANVAS_HEIGHT); 
51 uint32 flags = WebPDemuxGetI(demux, WEBP_FF_FORMAT_FLAGS); 
52 uint32 numFrames = WebPDemuxGetI(demux, WEBP_FF_FRAME_COUNT); 
53  
54 if ((width <= 0) || (height <= 0) || (numFrames <= 0)) 
55
56 WebPDemuxDelete(demux); 
57 delete[] webpFileInMemory
58 return false
59
60 
61 // Iterate over all frames. 
62 SrcPixelFormat = tPixelFormat::R8G8B8
63 WebPIterator iter
64 if (WebPDemuxGetFrame(demux, 1, &iter)) 
65
66 do 
67
68 WebPDecoderConfig config
69 WebPInitDecoderConfig(&config); 
70 
71 config.output.colorspace = MODE_RGBA
72 config.output.is_external_memory = 0
73 config.options.flip = 1
74 int result = WebPDecode(iter.fragment.bytes, iter.fragment.size, &config); 
75 if (result != VP8_STATUS_OK
76 continue
77 
78 Frame* newFrame = new Frame
79 newFrame->SrcPixelFormat = iter.has_alpha ? tPixelFormat::R8G8B8A8 : tPixelFormat::R8G8B8
80 if (iter.has_alpha
81 SrcPixelFormat = tPixelFormat::R8G8B8A8
82 newFrame->Width = width
83 newFrame->Height = height
84 newFrame->Pixels = new tPixel[width * height]; 
85 newFrame->Duration = float(iter.duration) / 1000.0f
86 
87 tStd::tMemcpy(newFrame->Pixels, config.output.u.RGBA.rgba, width * height * sizeof(tPixel)); 
88 WebPFreeDecBuffer(&config.output); 
89 Frames.Append(newFrame); 
90
91 while (WebPDemuxNextFrame(&iter)); 
92 
93 WebPDemuxReleaseIterator(&iter); 
94
95 
96 WebPDemuxDelete(demux); 
97 delete[] webpFileInMemory
98 return true
99
100 
101 
102
103