SayoriOS 0.3.3

tga.c
1 // TGA Decoder by pimnik98, NDRAEY and OSDev Wiki
2
3 #include "common.h"
4 #include "lib/stdio.h"
5 #include "fmt/tga.h"
6 #include "io/ports.h"
7 #include "mem/vmm.h"
8
9 bool tga_extract_info(const char* path, tga_header_t* out_meta){
10 FILE* file = fopen(path, "rb");
11
12 if(!file){
13 return false;
14 }
15
16 fread(file, sizeof(tga_header_t), 1, out_meta);
17
18 fclose(file);
19
20 return true;
21 }
22
23 // Pixel buffer needs to be 32-bit ARGB buffer
24 int tga_extract_pixels(const char* path, uint32_t* pixel_buf) {
25 FILE* file = fopen(path, "rb");
26
27 if(!file){
28 return -1;
29 }
30
31 fseek(file, 0, SEEK_END);
32
33 size_t filesize = ftell(file);
34
35 fseek(file, 0, SEEK_SET);
36
37 uint8_t* file_data = kcalloc(filesize, 1);
38
39 // qemu_note("FILE SIZE: %u", filesize);
40
41 fread(file, filesize, 1, file_data);
42
43 tga_header_t* targa_header = (tga_header_t*)file_data;
44
45 char* data = (char*)file_data + sizeof(tga_header_t);
46
47 // IDK how to understand this code.
48
49 int i = 0,
50 j = 0,
51 k = 0,
52 x = 0,
53 y = 0,
54 w = targa_header->h,
55 h = targa_header->w,
56 o = (file_data[11] << 8) + file_data[10];
57
58 int m = (targa_header->colormap ? (file_data[7]>>3) * file_data[5] : 0) + 18;
59
60 if(w < 1 || h < 1) {
61 return -2;
62 }
63
64 if (targa_header->image_type != 1
65 && targa_header->image_type != 2
66 && targa_header->image_type != 9
67 && targa_header->image_type != 10)
68 {
69 return -3;
70 }
71
72 switch(targa_header->image_type) {
73 case TGA_MODE_UC_CMI: {
74 if(file_data[6] != 0
75 || file_data[4] != 0
76 || file_data[3] != 0
77 || (file_data[7]!=24 && file_data[7]!=32)) {
78 return -4;
79 }
80
81 for(y = i = 0; y<h; y++) {
82 k = ((!o?h-y-1:y)*w);
83 for(x=0; x<w; x++) {
84 j = file_data[m + k++]*(file_data[7]>>3) + 18;
85
86 int g = file_data[j];
87 int a = file_data[j+1];
88 int b = file_data[j+2];
89 int r = (file_data[7]==32?file_data[j+3]:0xff);
90
91 pixel_buf[
92 y * targa_header->w + x
93 ] = (a << 24)
94 | (b << 16)
95 | (g << 8 )
96 | (r << 0 );
97 }
98 }
99 break;
100 }
101 case TGA_MODE_UC_RGB:{
102 if(file_data[5]!=0 || file_data[6]!=0 || file_data[1]!=0 || (file_data[16]!=24 && file_data[16]!=32)) {
103 return -4;
104 }
105
106 for(y = i = 0; y < h; y++) {
107 j = (!o ? h - y - 1 : y) * w * (targa_header->bpp >> 3);
108 for(x = 0; x < w; x++) {
109 int g = file_data[j];
110 int a = file_data[j+1];
111 int b = file_data[j+2];
112 int r = (targa_header->bpp == 32 ? file_data[j+3] : 0xff);
113
114 pixel_buf[
115 y * targa_header->w + x
116 ] = (a << 24)
117 | (b << 16)
118 | (g << 8 )
119 | (r << 0 );
120
121 j += targa_header->bpp >> 3;
122 }
123 }
124 break;
125 }
126 case TGA_MODE_RL_RGB: {
127 if(file_data[5]!=0 || file_data[6]!=0 || file_data[1]!=0 || (file_data[16]!=24 && file_data[16]!=32)) {
128 return -4;
129 }
130
131 y = i = 0;
132
133 size_t current_processing = 0;
134
135 size_t cur_x = 0;
136 size_t cur_y = 0;
137
138 while(cur_y < targa_header->h) {
139 uint8_t rep_count_raw = data[current_processing++];
140 uint8_t repetition_count = (rep_count_raw & 0b01111111) + 1;
141
142 // If packet is raw, repetition count will indicate pixel count.
143 bool is_raw = ((rep_count_raw & 0b10000000) >> 7); // Extract highest bit
144
145 uint8_t r = 0,
146 g = 0,
147 b = 0,
148 a = 0;
149
150 if(is_raw) {
151 r = data[current_processing++] & 0xff;
152 g = data[current_processing++] & 0xff;
153 b = data[current_processing++] & 0xff;
154
155 if(targa_header->bpp == 32)
156 a = data[current_processing++] & 0xff;
157 else
158 a = 0xFF;
159
160 while(repetition_count--) {
161 if(cur_x >= targa_header->w) {
162 cur_x = 0;
163 cur_y++;
164 }
165
166 // setPixelAlpha(cur_x, cur_y, (rgba_color) {
167 // b, g, r, a
168 // });
169
170 pixel_buf[
171 cur_y * targa_header->w + cur_x
172 ] = (a << 24)
173 | (b << 16)
174 | (g << 8 )
175 | (r << 0 );
176
177 cur_x++;
178 }
179 } else {
180 while(repetition_count--) {
181 r = data[current_processing++] & 0xff;
182 g = data[current_processing++] & 0xff;
183 b = data[current_processing++] & 0xff;
184
185 if(targa_header->bpp == 32)
186 a = data[current_processing++];
187 else
188 a = 0xFF;
189
190 if(cur_x >= targa_header->w) {
191 cur_x = 0;
192 cur_y++;
193 }
194
195 // setPixelAlpha(cur_x, cur_y, (rgba_color) {
196 // b, g, r, a
197 // });
198
199 pixel_buf[
200 cur_y * targa_header->w + cur_x
201 ] = (a << 24)
202 | (b << 16)
203 | (g << 8 )
204 | (r << 0 );
205
206 cur_x++;
207 }
208
209 }
210 }
211
212 break;
213 }
214 default: {
215 qemu_err("Error: Mode not implemented: %d\n", targa_header->image_type);
216 break;
217 }
218 }
219
220 kfree(file_data);
221 fclose(file);
222
223 return 0;
224 }
225
226 // Pixel buffer needs to be 32-bit ARGB buffer
227 int tga_extract_pixels_from_data(const char* raw_data, uint32_t* pixel_buf) {
228 ON_NULLPTR(raw_data, {
229 return 0;
230 });
231
232 tga_header_t* targa_header = (tga_header_t*)raw_data;
233
234 qemu_warn("W: %d", targa_header->w);
235 qemu_warn("H: %d", targa_header->h);
236 qemu_warn("BPP: %d", targa_header->bpp);
237
238 char* data = (char*)raw_data + sizeof(tga_header_t);
239
240 // IDK how to understand this code.
241
242 int i = 0,
243 j = 0,
244 k = 0,
245 x = 0,
246 y = 0,
247 w = targa_header->w,
248 h = targa_header->h,
249 o = (raw_data[11] << 8) + raw_data[10];
250
251 int m = (targa_header->colormap ? (raw_data[7]>>3) * raw_data[5] : 0) + 18;
252
253 if(w < 1 || h < 1) {
254 return -2;
255 }
256
257 if (targa_header->image_type != 1
258 && targa_header->image_type != 2
259 && targa_header->image_type != 9
260 && targa_header->image_type != 10)
261 {
262 return -3;
263 }
264
265 switch(targa_header->image_type) {
266 case TGA_MODE_UC_CMI: {
267 if(raw_data[6] != 0
268 || raw_data[4] != 0
269 || raw_data[3] != 0
270 || (raw_data[7]!=24 && raw_data[7]!=32)) {
271 return -4;
272 }
273
274 for(y = i = 0; y<h; y++) {
275 k = ((!o?h-y-1:y)*w);
276 for(x=0; x<w; x++) {
277 j = raw_data[m + k++]*(raw_data[7]>>3) + 18;
278
279 int g = raw_data[j];
280 int a = raw_data[j+1];
281 int b = raw_data[j+2];
282 int r = (raw_data[7]==32?raw_data[j+3]:0xff);
283
284 pixel_buf[
285 y * targa_header->w + x
286 ] = (a << 24)
287 | (b << 16)
288 | (g << 8 )
289 | (r << 0 );
290 }
291 }
292 break;
293 }
294 case TGA_MODE_UC_RGB:{
295 if(raw_data[5]!=0 || raw_data[6]!=0 || raw_data[1]!=0 || (raw_data[16]!=24 && raw_data[16]!=32)) {
296 return -4;
297 }
298
299 for(y = i = 0; y < h; y++) {
300 j = (!o ? h - y - 1 : y) * w * (targa_header->bpp >> 3);
301 for(x = 0; x < w; x++) {
302 int g = raw_data[j];
303 int a = raw_data[j+1];
304 int b = raw_data[j+2];
305 int r = (targa_header->bpp == 32 ? raw_data[j+3] : 0xff);
306
307 pixel_buf[
308 y * targa_header->w + x
309 ] = (a << 24)
310 | (b << 16)
311 | (g << 8 )
312 | (r << 0 );
313
314 j += targa_header->bpp >> 3;
315 }
316 }
317 break;
318 }
319 case TGA_MODE_RL_RGB: {
320 if(raw_data[5]!=0 || raw_data[6]!=0 || raw_data[1]!=0 || (raw_data[16]!=24 && raw_data[16]!=32)) {
321 return -4;
322 }
323
324 y = i = 0;
325
326 size_t current_processing = 0;
327
328 size_t cur_x = 0;
329 size_t cur_y = 0;
330
331 while(cur_y < targa_header->h) {
332 uint8_t rep_count_raw = data[current_processing++];
333 uint8_t repetition_count = (rep_count_raw & 0b01111111) + 1;
334
335 // If packet is raw, repetition count will indicate pixel count.
336 bool is_raw = ((rep_count_raw & 0b10000000) >> 7); // Extract highest bit
337
338 uint8_t r = 0,
339 g = 0,
340 b = 0,
341 a = 0;
342
343 if(is_raw) {
344 r = data[current_processing++] & 0xff;
345 g = data[current_processing++] & 0xff;
346 b = data[current_processing++] & 0xff;
347
348 if(targa_header->bpp == 32)
349 a = data[current_processing++] & 0xff;
350 else
351 a = 0xFF;
352
353 while(repetition_count--) {
354 if(cur_x >= targa_header->w) {
355 cur_x = 0;
356 cur_y++;
357 }
358
359 // setPixelAlpha(cur_x, cur_y, (rgba_color) {
360 // b, g, r, a
361 // });
362
363 pixel_buf[
364 cur_y * targa_header->w + cur_x
365 ] = (a << 24)
366 | (b << 16)
367 | (g << 8 )
368 | (r << 0 );
369
370 cur_x++;
371 }
372 } else {
373 while(repetition_count--) {
374 r = data[current_processing++] & 0xff;
375 g = data[current_processing++] & 0xff;
376 b = data[current_processing++] & 0xff;
377
378 if(targa_header->bpp == 32)
379 a = data[current_processing++];
380 else
381 a = 0xFF;
382
383 if(cur_x >= targa_header->w) {
384 cur_x = 0;
385 cur_y++;
386 }
387
388 // setPixelAlpha(cur_x, cur_y, (rgba_color) {
389 // b, g, r, a
390 // });
391
392 pixel_buf[
393 cur_y * targa_header->w + cur_x
394 ] = (a << 24)
395 | (b << 16)
396 | (g << 8 )
397 | (r << 0 );
398
399 cur_x++;
400 }
401
402 }
403 }
404
405 break;
406 }
407 default: {
408 qemu_log("Error: Mode not implemented: %d\n", targa_header->image_type);
409 break;
410 }
411 }
412
413 return 0;
414 }
common.h
Основные определения ядра
filesize
size_t filesize(const char *Path)
[FileIO] Возвращает размер указанного файла
Definition: fileio.c:67
fseek
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
Definition: stdio.c:315
fclose
void fclose(FILE *stream)
Закончить работу с файлом
Definition: stdio.c:213
fopen
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
ftell
int ftell(FILE *stream)
Текущая позиция считывания в файле
Definition: stdio.c:287
fread
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
FILE
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21