Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишу игровой движок на C++. 020. Загрузка bmp. Создание текстуры. Вывод 2D изображения.

Войти
Регистрация
Восстановить пароль
Исходные коды движка - https://github.com/532235/GoST
Документация

Другой хобби-проект в группе в вк https://vk.com/club154291467
Оценить эту запись

Пишу игровой движок на C++. 020. Загрузка bmp. Создание текстуры. Вывод 2D изображения.

Запись от 532235 размещена 18.12.2017 в 18:21

Чтение BMP картинки.
Загружаемые форматы:

32 bit
32 bit - x8r8g8b8
24 bit
16 bit - x4r4g4b4
16 bit - a4r4g4b4
16 bit - x1r5g5b5
16 bit - a1r5g5b5
16 bit - r5g6b5
8 bit
8 bit rle
4 bit
1 bit - монохромный

декодирование 8 bit rle взято у irrlicht.
4 bit rle не доделал, но ошибки не вызовет при чтении

Цвет текстуры D3D11 имеет формат R8G8B8A8
В gtImage сделал конвертацию в этот формат.

Данные в gtImage хранятся именно как в оригинале (кроме 8bit и 4bit bmp).
При создании тектсуры из gtImage вызывается функция конвертирования.

bmp картинки хранятся в перевёрнутом вверх-вниз состоянии.
для решения этого вопроса в gtImage добавил функцию отражения по вертикали.
так же добавил функцию инвертирования пикселя (для основных форматов пикселя), типа, был RGB стал BGR (без изменения типа формата).

