180668a56fe34b52632507164f4aeb2e435d53ee
[tpg/acess2.git] / Usermode / Libraries / libimage_sif.so_src / main.c
1 /*
2  */
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <image.h>
8 //#include <image_sif.h>
9 #include <acess/sys.h>  // _SysDebug
10
11 // === STRUCTURES ===
12 struct sHeader
13 {
14         uint16_t        Magic;
15         uint16_t        Flags;
16         uint16_t        Width;
17         uint16_t        Height;
18 };
19
20 // === CONSTANTS ===
21
22 // === CODE ===
23 int SoMain(void)
24 {
25         return 0;
26 }
27
28 /**
29  */
30 tImage *Image_SIF_Parse(void *Buffer, size_t Size)
31 {
32         uint16_t        w, h;
33          int    ofs, i;
34         tImage  *ret;
35          int    bRevOrder;
36          int    fileOfs = 0;
37          int    comp, fmt;
38          int    sampleSize;
39         struct sHeader  *hdr = Buffer;
40          
41         _SysDebug("Image_SIF_Parse: (Buffer=%p, Size=0x%x)", Buffer, Size);
42         
43         // Get magic word and determine byte ordering
44         if(hdr->Magic == 0x51F0)        // Little Endian
45                 bRevOrder = 0;
46         else if(hdr->Magic == 0xF051)   // Big Endian
47                 bRevOrder = 1;
48         else {
49                 _SysDebug(" Image_SIF_Parse: Magic invalid (0x%x)", hdr->Magic);
50                 return NULL;
51         }
52         
53         _SysDebug(" Image_SIF_Parse: bRevOrder = %i", bRevOrder);
54         
55         // Read flags
56         comp = hdr->Flags & 7;
57         fmt = (hdr->Flags >> 3) & 7;
58         
59         // Read dimensions
60         w = hdr->Width;
61         h = hdr->Height;
62         
63         _SysDebug(" Image_SIF_Parse: Dimensions %ix%i", w, h);
64         
65         // Get image format
66         switch(fmt)
67         {
68         case 0: // ARGB 32-bit Little Endian
69                 fmt = IMGFMT_BGRA;
70                 sampleSize = 4;
71                 break;
72         case 1: // RGB 24-bit big endian
73                 fmt = IMGFMT_RGB;
74                 sampleSize = 3;
75                 break;
76         default:
77                 return NULL;
78         }
79         
80         _SysDebug(" Image_SIF_Parse: sampleSize = %i, fmt = %i", sampleSize, fmt);
81         
82         fileOfs = sizeof(struct sHeader);
83         
84         // Allocate space
85         ret = calloc(1, sizeof(tImage) + w * h * sampleSize);
86         ret->Width = w;
87         ret->Height = h;
88         ret->Format = fmt;
89         for( ofs = 0; ofs < w*h*sampleSize; ofs ++ )
90                 ret->Data[ofs] = 255;
91         
92         switch(comp)
93         {
94         // Uncompressed 32-bpp data
95         case 0:
96                 if( fileOfs + w*h*sampleSize > Size ) {
97                         memcpy(ret->Data, Buffer+fileOfs, Size-fileOfs);
98                 }
99                 else {
100                         memcpy(ret->Data, Buffer+fileOfs, w*h*sampleSize);
101                 }
102                 return ret;
103         
104         // 1.7.n*8 RLE
105         // (1 Flag, 7-bit size, 32-bit value)
106         case 1:
107                 ofs = 0;
108                 while( ofs < w*h*sampleSize )
109                 {
110                         uint8_t len;
111                         if( fileOfs + 1 > Size )
112                                 return ret;
113                         len = ((uint8_t*)Buffer)[fileOfs++];
114                         // Verbatim
115                         if(len & 0x80) {
116                                 len &= 0x7F;
117                                 while( len -- )
118                                 {
119                                         if( fileOfs + sampleSize > Size )
120                                                 return ret;
121                                         memcpy(ret->Data+ofs, Buffer+fileOfs, sampleSize);
122                                         ofs += sampleSize;
123                                         fileOfs += sampleSize;
124                                 }
125                         }
126                         // RLE
127                         else {
128                                 if( fileOfs + sampleSize > Size )
129                                         return ret;
130                                 
131                                 while( len -- )
132                                 {
133                                         memcpy(ret->Data+ofs, Buffer+fileOfs, sampleSize);
134                                         ofs += sampleSize;
135                                 }
136                                 fileOfs += sampleSize;
137                         }
138                 }
139                 _SysDebug("Image_SIF_Parse: Complete at %i bytes", fileOfs);
140                 return ret;
141         
142         // Channel 1.7.8 RLE
143         // - Each channel is separately 1.7 RLE compressed
144         case 3:
145                 // Alpha, Red, Green, Blue
146                 for( i = 0; i < sampleSize; i++ )
147                 {
148                         ofs = i;
149                         while( ofs < w*h*sampleSize )
150                         {
151                                 uint8_t len, val;
152                                 if( fileOfs + 1 > Size )        return ret;
153                                 len = ((uint8_t*)Buffer)[fileOfs++];
154                                 if(len & 0x80) {
155                                         len &= 0x7F;
156                                         while(len--) {
157                                                 if( fileOfs + 1 > Size )        return ret;
158                                                 val = ((uint8_t*)Buffer)[fileOfs++];
159                                                 ret->Data[ofs] = val;
160                                                 ofs += sampleSize;
161                                         }
162                                 }
163                                 else {
164                                         if( fileOfs + 1 > Size )        return ret;
165                                         val = ((uint8_t*)Buffer)[fileOfs++];
166                                         while(len--) {
167                                                 ret->Data[ofs] = val;
168                                                 ofs += sampleSize;
169                                         }
170                                 }
171                         }
172                 }
173                 return ret;
174         
175         default:
176                 fprintf(stderr, "Warning: Unknown compression scheme %i for SIF\n", comp);
177                 return NULL;
178         }
179 }

UCC git Repository :: git.ucc.asn.au