9114c5d37de44c3e5ede9a527e95127ec866b625
[gnokii.git] / common / gsm-bitmaps.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8         
9   Functions for manipulating bitmaps
10   
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <sys/stat.h>
18
19 #include "gsm-common.h"
20 #include "gsm-bitmaps.h"
21 #include "gsm-sms.h"
22 #include "gsm-coding.h"
23 #include "gsm-networks.h"
24
25 void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
26 {
27   int pixel;
28   if (bmp->type == GSM_StartupLogo || bmp->type == GSM_6210StartupLogo || bmp->type == GSM_7110StartupLogo)
29     bmp->bitmap[((y/8)*bmp->width)+x] |= 1 << (y%8);
30   if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_7110OperatorLogo || bmp->type == GSM_CallerLogo) {
31     pixel=bmp->width*y + x;
32     bmp->bitmap[pixel/8] |= 1 << (7-(pixel%8));
33   }
34   if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] |= 1 << (7-(x%8));
35 }
36   
37 void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
38 {
39   int pixel;
40   if (bmp->type == GSM_StartupLogo || bmp->type == GSM_6210StartupLogo || bmp->type == GSM_7110StartupLogo)
41     bmp->bitmap[((y/8)*bmp->width)+x] &= 255 - (1 << (y%8));
42   if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_7110OperatorLogo || bmp->type == GSM_CallerLogo) {
43     pixel=bmp->width*y + x;
44     bmp->bitmap[pixel/8] &= ~(1 << (7-(pixel%8)));
45   }
46   if (bmp->type == GSM_PictureImage) bmp->bitmap[9*y + (x/8)] &= 255 - (1 << (7-(x%8)));
47 }
48
49 bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
50 {
51   int i=0;
52   int pixel;
53
54   if (bmp->type == GSM_StartupLogo || bmp->type == GSM_6210StartupLogo || bmp->type == GSM_7110StartupLogo)
55     i=(bmp->bitmap[((y/8)*bmp->width) + x] & 1<<((y%8)));
56   if (bmp->type == GSM_OperatorLogo || bmp->type == GSM_7110OperatorLogo || bmp->type == GSM_CallerLogo) {
57     pixel=bmp->width*y + x;
58     i=(bmp->bitmap[pixel/8] & 1<<(7-(pixel%8)));
59   }
60   if (bmp->type == GSM_PictureImage) i=(bmp->bitmap[9*y + (x/8)] & 1<<(7-(x%8)));
61
62   if (i) return true; else return false;
63 }
64   
65 void GSM_ClearBitmap(GSM_Bitmap *bmp)
66 {
67   int i;
68   for (i=0;i<bmp->size;i++) bmp->bitmap[i]=0;
69 }
70
71 int GSM_GetBitmapSize(GSM_Bitmap *bitmap)
72 {
73   switch (bitmap->type) {
74     case GSM_StartupLogo     : /*size 84*48*/
75     case GSM_OperatorLogo    : /*size 72*14*/
76     case GSM_CallerLogo      : /*size 72*14*/
77     case GSM_PictureImage    : /*size 72*28*/
78       return bitmap->height*bitmap->width/8;
79
80     case GSM_7110OperatorLogo: /*size 78*21*/
81       return (bitmap->width*bitmap->height + 7)/8;
82
83     case GSM_7110StartupLogo: /*size 96*65*/
84     case GSM_6210StartupLogo: /*size 96*60*/
85       return (bitmap->height+7)/8*bitmap->width;
86
87     default:
88       return 0;
89   }
90 }
91
92 GSM_Error GSM_ReadBitmap(GSM_SMSMessage *message, GSM_Bitmap *bitmap)
93 {
94   int offset = 1;
95   unsigned char buffer[20];
96
97   switch (message->UDHType) {
98   case GSM_OpLogo:
99     EncodeUDHHeader(buffer, GSM_OperatorLogo);
100     if (message->Length!=133) return GE_UNKNOWN;
101     
102     bitmap->type = GSM_OperatorLogo;
103
104     DecodeNetworkCode(message->MessageText, bitmap->netcode);
105
106     offset = 4;
107     break;
108
109   case GSM_CallerIDLogo:
110     EncodeUDHHeader(buffer, GSM_CallerLogo);
111     if (message->Length!=130) return GE_UNKNOWN;
112     
113     bitmap->type=GSM_CallerLogo;
114
115     break;
116   default: /* error */
117     return GE_UNKNOWN;
118     break;
119   }
120   bitmap->width = message->MessageText[offset];
121   bitmap->height = message->MessageText[offset + 1];
122   
123   if (bitmap->width!=72 || bitmap->height!=14) return GE_INVALIDIMAGESIZE;
124   
125   bitmap->size = GSM_GetBitmapSize(bitmap);
126   memcpy(bitmap->bitmap, message->MessageText + offset + 3, bitmap->size);
127
128 #ifdef DEBUG
129   fprintf(stdout, _("Bitmap from SMS: width %i, height %i\n"),bitmap->width,bitmap->height);
130 #endif
131
132   return GE_NONE;
133 }
134
135 void GSM_ResizeBitmap(GSM_Bitmap *bitmap, GSM_Bitmap_Types target)
136 {
137   GSM_Bitmap backup;
138   int x,y,width,height;
139   
140   backup=*bitmap;
141       
142   if (target==GSM_StartupLogo) {
143     bitmap->width=84;
144     bitmap->height=48;
145   }
146   if (target==GSM_7110StartupLogo) {
147     bitmap->width=96;
148     bitmap->height=65;
149   }
150   if (target==GSM_6210StartupLogo) {
151     bitmap->width=96;
152     bitmap->height=60;
153   }
154   if (target==GSM_OperatorLogo || target==GSM_CallerLogo) {
155     bitmap->width=72;
156     bitmap->height=14;
157   }
158   if (target==GSM_PictureImage ) {
159     bitmap->width=72;
160     bitmap->height=28;
161   }
162   if (target==GSM_7110OperatorLogo) {
163     bitmap->width=78;
164     bitmap->height=21;
165   }
166   bitmap->type=target;
167   bitmap->size=GSM_GetBitmapSize(bitmap);
168   
169   width=backup.width;
170   if (bitmap->width<width) {
171     width=bitmap->width;
172 #ifdef DEBUG
173     fprintf(stdout,_("We lost some part of image - it's cut (width from %i to %i) !\n"),backup.width,width);
174 #endif /* DEBUG */
175   }
176   
177   height=backup.height;
178   if (bitmap->height<height) {
179     height=bitmap->height; 
180 #ifdef DEBUG
181     fprintf(stdout,_("We lost some part of image - it's cut (height from %i to %i) !\n"),backup.height,height);
182 #endif /* DEBUG */
183   }
184   
185   GSM_ClearBitmap(bitmap);
186   
187   for (y=0;y<height;y++) {
188     for (x=0;x<width;x++)
189       if (GSM_IsPointBitmap(&backup,x,y)) GSM_SetPointBitmap(bitmap,x,y);
190   }
191   
192 //GSM_PrintBitmap(&backup);
193 //GSM_PrintBitmap(bitmap);
194 }
195
196 void GSM_PrintBitmap(GSM_Bitmap *bitmap)
197 {
198   int x,y;
199
200   for (y=0;y<bitmap->height;y++) {
201     for (x=0;x<bitmap->width;x++) {
202       if (GSM_IsPointBitmap(bitmap,x,y)) {
203         fprintf(stdout, _("#"));
204       } else {
205         fprintf(stdout, _(" "));
206       }
207     }
208     fprintf(stdout, _("\n"));
209   }
210 }
211
212 int GSM_SaveBitmapToSMS(GSM_MultiSMSMessage *SMS, GSM_Bitmap *bitmap,
213                         bool ScreenSaver, bool UnicodeText)
214 {
215   char MessageBuffer[GSM_MAX_SMS_8_BIT_LENGTH*4];
216   int MessageLength=0;
217   GSM_UDH UDHType=GSM_NoUDH;
218   
219   switch (bitmap->type) {
220     case GSM_OperatorLogo:
221       UDHType=GSM_OpLogo;
222
223       EncodeNetworkCode(MessageBuffer, bitmap->netcode);
224       MessageLength=3;
225
226       /* Set the logo size */
227       MessageBuffer[MessageLength++] = 0x00;
228       MessageBuffer[MessageLength++] = bitmap->width;
229       MessageBuffer[MessageLength++] = bitmap->height;
230       MessageBuffer[MessageLength++] = 0x01;
231
232       memcpy(MessageBuffer+MessageLength,bitmap->bitmap,bitmap->size);
233       MessageLength=MessageLength+bitmap->size;
234
235       break;
236     case GSM_CallerLogo:
237       UDHType=GSM_CallerIDLogo;
238
239       /* Set the logo size */
240       MessageBuffer[MessageLength++] = 0x00;
241       MessageBuffer[MessageLength++] = bitmap->width;
242       MessageBuffer[MessageLength++] = bitmap->height;
243       MessageBuffer[MessageLength++] = 0x01;
244
245       memcpy(MessageBuffer+MessageLength,bitmap->bitmap,bitmap->size);
246       MessageLength=MessageLength+bitmap->size;
247
248       break;
249     case GSM_PictureImage:
250       UDHType=GSM_ProfileUDH;
251
252       MessageBuffer[MessageLength++]=0x30;     //SM version. Here 3.0
253
254       if (!ScreenSaver)
255         MessageBuffer[MessageLength++]=SM30_OTA; //ID for OTA bitmap
256       else
257         MessageBuffer[MessageLength++]=SM30_SCREENSAVER; //ID for screen saver
258
259       /* Length for picture part */
260       MessageBuffer[MessageLength++]=0x01;     //length hi
261       MessageBuffer[MessageLength++]=0x00;     //length lo
262
263       /* Set the logo size */
264       MessageBuffer[MessageLength++] = 0x00;
265       MessageBuffer[MessageLength++] = bitmap->width;
266       MessageBuffer[MessageLength++] = bitmap->height;
267       MessageBuffer[MessageLength++] = 0x01;
268
269       memcpy(MessageBuffer+MessageLength,bitmap->bitmap,bitmap->size);
270       MessageLength=MessageLength+bitmap->size;
271
272       if (strlen(bitmap->text)!=0) {
273         if (UnicodeText) {
274           MessageBuffer[MessageLength++]=SM30_UNICODETEXT; //ID for Unicode text
275
276           /* Length for text part */
277           MessageBuffer[MessageLength++]=0x00;             //length of text1
278           MessageBuffer[MessageLength++]=strlen(bitmap->text)*2;//length of text2
279
280           EncodeUnicode (MessageBuffer+MessageLength,bitmap->text,strlen(bitmap->text));
281           MessageLength=MessageLength+2*strlen(bitmap->text);
282         } else {
283           MessageBuffer[MessageLength++]=SM30_ISOTEXT;    //ID for ISO-8859-1 text
284
285           /* Length for text part */
286           MessageBuffer[MessageLength++]=0x00;            //length of text1
287           MessageBuffer[MessageLength++]=strlen(bitmap->text); //length of text2
288
289           memcpy(MessageBuffer+MessageLength,bitmap->text,strlen(bitmap->text));
290           MessageLength=MessageLength+strlen(bitmap->text);
291        }
292       }
293       break;
294     
295     default: /* error */
296       break;
297   }
298         
299   GSM_MakeMultiPartSMS2(SMS,MessageBuffer,MessageLength, UDHType, GSM_Coding_Default);
300
301   return 0;
302 }
303