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

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