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

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