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