gtImage.h (такой стиль, чтобы алгоритм был понятнее для восприятия)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
class gtMainSystem;
    struct gtImage : public gtRefObject{
 
        gtImage( void ):
            format( Format::FMT_R8G8B8A8 ),
            width( 0u ),
            height( 0u ),
            bits( 32u ),
            mipCount( 1u ),
            data( nullptr ),
            dataSize( 0u ),
            pitch( 0u )
        {}
 
        virtual ~gtImage( void ){
            if( data ){
                delete []data;
                data = nullptr;
            }
        }
 
 
        enum Format{
 
            FMT_ONE_BIT,
            FMT_A1R5G5B5,
            FMT_X1R5G5B5,
            FMT_A4R4G4B4,
            FMT_X4R4G4B4,
            FMT_R5G6B5,
            FMT_X8R8G8B8,
            FMT_A8R8G8B8,
 
            FMT_R8G8B8A8,
 
            FMT_R8G8B8,
 
 
            //  OpenGL
            FMT_COMPRESSED_RGBA_S3TC_DXT1 = 0x83F1,
            FMT_COMPRESSED_RGBA_S3TC_DXT3 = 0x83F2,
            FMT_COMPRESSED_RGBA_S3TC_DXT5 = 0x83F3
 
        }format;
 
            //  ширина
        u32     width;
 
            //  высота
        u32     height;
 
            //  биты на пиксель
        u32     bits;
 
            //  количество mipMap. 1 - основная картинка
        u32     mipCount;
 
        u8  *   data;
        u32     dataSize;
 
        u32     pitch;
 
            //  конвертирует не сжатый формат в указанный
        void    convert( Format newFormat ){
            if( newFormat == format ) return;
 
            if( format == FMT_R8G8B8 ){
                if( newFormat == FMT_A8R8G8B8 ){
                    __R8G8B8_to_A8R8G8B8();
                }else if( newFormat == FMT_R8G8B8A8 ){
                    __R8G8B8_to_R8G8B8A8();
                }else if( newFormat == FMT_X8R8G8B8 ){
                    __R8G8B8_to_A8R8G8B8();
                }
 
            //  ==================================================
            }else if( format == FMT_A8R8G8B8 ){
                if( newFormat == FMT_R8G8B8 ){
                    __A8R8G8B8_to_R8G8B8();
                }else if( newFormat == FMT_R8G8B8A8 ){
                    __A8R8G8B8_to_R8G8B8A8();
                }else if( newFormat == FMT_X8R8G8B8 ){
                    __A8R8G8B8_to_X8R8G8B8();
                }
            //  ==================================================
            }else if( format == FMT_X8R8G8B8 ){
                if( newFormat == FMT_R8G8B8 ){
                    __A8R8G8B8_to_R8G8B8();
                }else if( newFormat == FMT_R8G8B8A8 ){
                    __A8R8G8B8_to_R8G8B8A8();
                }else if( newFormat == FMT_A8R8G8B8 ){
                    //__X8R8G8B8_to_A8R8G8B8();
                }
 
            //  ==================================================
            }else if( format == FMT_R8G8B8A8 ){
                if( newFormat == FMT_R8G8B8 ){
                    __R8G8B8A8_to_R8G8B8();
                }else if( newFormat == FMT_X8R8G8B8 ){
                    __R8G8B8A8_to_X8R8G8B8();
                }else if( newFormat == FMT_A8R8G8B8 ){
                    __R8G8B8A8_to_A8R8G8B8();
                }
            
                //  ==================================================
            }else if( format == FMT_X4R4G4B4 ){
                if( newFormat == FMT_R8G8B8A8 ){
                    __X4R4G4B4_to_R8G8B8A8();
                }else if( newFormat == FMT_A8R8G8B8 ){
                    __X4R4G4B4_to_A8R8G8B8();
                }else if( newFormat == FMT_X8R8G8B8 ){
                    __X4R4G4B4_to_A8R8G8B8();
                }else if( newFormat == FMT_R8G8B8 ){
                    __X4R4G4B4_to_R8G8B8();
                }
            
                //  ==================================================
            }else if( format == FMT_X1R5G5B5 ){
                if( newFormat == FMT_R8G8B8A8 ){
                    __X1R5G5B5_to_R8G8B8A8();
                }
 
                //  ==================================================
            }else if( format == FMT_A1R5G5B5 ){
                if( newFormat == FMT_R8G8B8A8 ){
                    __A1R5G5B5_to_R8G8B8A8();
                }
 
            }else if( format == FMT_R5G6B5 ){
                if( newFormat == FMT_R8G8B8A8 ){
                    __R5G6B5_to_R8G8B8A8();
                }
 
            }else if( format == FMT_ONE_BIT ){
                if( newFormat == FMT_R8G8B8A8 ){
                    __1_to_R8G8B8A8();
                }
            
                    //  ==================================================
            }else if( format == FMT_A4R4G4B4 ){
                if( newFormat == FMT_R8G8B8A8 ){
                    __X4R4G4B4_to_R8G8B8A8();
                }else if( newFormat == FMT_A8R8G8B8 ){
                    __X4R4G4B4_to_A8R8G8B8();
                }else if( newFormat == FMT_X8R8G8B8 ){
                    __X4R4G4B4_to_A8R8G8B8();
                }else if( newFormat == FMT_R8G8B8 ){
                    __X4R4G4B4_to_R8G8B8();
                }
            }
 
            format = newFormat;
        }
 
        void    flipPixel( void ){
            if( !data ) return;
            switch( format ){
            case gost::gtImage::FMT_ONE_BIT:
                break;
            
            case gost::gtImage::FMT_A1R5G5B5:
                __flip_pixel_A1R5G5B5();
                break;
            case gost::gtImage::FMT_X1R5G5B5:
                __flip_pixel_X1R5G5B5();
                break;
            case gost::gtImage::FMT_A4R4G4B4:
                __flip_pixel_X4R4G4B4();
                break;
            case gost::gtImage::FMT_X4R4G4B4:
                __flip_pixel_X4R4G4B4();
                break;
            case gost::gtImage::FMT_R5G6B5:
                __flip_pixel_R5G6B5();
                break;
            case gost::gtImage::FMT_X8R8G8B8:
                __flip_pixel_X8R8G8B8();
                break;
            case gost::gtImage::FMT_A8R8G8B8:
                __flip_pixel_A8R8G8B8();
                break;
            case gost::gtImage::FMT_R8G8B8A8:
                __flip_pixel_A8R8G8B8();
                break;
            case gost::gtImage::FMT_R8G8B8:
                __flip_pixel_R8G8B8();
                break;
            case gost::gtImage::FMT_COMPRESSED_RGBA_S3TC_DXT1:
                break;
            case gost::gtImage::FMT_COMPRESSED_RGBA_S3TC_DXT3:
                break;
            case gost::gtImage::FMT_COMPRESSED_RGBA_S3TC_DXT5:
                break;
            default:
                break;
            }
        }
 
            //  отразит по вертикали
        void flipVertical( void ){
            u8 * line;
            gtMainSystem::getInstance()->allocateMemory( (void**)&line, pitch );
 
            u8 * p_Up = &data[ 0u ];
            u8 * p_Down = &data[ pitch * height - pitch ];
 
            for( u32 i = 0u, offset = 0u; i < height / 2u; ++i ){
 
                memcpy( line, p_Up, pitch );
                
                memcpy( p_Up, p_Down, pitch );
 
                memcpy( p_Down, line, pitch );
 
                p_Up += pitch;
                p_Down -= pitch;
 
            }
 
            gtMainSystem::getInstance()->freeMemory( (void**)&line );
        }
        
    private:
 
        //  =================   FLIP    PIXEL ============
        void __flip_pixel_A8R8G8B8( void ){
            for( u32 i = 0u; i < dataSize; ){
                u8 a = data[ i ];
                u8 r = data[ i+1u ];
                u8 g = data[ i+2u ];
                u8 b = data[ i+3u ];
                data[ i ] = b;
                data[ i+1u ] = g;
                data[ i+2u ] = r;
                data[ i+3u ] = a;
                i += 4u;
            }
        }
 
        void __flip_pixel_X8R8G8B8( void ){
            for( u32 i = 0u; i < dataSize; ){
                u8 r = data[ i+1u ];
                u8 g = data[ i+2u ];
                u8 b = data[ i+3u ];
                data[ i+1u ] = b;
                data[ i+2u ] = g;
                data[ i+3u ] = r;
                i += 4u;
            }
        }
 
        void __flip_pixel_X4R4G4B4( void ){
            const u32 redMask = 3840u;
            const u32 greenMask = 240u;
            const u32 blueMask = 15u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
            for( u32 i = 0u; i < sz; ++i ){
                u16 pixel   = p[ i ];
                u16 red     = (pixel & redMask)>>8;
                u16 green   = (pixel & greenMask)>>4;
                u16 blue    = (pixel & blueMask);
 
                p[ i ] = red;
                p[ i ] |= green<<4;
                p[ i ] |= blue<<8;
            }
        }
 
        void __flip_pixel_R5G6B5( void ){
            const u32 redMask = 63488u;
            const u32 greenMask = 2016u;
            const u32 blueMask = 31u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
            for( u32 i = 0u; i < sz; ++i ){
                u16 pixel   = p[ i ];
                u16 red     = (pixel & redMask)>>11;
                u16 green   = (pixel & greenMask)>>6;
                u16 blue    = (pixel & blueMask);
 
                p[ i ] = red;
                p[ i ] |= green<<6;
                p[ i ] |= blue<<11;
            }
        }
 
        void __flip_pixel_X1R5G5B5( void ){
            const u32 redMask = 31744u;
            const u32 greenMask = 992u;
            const u32 blueMask = 31u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
            for( u32 i = 0u; i < sz; ++i ){
                u16 pixel   = p[ i ];
                u16 red     = (pixel & redMask)>>10;
                u16 green   = (pixel & greenMask)>>5;
                u16 blue    = (pixel & blueMask);
 
                p[ i ] = red;
                p[ i ] |= green<<5;
                p[ i ] |= blue<<10;
            }
        }
 
        void __flip_pixel_A1R5G5B5( void ){
            const u32 alphaMask = 32768u;
            const u32 redMask = 31744u;
            const u32 greenMask = 992u;
            const u32 blueMask = 31u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
            for( u32 i = 0u; i < sz; ++i ){
                u16 pixel   = p[ i ];
                u16 alpha   = (pixel & alphaMask)>>15;
                u16 red     = (pixel & redMask)>>10;
                u16 green   = (pixel & greenMask)>>5;
                u16 blue    = (pixel & blueMask);
 
                p[ i ] = alpha;
                p[ i ] |= red<<5;
                p[ i ] |= green<<10;
                p[ i ] |= blue<<15;
            }
        }
 
        void __flip_pixel_R8G8B8( void ){
            for( u32 i = 0u; i < dataSize; ){
                u8 red = data[ i ];
                data[ i ] = data[ i+2u ];
                data[ i+2u ] = red;
                i += 3u;
            }
        }
 
        //  ===================     CONVERT     =======================================
        void __R8G8B8_to_A8R8G8B8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize + (dataSize / 3u);
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            u32 * data32 = reinterpret_cast<u32*>(newData);
 
            for( u32 i = 0u, count = 0u; i < dataSize; ++data32 ){
                *data32 = GT_MAKEFOURCC( 255, data[ i ], data[ i+1u ], data[ i+2u ] );
                i += 3u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
 
        void __A8R8G8B8_to_R8G8B8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize - (dataSize / 4u);
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            for( u32 i = 0u, count = 0u; i < dataSize; ){
                newData[ count ] = data[ i+1 ];
                newData[ count+1 ] = data[ i+2 ];
                newData[ count+2 ] = data[ i+3 ];
                
                i += 4u;
                count += 3u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 3u;
        }
 
 
        void __A8R8G8B8_to_R8G8B8A8( void ){
            for( u32 i = 0u; i < dataSize; ){
                u8 a = data[ i ];
                u8 r = data[ i+1u ];
                u8 g = data[ i+2u ];
                u8 b = data[ i+3u ];
                data[ i ] = r;
                data[ i+1u ] = g;
                data[ i+2u ] = b;
                data[ i+3u ] = a;
                i += 4u;
            }
        }
 
        void __A8R8G8B8_to_X8R8G8B8( void ){
            for( u32 i = 0u; i < dataSize; ){
                data[ i ] = 255;
                i += 4u;
            }
        }
 
        void __R8G8B8_to_R8G8B8A8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize + (dataSize / 3u);
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            u32 * data32 = reinterpret_cast<u32*>(newData);
 
            for( u32 i = 0u, count = 0u; i < dataSize; ++data32 ){
                *data32 = GT_MAKEFOURCC( data[ i ], data[ i+1u ], data[ i+2u ], 255 );
                i += 3u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
        void __R8G8B8A8_to_R8G8B8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize - (dataSize / 4u);
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            for( u32 i = 0u, count = 0u; i < dataSize; ){
                newData[ count ] = data[ i ];
                newData[ count+1 ] = data[ i+1 ];
                newData[ count+2 ] = data[ i+2 ];
                
                i += 4u;
                count += 3u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 3u;
        }
 
        void __R8G8B8A8_to_X8R8G8B8( void ){
            for( u32 i = 0u; i < dataSize; ){
                u8 r = data[ i ];
                u8 g = data[ i+1u ];
                u8 b = data[ i+2u ];
                data[ i ] = 255;
                data[ i+1u ] = r;
                data[ i+2u ] = g;
                data[ i+3u ] = b;
                i += 4u;
            }
        }
 
        void __R8G8B8A8_to_A8R8G8B8( void ){
            for( u32 i = 0u; i < dataSize; ){
                u8 r = data[ i ];
                u8 g = data[ i+1u ];
                u8 b = data[ i+2u ];
                u8 a = data[ i+3u ];
                data[ i ] = a;
                data[ i+1u ] = r;
                data[ i+2u ] = g;
                data[ i+3u ] = b;
                i += 4u;
            }
        }
 
        void __X4R4G4B4_to_R8G8B8A8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize * 2;
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            const u32 redMask = 3840u;
            const u32 greenMask = 240u;
            const u32 blueMask = 15u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
 
            for( u32 i = 0u, count = 0u; i < sz; ++i ){
 
                newData[ count ] = (p[ i ]&redMask)>>8;
                newData[ count ] *= 17;
 
                newData[ count+1u ] = (p[ i ]&greenMask)>>4;
                newData[ count+1u ] *= 17;
 
                newData[ count+2u ] = (p[ i ]&blueMask);
                newData[ count+2u ] *= 17;
 
                newData[ count+3u ] = 255;
                count += 4u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
        void __X4R4G4B4_to_A8R8G8B8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize * 2;
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            const u32 redMask = 3840u;
            const u32 greenMask = 240u;
            const u32 blueMask = 15u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
 
            for( u32 i = 0u, count = 0u; i < sz; ++i ){
                
                newData[ count ] = 255;
 
                newData[ count+1u ] = (p[ i ]&redMask)>>8;
                newData[ count+1u ] *= 17;
 
                newData[ count+2u ] = (p[ i ]&greenMask)>>4;
                newData[ count+2u ] *= 17;
 
                newData[ count+3u ] = (p[ i ]&blueMask);
                newData[ count+3u ] *= 17;
 
                count += 4u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
        void __X4R4G4B4_to_R8G8B8( void ){
            u8 * newData = nullptr;
 
            u32 sz = dataSize / 2u;
 
            u32 newSize = dataSize + sz;
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            const u32 redMask = 3840u;
            const u32 greenMask = 240u;
            const u32 blueMask = 15u;
 
            u16 * p = reinterpret_cast<u16*>(data);
 
            for( u32 i = 0u, count = 0u; i < sz; ++i ){
 
                newData[ count ] = (p[ i ]&redMask)>>8;
                newData[ count ] *= 17;
 
                newData[ count+1u ] = (p[ i ]&greenMask)>>4;
                newData[ count+1u ] *= 17;
 
                newData[ count+2u ] = (p[ i ]&blueMask);
                newData[ count+2u ] *= 17;
 
                count += 3u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 3u;
        }
 
        void __X1R5G5B5_to_R8G8B8A8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize * 2;
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            const u32 redMask = 31744u;
            const u32 greenMask = 992u;
            const u32 blueMask = 31u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
 
            for( u32 i = 0u, count = 0u; i < sz; ++i ){
 
                newData[ count ] = (p[ i ]&redMask)>>10;
                newData[ count ] *= 8;
 
                newData[ count+1u ] = (p[ i ]&greenMask)>>5;
                newData[ count+1u ] *= 8;
 
                newData[ count+2u ] = (p[ i ]&blueMask);
                newData[ count+2u ] *= 8;
 
                newData[ count+3u ] = 255;
                count += 4u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
        void __A1R5G5B5_to_R8G8B8A8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize * 2;
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            const u32 alphaMask = 32768u;
            const u32 redMask = 31744u;
            const u32 greenMask = 992u;
            const u32 blueMask = 31u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
 
            for( u32 i = 0u, count = 0u; i < sz; ++i ){
 
                newData[ count ] = (p[ i ]&redMask)>>10;
                newData[ count ] *= 8;
 
                newData[ count+1u ] = (p[ i ]&greenMask)>>5;
                newData[ count+1u ] *= 8;
 
                newData[ count+2u ] = (p[ i ]&blueMask);
                newData[ count+2u ] *= 8;
 
                newData[ count+3u ] = ((p[ i ]&alphaMask)>>15) ? 255u : 0u;
                count += 4u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
        void __R5G6B5_to_R8G8B8A8( void ){
            u8 * newData = nullptr;
 
            u32 newSize = dataSize * 2;
 
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            const u32 redMask = 63488u;
            const u32 greenMask = 2016u;
            const u32 blueMask = 31u;
 
            u16 * p = reinterpret_cast<u16*>(data);
            u32 sz = dataSize / 2u;
 
            for( u32 i = 0u, count = 0u; i < sz; ++i ){
 
                newData[ count ] = (p[ i ]&redMask)>>11;
                newData[ count ] *= 8;
 
                newData[ count+1u ] = (p[ i ]&greenMask)>>6;
                newData[ count+1u ] *= 8;
 
                newData[ count+2u ] = (p[ i ]&blueMask);
                newData[ count+2u ] *= 8;
 
                newData[ count+3u ] = 255;
                count += 4u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
        void __1_to_R8G8B8A8( void ){
 
            u8 * newData = nullptr;
            u32 newSize = dataSize * 8u * 4u;
            gtMainSystem::getInstance()->allocateMemory( (void**)&newData, newSize );
 
            u32 * data32 = reinterpret_cast<u32*>(newData);
 
            u32 sz = newSize / 4u;
            for( u32 i = 0u, count = 0u; i < sz; ){
                data32[ i+7 ] = ((data[ count ] & 1u))?0x0:0xFFFFFFFF;
                data32[ i+6u ] = ((data[ count ] & 2u)>>1u)?0x0:0xFFFFFFFF;
                data32[ i+5u ] = ((data[ count ] & 4u)>>2u)?0x0:0xFFFFFFFF;
                data32[ i+4u ] = ((data[ count ] & 8u)>>3u)?0x0:0xFFFFFFFF;
                data32[ i+3u ] = ((data[ count ] & 16u)>>4u)?0x0:0xFFFFFFFF;
                data32[ i+2u ] = ((data[ count ] & 32u)>>5u)?0x0:0xFFFFFFFF;
                data32[ i+1u ] = ((data[ count ] & 64u)>>6u)?0x0:0xFFFFFFFF;
                data32[ i+0u ] = ((data[ count ] & 128u)>>7u)?0x0:0xFFFFFFFF;
                count++;
                i += 8u;
            }
 
            dataSize = newSize;
            gtMainSystem::getInstance()->freeMemory( (void**)&data );
            data = newData;
            pitch = width * 4u;
        }
 
    };
Сделал так чтобы gtImage видел gtMainSystem. Передвинул #include повыше, и объявил нужные классы.

------------------------
gtBMP.gpl
Здесь я не стал умничать, всё написано в одном файле.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
//  упаковка, типа __attribute__(packed)
    //  размер BitmapHeader по настоящему становится 14 байт
    #pragma pack(push,2)
    struct BitmapHeader{
        u16     bfType;
        u32     bfSize;
        u16     bfReserved1;
        u16     bfReserved2;
        u32     bfOffBits;
    };
    #pragma pack(pop)
 
    //  для 8 и 4 битных картинок
    //  ячейка таблицы
    struct rgbquad{
        u8 Blue;
        u8 Green;
        u8 Red;
        u8 Reserved;
    };
 
    struct ciexyzTriple{
        v3i     ciexyzRed;
        v3i     ciexyzGreen;
        v3i     ciexyzBlue;
    };
    //  каждая новая версия BITMAPHEADER является продолжением предидущей
    //  поэтому для чтения header любого bmp подойдёт последняя версия BMPHEADER
    // п0следняя это версия или нет - хз
    // взял у windows 8.1 sdk
    
    struct BitmapInfoHeader_v5{ 
        u32         bV5Size;        //  размер info header в файле
        s32         bV5Width;       //  ширина
        s32         bV5Height;      //  высота
        u16         bV5Planes;      //  хз что это, всегда 1
        u16         bV5BitCount;    //  биты
        u32         bV5Compression; //  1 - RLE 8bit, 2 - RLE 4bit, 3 или что-то, видимо, специальные обозначения у разработчиков 2D редакторов.
        u32         bV5SizeImage;   //  размер массива пикселей/индексов
        s32         bV5XPelsPerMeter;// размер в чём-то, видимо для печати или вывода ещё кудато
        s32         bV5YPelsPerMeter;// для обычного использования в ПК не обязательно
        u32         bV5ClrUsed;     //  обычно тут ноль
        u32         bV5ClrImportant;//  и тут ноль
        u32         bV5RedMask;     //  для определения позиции цветов
        u32         bV5GreenMask;   //  в форматах типа x1r5g5b5
        u32         bV5BlueMask;
        u32         bV5AlphaMask;
        u32         bV5CSType;      //  далее информация для более специализированного
        ciexyzTriple bV5Endpoints;  //  использования.
        u32         bV5GammaRed;    //  для передачи простой картинки достаточно того
        u32         bV5GammaGreen;  //  что указано выше. А эта часть нужна для, например,
        u32         bV5GammaBlue;   //  тех кто делает видео плеер, видео редактор
        u32         bV5Intent;      //  что-то типа этого. Как бы универсальное решение
        u32         bV5ProfileData; //  от Microsoft
        u32         bV5ProfileSize;
        u32         bV5Reserved;
    };
 
    //  изменённые функции декодирования, взяты у irrlicht
    void decompress4BitRLE( u8*& rleData, u8*& inds, s32 size, s32 width, s32 height ); 
    void decompress8BitRLE( u8*& rleData, u8*& inds, s32 size, s32 width, s32 height );
 
        //  вызывается из gost.dll
    GT_API bool PluginLoadImage( gtImage* image, gtString* fileName ){
 
        if( !gtFileSystem::existFile( *fileName ) ){
            gtLogWriter::printWarning( u"BMP Plugin: File not exist [%s]", fileName->data() );
            return false;
        }
 
        BitmapHeader header;
        BitmapInfoHeader_v5 info;
 
        {   //  отдельный блок для того чтобы файл автоматически закрылся
            /*так же добавил openFileForReadBin чтоб быстро открыть файл для bin чтения*/
            gtFile_t file = util::openFileForReadBin( *fileName ); 
            if( !file.data() ){
                gtLogWriter::printWarning( u"BMP Plugin: Can not open file [%s]", fileName->data() );
                return false;
            }
 
            u32 sz = file->size();
            if( sz < sizeof( BitmapHeader ) + sizeof( BitmapInfoHeader_v5 ) ){
                gtLogWriter::printWarning( u"BMP Plugin: Bad file size [%s]", fileName->data() );
                return false;
            }
 
            //  чтение заголовка
            u32 readNum = file->read( reinterpret_cast<u8*>(&header), sizeof(BitmapHeader) );
 
            if( readNum < sizeof(BitmapHeader) ){
                gtLogWriter::printWarning( u"BMP Plugin: Bad header [%s]", fileName->data() );
                return false;
            }
 
            if( !header.bfType == 19778u ){
                gtLogWriter::printWarning( u"BMP Plugin: Bad magic [%s]", fileName->data() );
                return false;
            }
 
            //  чтение основной информации
            readNum = file->read( reinterpret_cast<u8*>(&info), sizeof(BitmapInfoHeader_v5) );
        }
 
        if( info.bV5Size < 40u ){
            gtLogWriter::printWarning( u"BMP Plugin: Bad header size [%s]", fileName->data() );
            return false;
        }
 
        if( !info.bV5Width ){
            gtLogWriter::printWarning( u"BMP Plugin: Bad width [%s]", fileName->data() );
            return false;
        }
 
        if( !info.bV5Height ){
            gtLogWriter::printWarning( u"BMP Plugin: Bad height [%s]", fileName->data() );
            return false;
        }
 
        if( info.bV5BitCount != 1u &&
            info.bV5BitCount != 4u &&
            info.bV5BitCount != 8u &&
            info.bV5BitCount != 16u &&
            info.bV5BitCount != 24u &&
            info.bV5BitCount != 32u ){
            gtLogWriter::printWarning( u"BMP Plugin: Bad bit count [%s]", fileName->data() );
            return false;
        }
 
        image->width    = info.bV5Width;
        image->height   = info.bV5Height;
        image->bits     = info.bV5BitCount;
 
        gtFile_t file = util::openFileForReadBin( *fileName );
        if( !file.data() ){
            gtLogWriter::printWarning( u"BMP Plugin: Can not open file [%s]", fileName->data() );
            return false;
        }
 
 
        if( image->bits == 24u ){
            
            /* праильно было бы сделать BGR, а потом конвертировать в RGB, но сделал flipPixel() */
            image->format   = gtImage::Format::FMT_R8G8B8;
            image->pitch    = image->width * 3u;
            image->dataSize = image->pitch * image->height;
 
            if( !gtMainSystem::getInstance()->allocateMemory( (void**)&image->data, image->dataSize ) ){
                gtLogWriter::printWarning( u"BMP Plugin: can not allocate memory. [%s]", fileName->data() );
                return false;
            }
 
            file->seek( 54u, gtFile::SeekPos::ESP_BEGIN );
 
            u32 readNum = file->read( image->data, image->dataSize );
            if( readNum != image->dataSize ){
                gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                return false;
            }
            
            /*BGR -> RGB*/
            image->flipPixel();
 
        }else if( image->bits == 32u ){
 
            if( info.bV5Size != 40u && info.bV5Size != 56u ){
                gtLogWriter::printWarning( u"BMP Plugin: unsupported format. [%s]", fileName->data() );
                return false;
            }
 
            image->pitch = image->width * 4u;
 
            if( info.bV5Size == 40u ){
                file->seek( 54u, gtFile::SeekPos::ESP_BEGIN );
                image->format = gtImage::Format::FMT_A8R8G8B8;
            }else{
                file->seek( 70u, gtFile::SeekPos::ESP_BEGIN );
                image->format = gtImage::Format::FMT_X8R8G8B8;
            }
 
            image->dataSize = image->pitch * image->height;
 
            if( !gtMainSystem::getInstance()->allocateMemory( (void**)&image->data, image->dataSize ) ){
                gtLogWriter::printWarning( u"BMP Plugin: can not allocate memory. [%s]", fileName->data() );
                return false;
            }
 
            u32 readNum = file->read( image->data, image->dataSize );
 
            if( readNum != image->dataSize ){
                gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                return false;
            }
 
            image->flipPixel();
 
        }else if( image->bits == 16u ){
 
            if( info.bV5Size != 40u && info.bV5Size != 56u ){
                gtLogWriter::printWarning( u"BMP Plugin: unsupported format. [%s]", fileName->data() );
                return false;
            }
 
            image->pitch = image->width * 2u;
 
            if( info.bV5Size == 40u ){ // x1r5g5b5
                file->seek( 54u, gtFile::SeekPos::ESP_BEGIN );
                image->format = gtImage::Format::FMT_X1R5G5B5;
            }else{
                if( info.bV5RedMask == 3840u &&
                    info.bV5GreenMask == 240u && 
                    info.bV5BlueMask == 15u ){
                    if( info.bV5AlphaMask ){
                        image->format = gtImage::Format::FMT_A4R4G4B4;
                    }else{
                        image->format = gtImage::Format::FMT_X4R4G4B4;
                    }
                }else if( info.bV5RedMask == 63488u &&
                    info.bV5GreenMask == 2016u && 
                    info.bV5BlueMask == 31u ){
                    image->format = gtImage::Format::FMT_R5G6B5;
                }else if( info.bV5RedMask == 31744u &&
                    info.bV5GreenMask == 992u && 
                    info.bV5BlueMask == 31u ){
                    if( info.bV5AlphaMask )
                        image->format = gtImage::Format::FMT_A1R5G5B5;
                }else{
                    gtLogWriter::printWarning( u"BMP Plugin: unsupported format. [%s]", fileName->data() );
                    return false;
                }
                file->seek( 70u, gtFile::SeekPos::ESP_BEGIN );
            }
 
            image->dataSize = image->pitch * image->height;
 
            if( !gtMainSystem::getInstance()->allocateMemory( (void**)&image->data, image->dataSize ) ){
                gtLogWriter::printWarning( u"BMP Plugin: can not allocate memory. [%s]", fileName->data() );
                return false;
            }
 
            u32 readNum = file->read( image->data, image->dataSize );
 
            if( readNum != image->dataSize ){
                gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                return false;
            }
 
 
 
        }else if( image->bits == 8u ){
            
            image->format = gtImage::Format::FMT_R8G8B8A8;
            image->pitch = image->width * 4u;
            image->dataSize = image->pitch * image->height;
 
            
            file->seek( 54u, gtFile::SeekPos::ESP_BEGIN );
 
            u32 tableSize = header.bfOffBits - 54u;
 
            std::unique_ptr<u8[]> table( new u8[ tableSize ] );
 
            file->read( table.get(), tableSize );
            
            rgbquad * quadTable = reinterpret_cast<rgbquad*>(table.get());
            
            file->seek( header.bfOffBits, gtFile::SeekPos::ESP_BEGIN );
 
            if( !gtMainSystem::getInstance()->allocateMemory( (void**)&image->data, image->dataSize ) ){
                gtLogWriter::printWarning( u"BMP Plugin: can not allocate memory. [%s]", fileName->data() );
                return false;
            }
 
            u32 indSize = image->width * image->height;
            std::unique_ptr<u8[]> inds( new u8[ indSize ] );
 
            if( !info.bV5Compression ){
                u32 readNum = file->read( inds.get(), indSize );
                if( readNum != indSize ){
                    gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                    gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                    return false;
                }
            }else{
                std::unique_ptr<u8[]> rle( new u8[ info.bV5SizeImage ] );
                u32 readNum = file->read( rle.get(), info.bV5SizeImage );
                if( readNum != info.bV5SizeImage ){
                    gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                    gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                    return false;
                }
 
                decompress8BitRLE( rle._Myptr(), inds._Myptr(), info.bV5SizeImage, image->width, image->height );
            }
 
            u8 * u8_ptr = inds.get();
 
            for( u32 i = 0u, count = 0u; i < indSize; ){
                image->data[ count ] = quadTable[ u8_ptr[ i ] ].Red;
                image->data[ count+1u ] = quadTable[ u8_ptr[ i ] ].Green;
                image->data[ count+2u ] = quadTable[ u8_ptr[ i ] ].Blue;
                image->data[ count+3u ] = 255u;
                count += 4u;
                i += 1u;
            }
 
            
 
        }else if( image->bits == 4u ){
 
            image->format = gtImage::Format::FMT_R8G8B8A8;
 
            image->pitch = image->width * 4u;
 
            image->dataSize = image->pitch * image->height;
 
            
            file->seek( 54u, gtFile::SeekPos::ESP_BEGIN );
 
            u32 tableSize = header.bfOffBits - 54u;
 
            std::unique_ptr<u8[]> table( new u8[ tableSize ] );
 
            file->read( table.get(), tableSize );
 
 
            rgbquad * quadTable = reinterpret_cast<rgbquad*>(table.get());
            
            file->seek( header.bfOffBits, gtFile::SeekPos::ESP_BEGIN );
 
            
            u32 indSize = image->width * image->height/2;
 
            if( !gtMainSystem::getInstance()->allocateMemory( (void**)&image->data, image->dataSize ) ){
                gtLogWriter::printWarning( u"BMP Plugin: can not allocate memory. [%s]", fileName->data() );
                return false;
            }
 
 
            std::unique_ptr<u8[]> inds( new u8[ indSize ] );
 
            u8 * u8_ptr = inds.get();
 
            if( !info.bV5Compression ){
                u32 readNum = file->read( inds.get(), indSize );
                if( readNum != indSize ){
                    gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                    gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                    return false;
                }
            }else{
                std::unique_ptr<u8[]> rle( new u8[ info.bV5SizeImage ] );
                u32 readNum = file->read( rle.get(), info.bV5SizeImage );
                if( readNum != info.bV5SizeImage ){
                    gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                    gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                    return false;
                }
 
                u8 * rlePtr = rle.get();
                decompress4BitRLE( rlePtr, u8_ptr, indSize, image->width, image->height );
 
            }
                
            
 
 
            for( u32 i = 0u, count = 0u; i < indSize; ){
 
                u8 color = u8_ptr[ i ];
                u8 part1 = color & 15u;
                u8 part2 = (color & 240u)>>4u;
 
                image->data[ count ] = quadTable[ part1 ].Red;
                image->data[ count+1u ] = quadTable[ part1 ].Green;
                image->data[ count+2u ] = quadTable[ part1 ].Blue;
                image->data[ count+3u ] = 255u;
                image->data[ count+4u ] = quadTable[ part2 ].Red;
                image->data[ count+5u ] = quadTable[ part2 ].Green;
                image->data[ count+6u ] = quadTable[ part2 ].Blue;
                image->data[ count+7u ] = 255u;
                count += 8u;
                i += 1u;
            }
 
            
 
 
        }else if( image->bits == 1u ){
            image->format = gtImage::Format::FMT_ONE_BIT;
            image->pitch = image->width;
            image->dataSize = info.bV5SizeImage;
            file->seek( header.bfOffBits, gtFile::SeekPos::ESP_BEGIN );
            if( !gtMainSystem::getInstance()->allocateMemory( (void**)&image->data, image->dataSize ) ){
                gtLogWriter::printWarning( u"BMP Plugin: can not allocate memory. [%s]", fileName->data() );
                return false;
            }
            u32 readNum = file->read( image->data, image->dataSize );
            if( readNum != image->dataSize ){
                gtLogWriter::printWarning( u"BMP Plugin: can not read file. [%s]", fileName->data() );
                gtMainSystem::getInstance()->freeMemory( (void**)&image->data );
                return false;
            }
 
            //  фукнция отразить по вертикали не может работать с ONE_BIT по этому конвертация здесь.
            image->convert( gtImage::Format::FMT_R8G8B8A8 );
        }else{
            return false;
        }
 
        image->flipVertical();
 
        return true;
    }
 
 
//  irrlicht
void decompress4BitRLE( u8*& rleData, u8*& inds, s32 size, s32 width, s32 height ){
        s32 lineWidth = (width+1)/2/*+pitch*/;
        u8* p = rleData;
        u8* newBmp = inds;
        u8* d = newBmp;
        u8* ******d = newBmp + lineWidth*height;
        s32 line = 0;
        s32 shift = 4;
 
        while( rleData - p < size && d < ******d){
            if( *p == 0 ){
                ++p;
 
                switch( *p ){
                case 0: // end of line
                    ++p;
                    ++line;
                    d = newBmp + (line*lineWidth);
                    shift = 4;
                    break;
                case 1: // end of bmp
                    return;
                case 2:
                    {
                        ++p;
                        s32 x = (u8)*p; ++p;
                        s32 y = (u8)*p; ++p;
                        d += x/2 + y*lineWidth;
                        shift = x%2==0 ? 4 : 0;
                    }
                    break;
                default:
                    {
                        // absolute mode
                        s32 count = (u8)*p; ++p;
                        s32 readAdditional = ((2-((count)%2))%2);
                        s32 readShift = 4;
                        s32 i;
 
                        for (i=0; i<count; ++i)
                        {
                            s32 color = (((u8)*p) >> readShift) & 0x0f;
                            readShift -= 4;
                            if (readShift < 0)
                            {
                                ++*p;
                                readShift = 4;
                            }
 
                            u8 mask = 0x0f << shift;
                            *d = (*d & (~mask)) | ((color << shift) & mask);
 
                            shift -= 4;
                            if (shift < 0)
                            {
                                shift = 4;
                                ++d;
                            }
 
                        }
 
                        for (i=0; i<readAdditional; ++i)
                            ++p;
                    }
                }
            }
            else
            {
                s32 count = (u8)*p; ++p;
                s32 color1 = (u8)*p; color1 = color1 & 0x0f;
                s32 color2 = (u8)*p; color2 = (color2 >> 4) & 0x0f;
                ++p;
 
                for (s32 i=0; i<count; ++i)
                {
                    u8 mask = 0x0f << shift;
                    u8 toSet = (shift==0 ? color1 : color2) << shift;
                    *d = (*d & (~mask)) | (toSet & mask);
 
                    shift -= 4;
                    if (shift < 0)
                    {
                        shift = 4;
                        ++d;
                    }
                }
            }
        }
    }
 
    void decompress8BitRLE( u8*& rleData, u8*& inds, s32 size, s32 width, s32 height ){
        u8* p = rleData;
        u8* newBmp = inds;
        u8* d = newBmp;
        u8* ******d = newBmp + (width*height);
        s32 line = 0;
 
        while( rleData - p < size && d < ******d)
        {
            if (*p == 0)
            {
                ++p;
 
                switch(*p)
                {
                case 0: // end of line
                    ++p;
                    ++line;
                    d = newBmp + (line*(width));
                    break;
                case 1: // end of bmp
                    return;
                case 2:
                    ++p; d +=(u8)*p;  // delta
                    ++p; d += ((u8)*p)*(width);
                    ++p;
                    break;
                default:
                    {
                        // absolute mode
                        s32 count = (u8)*p; ++p;
                        s32 readAdditional = ((2-(count%2))%2);
                        s32 i;
 
                        for (i=0; i<count; ++i)
                        {
                            *d = *p;
                            ++p;
                            ++d;
                        }
 
                        for (i=0; i<readAdditional; ++i)
                            ++p;
                    }
                }
            }
            else
            {
                s32 count = (u8)*p; ++p;
                u8 color = *p; ++p;
                for (s32 i=0; i<count; ++i)
                {
                    *d = color;
                    ++d;
                }
            }
        }
    }

------------------------
Создание текстуры из картинки.

класс gtDriver. Добавляю метод.
C++
1
2
    //  Создаёт текстуру из gtImage
virtual gtTexture*  createTexture( gtImage* ) = 0;
Реализация в render плагине.
Нужно сделать класс текстуры для D3D11.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#pragma once
#ifndef __GT_TEXTURE_D3D11_H__
#define __GT_TEXTURE_D3D11_H__
 
 
namespace gost{
 
    class gtTextureD3D11 GT_FINAL : public gtTexture{
 
            //  тип текстуры
        gtTextureType m_type;
 
            //  текстура
        ID3D11Resource*         m_texture;
        ID3D11ShaderResourceView*   m_textureResView;
        ID3D11SamplerState*         m_samplerState;
 
        gtDriverD3D11* m_driver;
 
        HRESULT createSamplerState( 
            D3D11_FILTER filter, 
            D3D11_TEXTURE_ADDRESS_MODE addressMode,
            u32 anisotropic_level = 1 );
    public:
 
        gtTextureD3D11( gtDriverD3D11* );
        virtual ~gtTextureD3D11( void );
 
        bool init( gtImage* image );
 
        ID3D11ShaderResourceView* const * getResourceView( void );
        ID3D11SamplerState* const * getSamplerState( void );
 
        //  ===========================================
            //  возвратит тип текстуры
        gtTextureType   getType( void );
 
    };
 
}
 
#endif
реализация
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
gtTextureD3D11::gtTextureD3D11( gtDriverD3D11* d ):
    m_type( gtTextureType::TEXTURE_TYPE_2D ),
    m_texture( nullptr ),
    m_textureResView( nullptr ),
    m_samplerState( nullptr ),
    m_driver( d )
{}
 
gtTextureD3D11::~gtTextureD3D11( void ){
 
    if( m_samplerState ){
        m_samplerState->Release();
        m_samplerState = nullptr;
    }
 
    if( m_textureResView ){
        m_textureResView->Release();
        m_textureResView = nullptr;
    }
 
    if( m_texture ){
        m_texture->Release();
        m_texture = nullptr;
    }
}
 
bool gtTextureD3D11::init( gtImage* image ){
 
    if( !image ) return false;
 
    image->convert( gtImage::Format::FMT_R8G8B8A8 );
 
    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory( &desc, sizeof( desc ) );
    desc.Width  =   image->width;
    desc.Height =   image->height;
    desc.Format =   DXGI_FORMAT_R8G8B8A8_UNORM;
    desc.SampleDesc.Count   =   1;
    desc.SampleDesc.Quality =   0;
    desc.BindFlags  =   D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    desc.MiscFlags  =   D3D11_RESOURCE_MISC_GENERATE_MIPS;
    desc.ArraySize  =   1;
    desc.MipLevels  =   1;
    desc.Usage  =   D3D11_USAGE_DEFAULT;
    desc.CPUAccessFlags =   0;
 
    D3D11_SUBRESOURCE_DATA initData;
    ZeroMemory( &initData, sizeof( initData ) );
    initData.pSysMem     =  image->data;
    initData.SysMemPitch =  image->pitch;
    initData.SysMemSlicePitch = image->dataSize;
 
    ID3D11Texture2D * texture = nullptr;
 
    HRESULT hr = m_driver->getD3DDevice()->CreateTexture2D( &desc, &initData, &texture );
    if( FAILED( hr ) ){
        gtLogWriter::printWarning( u"Can't create 2D texture" );
        return false;
    }
 
    m_texture = texture;
 
    D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
    ZeroMemory( &SRVDesc, sizeof( SRVDesc ) );
    SRVDesc.Format = desc.Format;
    SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    SRVDesc.Texture2D.MostDetailedMip   =   0;
    SRVDesc.Texture2D.MipLevels = -1;
 
    hr = m_driver->getD3DDevice()->CreateShaderResourceView( m_texture,
            &SRVDesc, &this->m_textureResView );
    if( FAILED( hr ) ){
        gtLogWriter::printWarning( u"Can't create shader resource view" );
        return false;
    }
 
    D3D11_FILTER filter = D3D11_FILTER_ANISOTROPIC;
    hr = this->createSamplerState( filter, D3D11_TEXTURE_ADDRESS_WRAP, 1u );
    if( FAILED( hr ) ){
        gtLogWriter::printWarning( u"Can't create sampler state" );
        return false;
    }
 
    return true;
}
 
ID3D11ShaderResourceView * const * gtTextureD3D11::getResourceView( void ){
    return &this->m_textureResView;
}
 
ID3D11SamplerState* const * gtTextureD3D11::getSamplerState( void ){
    return &this->m_samplerState;
}
 
HRESULT gtTextureD3D11::createSamplerState( D3D11_FILTER filter, D3D11_TEXTURE_ADDRESS_MODE addressMode, u32 anisotropic_level ){
    D3D11_SAMPLER_DESC samplerDesc;
    ZeroMemory( &samplerDesc, sizeof(samplerDesc) );
    samplerDesc.Filter = filter;
 
    samplerDesc.AddressU = addressMode;
    samplerDesc.AddressV = addressMode;
    samplerDesc.AddressW = addressMode;
 
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    samplerDesc.MaxLOD = FLT_MAX;
 
    samplerDesc.MaxAnisotropy = anisotropic_level;
 
    return m_driver->getD3DDevice()->CreateSamplerState( &samplerDesc, &this->m_samplerState );
}
 
//===============================================================
    //  возвратит тип текстуры
gtTextureType   gtTextureD3D11::getType( void ){
    return m_type;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    //  Создаёт текстуру из gtImage
gtTexture*  gtDriverD3D11::createTexture( gtImage* image ){
    GT_ASSERT2( image, "image!=nullptr" );
 
    gtPtr<gtTextureD3D11> texture = gtPtrNew<gtTextureD3D11>( new gtTextureD3D11( this ) );
 
    if( !texture->init( image ) ){
        gtLogWriter::printWarning( u"Can not init D3D11 texture" );
        return nullptr;
    }
 
    texture->addRef();
 
    return texture.data();
}

-----------------------------------
наложение текстуры на поверхность
C++
1
2
3
4
5
void gtDriverD3D11::setActiveShader( gtShader* shader ){
    m_d3d11DevCon->IASetInputLayout( ((gtShaderImpl*)shader)->m_vLayout );
    m_d3d11DevCon->VSSetShader( ((gtShaderImpl*)shader)->m_vShader, 0, 0 );
    m_d3d11DevCon->PSSetShader( ((gtShaderImpl*)shader)->m_pShader, 0, 0 );
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    //  нарисует картинку
    //  rect - координаты левого верхнего и правого нижнего углов
void gtDriverD3D11::draw2DImage( const v4f& rect, const gtMaterial& material ){
    
    gtShader * shader = material.shader;
    if( !shader ){
        shader = m_shader2DStandart;
    }
        
    struct cbVerts{
        v4f v1;
        v4f v2;
        v4f v3;
        v4f v4;
        v2f t1;
        v2f t2;
        v2f t3;
        v2f t4;
    }cb;
 
    //  нужно послать в константный буффер координаты
 
    //  позиция
    cb.v1[ 0 ] = -0.5f; //x     
    cb.v1[ 1 ] = -0.5f; //y     
    cb.v1[ 2 ] = 0.5f;  //z     *
    cb.v1[ 3 ] = 1.f;
    cb.t1[ 0 ] = 0.f;   //u
    cb.t1[ 1 ] = 1.f;   //v
 
    cb.v2[ 0 ] = -0.5f; //x     *
    cb.v2[ 1 ] = 0.5f;  //y     |
    cb.v2[ 2 ] = 0.5f;  //z     *
    cb.v2[ 3 ] = 1.f;
    cb.t2[ 0 ] = 0.f;   //u
    cb.t2[ 1 ] = 0.f;   //v
 
    cb.v3[ 0 ] = 0.5f;  //x     *-----*
    cb.v3[ 1 ] = 0.5f;  //y     |   /
    cb.v3[ 2 ] = 0.5f;  //z     */
    cb.v3[ 3 ] = 1.f;
    cb.t3[ 0 ] = 1.f;   //u
    cb.t3[ 1 ] = 0.f;   //v
 
    cb.v4[ 0 ] = 0.5f;  //x     *-----*
    cb.v4[ 1 ] = -0.5f; //y     |   /
    cb.v4[ 2 ] = 0.5f;  //z     */    *
    cb.v4[ 3 ] = 1.f;
    cb.t4[ 0 ] = 1.f;   //u
    cb.t4[ 1 ] = 1.f;   //v
    //индексы указываются в шейдере в ручную с помощью SV_VertexID
 
    setActiveShader( shader );
    
    m_d3d11DevCon->IASetInputLayout( 0 );
    m_d3d11DevCon->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
 
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    m_d3d11DevCon->Map(
        ((gtShaderImpl*)shader)->m_constantBuffers[ 0 ],
        0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
 
    D3D11_BUFFER_DESC d;
    ((gtShaderImpl*)shader)->m_constantBuffers[ 0 ]->GetDesc( &d );
 
    memcpy( mappedResource.pData, &cb, d.ByteWidth );
    m_d3d11DevCon->Unmap( ((gtShaderImpl*)shader)->m_constantBuffers[ 0 ], 0 );
 
    for( u32 i = 0u; i < 16u; ++i ){
        if( !material.textureLayer[ i ].texture ) break;
 
        gtTextureD3D11* texture = (gtTextureD3D11*)material.textureLayer[ i ].texture;
 
        m_d3d11DevCon->PSSetShaderResources( i, 1, texture->getResourceView() );
        m_d3d11DevCon->PSSetSamplers( i, 1, texture->getSamplerState() );
    }
 
    m_d3d11DevCon->VSSetConstantBuffers( 0, 1, &((gtShaderImpl*)shader)->m_constantBuffers[ 0 ] );
    m_d3d11DevCon->Draw( 6, 0 );
}
и дополнение в HLSL
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
if( input.vertexId == 0 ){
        output.pos = v1;
        output.uv = t1;
    }else if ( input.vertexId == 1 ){
        output.pos = v2;
        output.uv = t2;
    }else if ( input.vertexId == 2 ){
        output.pos = v3;
        output.uv = t3;
    }else if ( input.vertexId == 3 ){
        output.pos = v1;
        output.uv = t1;
    }else if ( input.vertexId == 4 ){
        output.pos = v3;
        output.uv = t3;
    }else if ( input.vertexId == 5 ){
        output.pos = v4;
        output.uv = t4;
    }
    
    ....
    
    PSOut PSMain(VSOut input)
{
    PSOut output;
    
    float4 diffuseColor = tex2d_1.Sample(tex2D_sampler_1, input.uv);
    
    output.color = diffuseColor;
    
    output.color.a = 255;
    return output;
}

ПРОГРАММА
C++
1
2
3
4
5
6
7
8
9
10
gtImage * image = my_system->loadImage( gtFileSystem::getProgramPath() + u"bmp24bit.bmp" );
    
    // если без gtPtr, то в конце нужно вызвать texture->release();
    gtPtr<gtTexture> texture = gtPtrNew<gtTexture>( driver1->createTexture( image ) );
 
    /* software картинка больше не нужна */
    my_system->removeImage( image );
    
    gtMaterial material;
    material.textureLayer[ 0u ].texture = texture.data();


https://github.com/532235/GoST/
Миниатюры
Нажмите на изображение для увеличения
Название: yugh.JPG
Просмотров: 89
Размер:	135.5 Кб
ID:	4561  
Размещено в Игровой движок
Просмотров 258 Комментарии 0
Всего комментариев 0

Комментарии

 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.