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 }
Основные определения ядра
size_t filesize(const char *Path)
[FileIO] Возвращает размер указанного файла
Definition: fileio.c:67
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
Definition: stdio.c:315
void fclose(FILE *stream)
Закончить работу с файлом
Definition: stdio.c:213
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
int ftell(FILE *stream)
Текущая позиция считывания в файле
Definition: stdio.c:287
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21