Skip to content

Commit e91fc99

Browse files
ColumbusTechColumbusTech
ColumbusTech
authored and
ColumbusTech
committed
C library
1 parent 36cb009 commit e91fc99

File tree

2 files changed

+469
-143
lines changed

2 files changed

+469
-143
lines changed

tga.h

+298
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
#pragma once
2+
3+
/*!
4+
* @file tga.h
5+
* @brief All C library functional.
6+
*/
7+
8+
#include <string.h>
9+
#include <stdint.h>
10+
#include <stdlib.h>
11+
#include <stdio.h>
12+
13+
/**
14+
* @brief Loads TGA from file.
15+
*
16+
* ## Example
17+
*
18+
* ```c
19+
* int w, h, b;
20+
* uint8_t* data = tga_load("image.tga", &w, &h, &b);
21+
* ```
22+
*
23+
* @param Filename Image file to load.
24+
* @param Width Pointer to int to store image width.
25+
* @param Height Pointer to int to store image height.
26+
* @param Bpp Pointer to int to store size of pixel in bytes.
27+
*/
28+
uint8_t* tga_load(const char* Filename, int* Width, int* Height, int* Bpp);
29+
/**
30+
* @brief Loads TGA from memory buffer.
31+
* @param Data Buffer storing image file data.
32+
* @param Size Size of buffer.
33+
* @param Width Pointer to int to store image width.
34+
* @param Height Pointer to int to store image height.
35+
* @param Bpp Pointer to int to store sixe of pixel in bytes.
36+
*/
37+
uint8_t* tga_load_memory(uint8_t* Data, int Size, int* Width, int* Height, int* Bpp);
38+
39+
static void tga_load_compressed_paletted_8(uint8_t* InBuffer, uint8_t* ColorMap, uint8_t* OutBuffer, size_t Size, size_t PixelSize);
40+
static void tga_load_compressed_paletted_16(uint16_t* InBuffer, uint8_t* ColorMap, uint8_t* OutBuffer, size_t Size, size_t PixelSize);
41+
static void tga_load_compressed_true_color(uint8_t* InBuffer, uint8_t* OutBuffer, size_t Size, size_t PixelSize);
42+
static void tga_load_compressed_monochrome(uint8_t* InBuffer, uint8_t* OutBuffer, size_t Size);
43+
44+
void tga_load_compressed_paletted_8(uint8_t* InBuffer, uint8_t* ColorMap, uint8_t* OutBuffer, size_t Size, size_t PixelSize)
45+
{
46+
uint8_t Index;
47+
uint8_t Pixel[4];
48+
uint8_t Tmp;
49+
uint8_t* ColorMapPtr;
50+
51+
for (size_t i = 0; i < Size; i++)
52+
{
53+
Index = *InBuffer++;
54+
ColorMapPtr = &ColorMap[Index * PixelSize];
55+
56+
memcpy(Pixel, ColorMapPtr, PixelSize);
57+
Tmp = Pixel[0]; Pixel[0] = Pixel[2]; Pixel[2] = Tmp;
58+
memcpy(OutBuffer, Pixel, PixelSize); OutBuffer += PixelSize;
59+
}
60+
}
61+
62+
void tga_load_compressed_paletted_16(uint16_t* InBuffer, uint8_t* ColorMap, uint8_t* OutBuffer, size_t Size, size_t PixelSize)
63+
{
64+
uint16_t Index;
65+
uint8_t Pixel[4];
66+
uint8_t Tmp;
67+
uint8_t* ColorMapPtr;
68+
69+
for (size_t i = 0; i < Size; i++)
70+
{
71+
Index = *InBuffer++;
72+
ColorMapPtr = &ColorMap[Index * PixelSize];
73+
74+
memcpy(Pixel, ColorMapPtr, PixelSize);
75+
Tmp = Pixel[0]; Pixel[0] = Pixel[2]; Pixel[2] = Tmp;
76+
memcpy(OutBuffer, Pixel, PixelSize); OutBuffer += PixelSize;
77+
}
78+
}
79+
80+
void tga_load_compressed_true_color(uint8_t* InBuffer, uint8_t* OutBuffer, size_t Size, size_t PixelSize)
81+
{
82+
uint8_t Header;
83+
uint8_t Pixel[4], Tmp;
84+
size_t i, j, PixelCount;
85+
86+
for (i = 0; i < Size; )
87+
{
88+
Header = *InBuffer++;
89+
PixelCount = (Header & 0x7F) + 1;
90+
91+
if (Header & 0x80)
92+
{
93+
memcpy(Pixel, InBuffer, PixelSize); InBuffer += PixelSize;
94+
Tmp = Pixel[0]; Pixel[0] = Pixel[2]; Pixel[2] = Tmp;
95+
96+
for (j = 0; j < PixelCount; j++)
97+
{
98+
memcpy(OutBuffer, Pixel, PixelSize); OutBuffer += PixelSize;
99+
}
100+
101+
i += PixelCount;
102+
}
103+
else
104+
{
105+
for (j = 0; j < PixelCount; j++)
106+
{
107+
memcpy(Pixel, InBuffer, PixelSize); InBuffer += PixelSize;
108+
Tmp = Pixel[0]; Pixel[0] = Pixel[2]; Pixel[2] = Tmp;
109+
memcpy(OutBuffer, Pixel, PixelSize); OutBuffer += PixelSize;
110+
}
111+
i += PixelCount;
112+
}
113+
}
114+
}
115+
116+
void tga_load_compressed_monochrome(uint8_t* InBuffer, uint8_t* OutBuffer, size_t Size)
117+
{
118+
uint8_t Header;
119+
uint8_t Red;
120+
size_t i, j, PixelCount;
121+
122+
for (i = 0; i < Size; )
123+
{
124+
Header = *InBuffer++;
125+
PixelCount = (Header & 0x7F) + 1;
126+
127+
if (Header & 0x80)
128+
{
129+
Red = *InBuffer++;
130+
131+
for (j = 0; j < PixelCount; j++)
132+
{
133+
*OutBuffer++ = Red;
134+
}
135+
136+
i += PixelCount;
137+
}
138+
else
139+
{
140+
for (j = 0; j < PixelCount; j++)
141+
{
142+
*OutBuffer++ = *InBuffer++;
143+
}
144+
145+
i += PixelCount;
146+
}
147+
}
148+
}
149+
150+
uint8_t* tga_load(const char* Filename, int* Width, int* Height, int* Bpp)
151+
{
152+
FILE* f = fopen(Filename, "rb");
153+
if (f == NULL) return NULL;
154+
155+
size_t Size = 0;
156+
fseek(f, 0, SEEK_END);
157+
Size = ftell(f);
158+
rewind(f);
159+
160+
uint8_t* Buffer = (uint8_t*)malloc(Size);
161+
if (Buffer == NULL) return NULL;
162+
if (fread(Buffer, 1, Size, f) != Size)
163+
{
164+
fclose(f);
165+
return NULL;
166+
}
167+
168+
fclose(f);
169+
170+
uint8_t* Result = tga_load_memory(Buffer, Size, Width, Height, Bpp);
171+
free(Buffer);
172+
return Result;
173+
}
174+
175+
uint8_t* tga_load_memory(uint8_t* Data, int Size, int* Width, int* Height, int* Bpp)
176+
{
177+
struct
178+
{
179+
uint8_t IDLength;
180+
uint8_t ColorMapType;
181+
uint8_t ImageType;
182+
183+
uint16_t ColorMapOrigin;
184+
uint16_t ColorMapLength;
185+
uint8_t ColorMapEntrySize;
186+
187+
uint16_t XOrigin;
188+
uint16_t YOrigin;
189+
uint16_t Width;
190+
uint16_t Height;
191+
uint8_t Bits;
192+
uint8_t ImageDescriptor;
193+
} Header;
194+
195+
Header.IDLength = *Data++;
196+
Header.ColorMapType = *Data++;
197+
Header.ImageType = *Data++;
198+
Header.ColorMapOrigin = *((uint16_t*)Data); Data += sizeof(uint16_t);
199+
Header.ColorMapLength = *((uint16_t*)Data); Data += sizeof(uint16_t);
200+
Header.ColorMapEntrySize = *Data++;
201+
Header.XOrigin = *((uint16_t*)Data); Data += sizeof(uint16_t);
202+
Header.YOrigin = *((uint16_t*)Data); Data += sizeof(uint16_t);
203+
Header.Width = *((uint16_t*)Data); Data += sizeof(uint16_t);
204+
Header.Height = *((uint16_t*)Data); Data += sizeof(uint16_t);
205+
Header.Bits = *Data++;
206+
Header.ImageDescriptor = *Data++;
207+
208+
Data += Header.ImageDescriptor;
209+
210+
size_t ColorMapElementSize = Header.ColorMapEntrySize / 8;
211+
size_t ColorMapSize = Header.ColorMapLength * ColorMapElementSize;
212+
uint8_t* ColorMap = (uint8_t*)malloc(ColorMapSize);
213+
214+
if (Header.ColorMapType == 1)
215+
{
216+
memcpy(ColorMap, Data, ColorMapSize);
217+
Data += ColorMapSize;
218+
}
219+
220+
size_t PixelSize = Header.ColorMapLength == 0 ? (Header.Bits / 8) : ColorMapElementSize;
221+
size_t DataSize = Size - sizeof(Header) - (Header.ColorMapType == 1 ? ColorMapSize : 0);
222+
size_t ImageSize = Header.Width * Header.Height * PixelSize;
223+
224+
uint8_t* Result = (uint8_t*)calloc(ImageSize, 1);
225+
226+
switch (Header.ImageType)
227+
{
228+
case 0: break; // No Image
229+
case 1: // Uncompressed paletted
230+
{
231+
if (PixelSize == 3 || PixelSize == 4)
232+
{
233+
switch (Header.Bits)
234+
{
235+
case 8: tga_load_compressed_paletted_8 ((uint8_t*) Data, ColorMap, Result, Header.Width * Header.Height, PixelSize); break;
236+
case 16: tga_load_compressed_paletted_16((uint16_t*)Data, ColorMap, Result, Header.Width * Header.Height, PixelSize); break;
237+
}
238+
}
239+
240+
break;
241+
}
242+
case 2: // Uncompressed TrueColor
243+
{
244+
if (Header.Bits = 24 || Header.Bits == 32)
245+
{
246+
memcpy(Result, Data, ImageSize);
247+
uint8_t Tmp;
248+
249+
for (size_t i = 0; i < ImageSize; i += PixelSize)
250+
{
251+
Tmp = Result[i]; Result[i] = Result[i + 2]; Result[i + 2] = Tmp;
252+
}
253+
}
254+
255+
break;
256+
}
257+
258+
case 3: // Uncompressed Monochrome
259+
{
260+
if (Header.Bits == 8)
261+
{
262+
memcpy(Result, Data, ImageSize);
263+
}
264+
265+
break;
266+
}
267+
268+
case 9: break; // Compressed paletted TODO
269+
case 10: // Compressed TrueColor
270+
{
271+
if (PixelSize == 3 || PixelSize == 4)
272+
{
273+
tga_load_compressed_true_color(Data, Result, Header.Width * Header.Height, PixelSize);
274+
}
275+
276+
break;
277+
}
278+
279+
case 11: // Compressed Monocrhome
280+
{
281+
if (Header.Bits == 8)
282+
{
283+
tga_load_compressed_monochrome(Data, Result, Header.Width * Header.Height);
284+
}
285+
286+
break;
287+
}
288+
}
289+
290+
*Width = Header.Width;
291+
*Height = Header.Height;
292+
*Bpp = PixelSize;
293+
294+
free(ColorMap);
295+
return Result;
296+
}
297+
298+

0 commit comments

Comments
 (0)