summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service/gsmlogo.c
Unidiff
Diffstat (limited to 'gammu/emb/common/service/gsmlogo.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/service/gsmlogo.c1003
1 files changed, 1003 insertions, 0 deletions
diff --git a/gammu/emb/common/service/gsmlogo.c b/gammu/emb/common/service/gsmlogo.c
new file mode 100644
index 0000000..c992915
--- a/dev/null
+++ b/gammu/emb/common/service/gsmlogo.c
@@ -0,0 +1,1003 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <stdlib.h>
5
6#include "../misc/misc.h"
7#include "../misc/coding/coding.h"
8#include "gsmlogo.h"
9#include "gsmnet.h"
10
11void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height)
12{
13 *width = 0;
14 *height= 0;
15 switch (Type) {
16 case GSM_EMSSmallPicture: *width=8; *height=8; break;
17 case GSM_EMSMediumPicture: *width=16; *height=16; break;
18 case GSM_EMSBigPicture : *width=32; *height=32; break;
19 case GSM_NokiaOperatorLogo:
20 case GSM_NokiaCallerLogo: *width=72; *height=14; break;
21 case GSM_NokiaPictureImage: *width=72; *height=28; break;
22 case GSM_Nokia7110OperatorLogo:
23 case GSM_Nokia6510OperatorLogo: *width=78; *height=21; break;
24 case GSM_NokiaStartupLogo: *width=84; *height=48; break;
25 case GSM_Nokia6210StartupLogo: *width=96; *height=60; break;
26 case GSM_Nokia7110StartupLogo: *width=96; *height=65; break;
27 case GSM_EMSVariablePicture : break;
28 case GSM_AlcatelBMMIPicture : break;
29 }
30}
31
32int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int Width, int Height)
33{
34 int width, height, x;
35
36 PHONE_GetBitmapWidthHeight(Type, &width, &height);
37 if (width == 0 && height == 0) {
38 width = Width;
39 height = Height;
40 }
41 switch (Type) {
42 case GSM_Nokia6510OperatorLogo:
43 x = width * height;
44 return x/8 + (x%8 > 0);
45 case GSM_Nokia7110OperatorLogo:
46 return (width*height + 7)/8;
47 case GSM_NokiaStartupLogo:
48 case GSM_NokiaOperatorLogo:
49 case GSM_NokiaCallerLogo:
50 case GSM_NokiaPictureImage:
51 case GSM_EMSSmallPicture:
52 case GSM_EMSMediumPicture:
53 case GSM_EMSBigPicture:
54 case GSM_EMSVariablePicture:
55 return height*width/8;
56 case GSM_Nokia7110StartupLogo:
57 case GSM_Nokia6210StartupLogo:
58 return (height+7)/8*width;
59 case GSM_AlcatelBMMIPicture:
60 return width*((height+7)/8);
61 }
62 return 0;
63}
64
65static bool PHONE_IsPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
66{
67 int i=0, pixel;
68
69 switch (Type) {
70 case GSM_NokiaStartupLogo:
71 case GSM_Nokia6210StartupLogo:
72 case GSM_Nokia7110StartupLogo:
73 case GSM_Nokia6510OperatorLogo:
74 i=(buffer[(y/8*width) + x] & 1<<(y%8));
75 break;
76 case GSM_NokiaOperatorLogo:
77 case GSM_Nokia7110OperatorLogo:
78 case GSM_NokiaCallerLogo:
79 case GSM_EMSVariablePicture:
80 case GSM_EMSSmallPicture:
81 case GSM_EMSMediumPicture:
82 case GSM_EMSBigPicture:
83 pixel=width*y + x;
84 i=(buffer[pixel/8] & 1<<(7-(pixel%8)));
85 break;
86 case GSM_NokiaPictureImage:
87 i=(buffer[9*y + x/8] & 1<<(7-(x%8)));
88 break;
89 case GSM_AlcatelBMMIPicture:
90 break;
91 }
92 if (i) return true; else return false;
93}
94
95static void PHONE_SetPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
96{
97 int pixel;
98
99 switch (Type) {
100 case GSM_NokiaStartupLogo:
101 case GSM_Nokia6210StartupLogo:
102 case GSM_Nokia7110StartupLogo:
103 case GSM_Nokia6510OperatorLogo:
104 buffer[(y/8*width)+x] |= 1 << (y%8);
105 break;
106 case GSM_NokiaOperatorLogo:
107 case GSM_Nokia7110OperatorLogo:
108 case GSM_NokiaCallerLogo:
109 case GSM_EMSSmallPicture:
110 case GSM_EMSMediumPicture:
111 case GSM_EMSBigPicture:
112 case GSM_EMSVariablePicture:
113 pixel = width*y + x;
114 buffer[pixel/8] |= 1 << (7-(pixel%8));
115 break;
116 case GSM_NokiaPictureImage:
117 buffer[9*y + x/8] |= 1 << (7-(x%8));
118 break;
119 case GSM_AlcatelBMMIPicture:
120 pixel = height / 8;
121 if ((height % 8) != 0) pixel++;
122 buffer[pixel*x + y/8] |= 1 << (7 - (y%8));
123 break;
124 }
125}
126
127void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
128{
129 int width, height, x,y;
130
131 PHONE_GetBitmapWidthHeight(Type, &width, &height);
132 if (Type != GSM_Nokia6510OperatorLogo && Type != GSM_Nokia7110OperatorLogo && Type != GSM_EMSVariablePicture) {
133 Bitmap->BitmapHeight= height;
134 Bitmap->BitmapWidth= width;
135 }
136 switch (Type) {
137 case GSM_NokiaOperatorLogo:
138 case GSM_Nokia7110OperatorLogo:
139 case GSM_Nokia6510OperatorLogo : Bitmap->Type=GSM_OperatorLogo;break;
140 case GSM_NokiaCallerLogo : Bitmap->Type=GSM_CallerGroupLogo;break;
141 case GSM_AlcatelBMMIPicture :
142 case GSM_NokiaStartupLogo:
143 case GSM_Nokia7110StartupLogo:
144 case GSM_Nokia6210StartupLogo : Bitmap->Type=GSM_StartupLogo; break;
145 case GSM_NokiaPictureImage:
146 case GSM_EMSVariablePicture:
147 case GSM_EMSSmallPicture:
148 case GSM_EMSMediumPicture:
149 case GSM_EMSBigPicture : Bitmap->Type=GSM_PictureImage;break;
150 }
151
152 Bitmap->Location = 0;
153 Bitmap->Text[0] = 0;
154 Bitmap->Text[1] = 0;
155 Bitmap->BitmapEnabled = false;
156 Bitmap->DefaultName = false;
157 Bitmap->DefaultBitmap = false;
158 Bitmap->DefaultRingtone = false;
159 Bitmap->RingtoneID = 0;
160 Bitmap->NetworkCode[0] = 0;
161 Bitmap->Sender[0] = 0;
162 Bitmap->Sender[1] = 0;
163 Bitmap->ID = 0;
164
165 GSM_ClearBitmap(Bitmap);
166 for (x=0;x<Bitmap->BitmapWidth;x++) {
167 for (y=0;y<Bitmap->BitmapHeight;y++) {
168 if (PHONE_IsPointBitmap(Type, buffer, x, y, Bitmap->BitmapWidth, Bitmap->BitmapHeight)) {
169 GSM_SetPointBitmap(Bitmap,x,y);
170 }
171 }
172 }
173}
174
175void PHONE_ClearBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height)
176{
177 memset(buffer,0,PHONE_GetBitmapSize(Type,width,height));
178}
179
180void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
181{
182 int width, height, x, y;
183 GSM_Bitmapdest;
184
185 PHONE_GetBitmapWidthHeight(Type, &width, &height);
186 if (width == 0 && height == 0) {
187 width = Bitmap->BitmapWidth;
188 height = Bitmap->BitmapHeight;
189 }
190 GSM_ResizeBitmap(&dest, Bitmap, width, height);
191 PHONE_ClearBitmap(Type, buffer, width, height);
192
193 for (x=0;x<width;x++) {
194 for (y=0;y<height;y++) {
195 if (GSM_IsPointBitmap(&dest,x,y)) PHONE_SetPointBitmap(Type, buffer, x, y, width, height);
196 }
197 }
198}
199
200void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height)
201{
202 switch (Type) {
203 case GSM_CallerGroupLogo: *width=72; *height=14; break;
204 case GSM_OperatorLogo: *width=101;*height=21; break;
205 case GSM_StartupLogo: *width=96; *height=65; break;
206 case GSM_PictureImage: *width=72; *height=28; break;
207 default : break;
208 }
209}
210
211void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
212{
213 SetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
214}
215
216void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
217{
218 ClearBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
219}
220
221bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
222{
223 if (GetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x)) return true; else return false;
224}
225
226void GSM_ClearBitmap(GSM_Bitmap *bmp)
227{
228 memset(bmp->BitmapPoints,0,GSM_GetBitmapSize(bmp));
229}
230
231int GSM_GetBitmapSize(GSM_Bitmap *bmp)
232{
233 return bmp->BitmapWidth*bmp->BitmapHeight/8+1;
234}
235
236void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
237{
238 int x,y;
239
240 for (y=0;y<bitmap->BitmapHeight;y++) {
241 for (x=0;x<bitmap->BitmapWidth;x++) {
242 if (GSM_IsPointBitmap(bitmap,x,y)) {
243 fprintf(file,"#");
244 } else {
245 fprintf(file," ");
246 }
247 }
248 fprintf(file,"\n");
249 }
250}
251
252void GSM_ReverseBitmap(GSM_Bitmap *Bitmap)
253{
254 int x, y;
255
256 for (x=0;x<Bitmap->BitmapWidth;x++) {
257 for (y=0;y<Bitmap->BitmapHeight;y++) {
258 if (GSM_IsPointBitmap(Bitmap,x,y)) {
259 GSM_ClearPointBitmap(Bitmap, x, y);
260 } else {
261 GSM_SetPointBitmap(Bitmap, x, y);
262 }
263 }
264 }
265}
266
267void GSM_ResizeBitmap(GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height)
268{
269 int startx=0,endx=0,setx=0, starty=0,endy=0,sety=0, x, y;
270
271 if (src->BitmapWidth<=width) {
272 startx= 0;
273 endx= src->BitmapWidth;
274 setx= (width-src->BitmapWidth)/2;
275 } else {
276 startx= (src->BitmapWidth-width)/2;
277 endx= startx + width;
278 setx= 0;
279 }
280 if (src->BitmapHeight<=height) {
281 starty= 0;
282 endy= src->BitmapHeight;
283 sety= (height-src->BitmapHeight)/2;
284 } else {
285 starty= (src->BitmapHeight-height)/2;
286 endy= starty + height;
287 sety= 0;
288 }
289 dest->BitmapHeight= height;
290 dest->BitmapWidth= width;
291 GSM_ClearBitmap(dest);
292 for (x=startx;x<endx;x++) {
293 for (y=starty;y<endy;y++) {
294 if (GSM_IsPointBitmap(src,x,y))
295 GSM_SetPointBitmap(dest,setx+x-startx,sety+y-starty);
296 }
297 }
298}
299
300GSM_Error Bitmap2BMP(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
301{
302 int x,y,pos,i,sizeimage,buffpos=0;
303 unsigned charbuff[1];
304 div_t division;
305 bool isfile=false;
306
307 unsigned char header[]={
308/*1'st header*/ 'B','M', /* BMP file ID */
309 0x00,0x00,0x00,0x00, /* Size of file */
310 0x00,0x00, /* Reserved for future use */
311 0x00,0x00, /* Reserved for future use */
312 62,0x00,0x00,0x00, /* Offset for image data */
313
314/*2'nd header*/ 40,0x00,0x00,0x00, /* Length of this part of header */
315 0x00,0x00,0x00,0x00, /* Width of image */
316 0x00,0x00,0x00,0x00, /* Height of image */
317 1,0x00, /* How many planes in target device */
318 1,0x00, /* How many colors in image. 1 means 2^1=2 colors */
319 0x00,0x00,0x00,0x00, /* Type of compression. 0 means no compression */
320/*Sometimes */ 0x00,0x00,0x00,0x00, /* Size of part with image data */
321/*ttttttt...*/ 0xE8,0x03,0x00,0x00, /* XPelsPerMeter */
322 /*hhiiiiissss*/ 0xE8,0x03,0x00,0x00, /* YPelsPerMeter */
323/*part of header*/0x02,0x00,0x00,0x00, /* How many colors from palette is used */
324/*doesn't exist*/ 0x00,0x00,0x00,0x00, /* How many colors from palette is required to display image. 0 means all */
325
326/*Color palette*/ 0x00,0x00,0x00, /* First color in palette in Blue, Green, Red. Here white */
327 0x00, /* Each color in palette is end by 4'th byte */
328 102, 204, 102, /* Second color in palette in Blue, Green, Red. Here green */
329 0x00}; /* Each color in palette is end by 4'th byte */
330
331 if (file!=NULL) isfile=true;
332
333 header[22]=bitmap->BitmapHeight;
334 header[18]=bitmap->BitmapWidth;
335
336 pos = 7;
337 sizeimage = 0;
338 /*lines are written from the last to the first*/
339 for (y=bitmap->BitmapHeight-1;y>=0;y--) {
340 i=1;
341 for (x=0;x<bitmap->BitmapWidth;x++) {
342 /*new byte !*/
343 if (pos==7) {
344 if (x!=0) sizeimage++;
345 i++;
346 /*each line is written in multiply of 4 bytes*/
347 if(i==5) i=1;
348 }
349 pos--;
350 /*going to new byte*/
351 if (pos<0) pos=7;
352 }
353 /*going to new byte*/
354 pos=7;
355 sizeimage++;
356 if (i!=1) {
357 /*each line is written in multiply of 4 bytes*/
358 while (i!=5) {
359 sizeimage++;
360 i++;
361 }
362 }
363 }
364 dbgprintf("Data size in BMP file: %i\n",sizeimage);
365 division=div(sizeimage,256);
366 header[35]=division.quot;
367 header[34]=sizeimage-(division.quot*256);
368 sizeimage=sizeimage+sizeof(header);
369 dbgprintf("Size of BMP file: %i\n",sizeimage);
370 division=div(sizeimage,256);
371 header[3]=division.quot;
372 header[2]=sizeimage-(division.quot*256);
373
374 if (isfile) {
375 fwrite(header,1,sizeof(header),file);
376 } else {
377 memcpy(buffer,header,sizeof(header));
378 buffpos += sizeof(header);
379 }
380
381 pos=7;
382 /*lines are written from the last to the first*/
383 for (y=bitmap->BitmapHeight-1;y>=0;y--) {
384 i=1;
385 for (x=0;x<bitmap->BitmapWidth;x++) {
386 /*new byte !*/
387 if (pos==7) {
388 if (x!=0) {
389 if (isfile) {
390 fwrite(buff, 1, sizeof(buff), file);
391 } else {
392 memcpy (buffer+buffpos,buff,1);
393 buffpos++;
394 }
395 }
396 i++;
397 /*each line is written in multiply of 4 bytes*/
398 if(i==5) i=1;
399 buff[0]=0;
400 }
401 if (!GSM_IsPointBitmap(bitmap,x,y)) buff[0]|=(1<<pos);
402 pos--;
403 /*going to new byte*/
404 if (pos<0) pos=7;
405 }
406 /*going to new byte*/
407 pos=7;
408 if (isfile) {
409 fwrite(buff, 1, sizeof(buff), file);
410 } else {
411 memcpy (buffer+buffpos,buff,1);
412 buffpos++;
413 }
414 if (i!=1) {
415 /*each line is written in multiply of 4 bytes*/
416 while (i!=5) {
417 buff[0]=0;
418 if (isfile) {
419 fwrite(buff, 1, sizeof(buff), file);
420 } else {
421 memcpy (buffer+buffpos,buff,1);
422 buffpos++;
423 }
424 i++;
425 }
426 }
427 }
428 return ERR_NONE;
429}
430
431static GSM_Error savebmp(FILE *file, GSM_MultiBitmap *bitmap)
432{
433 GSM_Error error;
434
435 error=Bitmap2BMP(NULL,file,&bitmap->Bitmap[0]);
436 return error;
437}
438
439static void PrivSaveNLMWBMP(FILE *file, GSM_Bitmap *Bitmap)
440{
441 unsigned charbuffer[1000];
442 int x,y,pos,pos2;
443 div_t division;
444
445 pos=0;pos2=7;
446 for (y=0;y<Bitmap->BitmapHeight;y++) {
447 for (x=0;x<Bitmap->BitmapWidth;x++) {
448 if (pos2==7) buffer[pos]=0;
449 if (GSM_IsPointBitmap(Bitmap,x,y)) buffer[pos]|=(1<<pos2);
450 pos2--;
451 /* going to new line */
452 if (pos2<0) {pos2=7;pos++;}
453 }
454 /* for startup logos - new line with new byte */
455 if (pos2!=7) {pos2=7;pos++;}
456 }
457
458 division=div(Bitmap->BitmapWidth,8);
459 /* For startup logos */
460 if (division.rem!=0) division.quot++;
461
462 fwrite(buffer,1,(division.quot*Bitmap->BitmapHeight),file);
463}
464
465static GSM_Error savenlm(FILE *file, GSM_MultiBitmap *bitmap)
466{
467 int i;
468 char header[]={
469 'N','L','M',' ', /* Nokia Logo Manager file ID. */
470 0x01,
471 0x00, /* 0x00 (OP), 0x01 (CLI), 0x02 (Startup), 0x03 (Picture)*/
472 0x00, /* Number of images inside file - 1. 0x01==2 images, 0x03==4 images, etc. */
473 0x00, /* Width. */
474 0x00, /* Height. */
475 0x01};
476
477 switch (bitmap->Bitmap[0].Type) {
478 case GSM_OperatorLogo : header[5]=0x00; break;
479 case GSM_CallerGroupLogo : header[5]=0x01; break;
480 case GSM_StartupLogo : header[5]=0x02; break;
481 case GSM_PictureImage : header[5]=0x03; break;
482 default : return ERR_UNKNOWN;
483 }
484 header[6] = bitmap->Number - 1;
485 header[7] = bitmap->Bitmap[0].BitmapWidth;
486 header[8] = bitmap->Bitmap[0].BitmapHeight;
487 fwrite(header,1,sizeof(header),file);
488
489 for (i=0;i<bitmap->Number;i++) {
490 PrivSaveNLMWBMP(file, &bitmap->Bitmap[i]);
491 }
492
493 return ERR_NONE;
494}
495
496static void PrivSaveNGGNOL(FILE *file, GSM_MultiBitmap *bitmap)
497{
498 char buffer[GSM_BITMAP_SIZE];
499 intx,y,current=0;
500
501 for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
502 for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++) {
503 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
504 buffer[current++] = '1';
505 } else {
506 buffer[current++] = '0';
507 }
508 }
509 }
510 fwrite(buffer,1,current,file);
511}
512
513static GSM_Error savengg(FILE *file, GSM_MultiBitmap *bitmap)
514{
515 char header[]={
516 'N','G','G',0x00,0x01,0x00,
517 0x00,0x00,/* Width */
518 0x00,0x00,/* Height */
519 0x01,0x00,0x01,0x00,
520 0x00, /* Unknown.Can't be checksum - for */
521 /* the same logo files can be different */
522 0x00};
523
524 header[6] = bitmap->Bitmap[0].BitmapWidth;
525 header[8] = bitmap->Bitmap[0].BitmapHeight;
526 fwrite(header,1,sizeof(header),file);
527
528 PrivSaveNGGNOL(file,bitmap);
529
530 return ERR_NONE;
531}
532
533static GSM_Error savenol(FILE *file, GSM_MultiBitmap *bitmap)
534{
535 int country,net;
536 char header[]={
537 'N','O','L',0x00,0x01,0x00,
538 0x00,0x00, /* MCC */
539 0x00,0x00, /* MNC */
540 0x00,0x00, /* Width */
541 0x00,0x00, /* Height */
542 0x01,0x00,0x01,0x00,
543 0x00, /* Unknown.Can't be checksum - for */
544 /* the same logo files can be different */
545 0x00};
546
547 if (bitmap->Bitmap[0].Type == GSM_OperatorLogo) sscanf(bitmap->Bitmap[0].NetworkCode, "%d %d", &country, &net);
548
549 header[6]= country%256;
550 header[7]= country/256;
551 header[8]= net%256;
552 header[9]= net/256;
553 header[10]= bitmap->Bitmap[0].BitmapWidth;
554 header[12]= bitmap->Bitmap[0].BitmapHeight;
555 fwrite(header,1,sizeof(header),file);
556
557 PrivSaveNGGNOL(file,bitmap);
558
559 return ERR_NONE;
560}
561
562static GSM_Error savexpm(FILE *file, GSM_MultiBitmap *bitmap)
563{
564 int x,y;
565
566 fprintf(file,"/* XPM */\n");
567 fprintf(file,"static char * ala_xpm[] = {\n");
568 fprintf(file,"\"%i %i 2 1\",\n",bitmap->Bitmap[0].BitmapWidth,bitmap->Bitmap[0].BitmapHeight);
569 fprintf(file,"\". s c m #000000 g4 #000000 g #000000c #000000\",\n");
570 fprintf(file,"\"# s c m #ffffff g4 #ffffff g #ffffffc #ffffff\",\n");
571
572 for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
573 fprintf(file,"\"");
574 for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++)
575 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
576 fprintf(file,".");
577 } else {
578 fprintf(file,"#");
579 }
580 fprintf(file,"\"");
581 if (y==bitmap->Bitmap[0].BitmapHeight-1) {
582 fprintf(file,"};\n");
583 } else {
584 fprintf(file,",\n");
585 }
586 }
587
588 return ERR_NONE;
589}
590
591static GSM_Error savensl(FILE *file, GSM_MultiBitmap *bitmap)
592{
593 char buffer[GSM_BITMAP_SIZE];
594 unsigned char header[]={
595 'F','O','R','M', 0x01,0xFE,/* File ID block, size 1*256+0xFE=510*/
596 'N','S','L','D', 0x01,0xF8};/* Startup Logo block, size 1*256+0xF8=504*/
597
598 fwrite(header,1,sizeof(header),file);
599 PHONE_EncodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
600 fwrite(buffer,1,PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0),file);
601
602 return ERR_NONE;
603}
604
605static GSM_Error savewbmp(FILE *file, GSM_MultiBitmap *bitmap)
606{
607 unsigned char buffer[4];
608
609 buffer[0] = 0x00;
610 buffer[1] = 0x00;
611 buffer[2] = bitmap->Bitmap[0].BitmapWidth;
612 buffer[3] = bitmap->Bitmap[0].BitmapHeight;
613 fwrite(buffer,1,4,file);
614
615 PrivSaveNLMWBMP(file, &bitmap->Bitmap[0]);
616
617 return ERR_NONE;
618}
619
620GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
621{
622 FILE *file;
623 GSM_Error error=ERR_NONE;
624
625 file = fopen(FileName, "wb");
626 if (file == NULL) return ERR_CANTOPENFILE;
627
628 /* Attempt to identify filetype */
629 if (strstr(FileName,".nlm")) {
630 error=savenlm(file,bitmap);
631 } else if (strstr(FileName,".ngg")) {
632 error=savengg(file,bitmap);
633 } else if (strstr(FileName,".nol")) {
634 error=savenol(file,bitmap);
635 } else if (strstr(FileName,".xpm")) {
636 error=savexpm(file,bitmap);
637 } else if (strstr(FileName,".nsl")) {
638 error=savensl(file,bitmap);
639 } else if (strstr(FileName,".wbmp")) {
640 error=savewbmp(file,bitmap);
641 } else {
642 error=savebmp(file,bitmap);
643 }
644 fclose(file);
645
646 return error;
647}
648
649GSM_Error BMP2Bitmap(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
650{
651 bool first_white,isfile=false;
652 unsigned char buff[34];
653 int w,h,pos,y,x,i,buffpos=0;
654#ifdef DEBUG
655 int sizeimage=0;
656#endif
657
658 if (bitmap->Type == GSM_None) bitmap->Type = GSM_StartupLogo;
659 if (file!=NULL) isfile=true;
660 if (isfile) {
661 fread(buff, 1, 34, file);
662 } else {
663 memcpy(buff,buffer,34);
664 }
665
666 /* height and width of image in the file */
667 h=buff[22]+256*buff[21];
668 w=buff[18]+256*buff[17];
669 dbgprintf("Image Size in BMP file: %dx%d\n",w,h);
670
671 GSM_GetMaxBitmapWidthHeight(bitmap->Type, &bitmap->BitmapWidth, &bitmap->BitmapHeight);
672 if (h<bitmap->BitmapHeight)bitmap->BitmapHeight=h;
673 if (w<bitmap->BitmapWidth)bitmap->BitmapWidth=w;
674 dbgprintf("Height %i %i, width %i %i\n",h,bitmap->BitmapHeight,w,bitmap->BitmapWidth);
675
676 GSM_ClearBitmap(bitmap);
677
678#ifdef DEBUG
679 dbgprintf("Number of colors in BMP file: ");
680 switch (buff[28]) {
681 case 1 : dbgprintf("2 (supported)\n"); break;
682 case 4 : dbgprintf("16 (NOT SUPPORTED)\n"); break;
683 case 8 : dbgprintf("256 (NOT SUPPORTED)\n"); break;
684 case 24 : dbgprintf("True Color (NOT SUPPORTED)\n"); break;
685 default : dbgprintf("unknown\n"); break;
686 }
687#endif
688 if (buff[28]!=1) {
689 dbgprintf("Wrong number of colors\n");
690 return ERR_FILENOTSUPPORTED;
691 }
692
693#ifdef DEBUG
694 dbgprintf("Compression in BMP file: ");
695 switch (buff[30]) {
696 case 0 :dbgprintf("no compression (supported)\n"); break;
697 case 1 :dbgprintf("RLE8 (NOT SUPPORTED)\n"); break;
698 case 2 :dbgprintf("RLE4 (NOT SUPPORTED)\n"); break;
699 default :dbgprintf("unknown\n"); break;
700 }
701#endif
702 if (buff[30]!=0) {
703 dbgprintf("Compression type not supported\n");
704 return ERR_FILENOTSUPPORTED;
705 }
706
707 /* read rest of header (if exists) and color palette */
708 if (isfile) {
709 pos=buff[10]-34;
710 fread(buff, 1, pos, file);
711 } else {
712 pos=buff[10]-34;
713 buffpos=buff[10];
714 memcpy (buff,buffer+34,pos);
715 }
716
717#ifdef DEBUG
718 dbgprintf("First color in BMP file: %i %i %i ",buff[pos-8], buff[pos-7], buff[pos-6]);
719 if (buff[pos-8]==0 && buff[pos-7]==0 && buff[pos-6]==0) dbgprintf("(white)");
720 if (buff[pos-8]==0xFF && buff[pos-7]==0xFF && buff[pos-6]==0xFF) dbgprintf("(black)");
721 if (buff[pos-8]==102 && buff[pos-7]==204 && buff[pos-6]==102) dbgprintf("(green)");
722 dbgprintf("\n");
723 dbgprintf("Second color in BMP file: %i %i %i ",buff[pos-38], buff[pos-37], buff[pos-36]);
724 if (buff[pos-4]==0 && buff[pos-3]==0 && buff[pos-2]==0) dbgprintf("(white)");
725 if (buff[pos-4]==0xFF && buff[pos-3]==0xFF && buff[pos-2]==0xFF) dbgprintf("(black)");
726 dbgprintf("\n");
727#endif
728 first_white=true;
729 if (buff[pos-8]!=0 || buff[pos-7]!=0 || buff[pos-6]!=0) first_white=false;
730
731 pos=7;
732 /* lines are written from the last to the first */
733 for (y=h-1;y>=0;y--) { i=1;
734 for (x=0;x<w;x++) { /* new byte ! */
735 if (pos==7) { if (isfile) {
736 fread(buff, 1, 1, file);
737 } else {
738 memcpy (buff,buffer+buffpos,1);
739 buffpos++;
740 }
741#ifdef DEBUG
742 sizeimage++;
743#endif
744 i++;
745 /* each line is written in multiply of 4 bytes */
746 if(i==5) i=1;
747 }
748 /* we have top left corner ! */
749 if (x<=bitmap->BitmapWidth && y<=bitmap->BitmapHeight) { if (first_white) {
750 if ((buff[0]&(1<<pos))<=0) GSM_SetPointBitmap(bitmap,x,y);
751 } else {
752 if ((buff[0]&(1<<pos))>0) GSM_SetPointBitmap(bitmap,x,y);
753 }
754 }
755 pos--;
756 /* going to new byte */
757 if (pos<0) pos=7;
758 }
759 /* going to new byte */
760 pos=7;
761 if (i!=1) {
762 /* each line is written in multiply of 4 bytes */
763 while (i!=5) {
764 if (isfile) {
765 fread(buff, 1, 1, file);
766 } else {
767 memcpy (buff,buffer+buffpos,1);
768 buffpos++;
769 }
770#ifdef DEBUG
771 sizeimage++;
772#endif
773 i++;
774 }
775 }
776 }
777#ifdef DEBUG
778 dbgprintf("Data size in BMP file: %i\n",sizeimage);
779#endif
780 return(ERR_NONE);
781}
782
783static GSM_Error loadbmp(FILE *file, GSM_MultiBitmap *bitmap)
784{
785 GSM_Error error;
786
787 error=BMP2Bitmap(NULL,file,&bitmap->Bitmap[0]);
788 bitmap->Number = 1;
789 return error;
790}
791
792static GSM_Error loadnlm (FILE *file, GSM_MultiBitmap *bitmap)
793{
794 unsigned char buffer[1000];
795 int pos,pos2,x,y,h,w,i,number;
796 div_t division;
797
798 fread(buffer,1,5,file);
799
800 fread(buffer,1,1,file);
801 switch (buffer[0]) {
802 case 0x00:
803 dbgprintf("Operator logo\n");
804 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
805 break;
806 case 0x01:
807 dbgprintf("Caller logo\n");
808 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
809 break;
810 case 0x02:
811 dbgprintf("Startup logo\n");
812 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_StartupLogo;
813 break;
814 case 0x03:
815 dbgprintf("Picture Image logo\n");
816 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_PictureImage;
817 break;
818 }
819
820 bitmap->Number = 0;
821 fread(buffer,1,4,file);
822 number = buffer[0] + 1;
823 w = buffer[1];
824 h = buffer[2];
825 for (i=0;i<number;i++) {
826 bitmap->Bitmap[i].Type = bitmap->Bitmap[0].Type;
827 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[i].Type, &bitmap->Bitmap[i].BitmapWidth, &bitmap->Bitmap[i].BitmapHeight);
828 if (h < bitmap->Bitmap[i].BitmapHeight) bitmap->Bitmap[i].BitmapHeight= h;
829 if (w < bitmap->Bitmap[i].BitmapWidth) bitmap->Bitmap[i].BitmapWidth = w;
830
831 division=div(w,8);
832 /* For startup logos */
833 if (division.rem!=0) division.quot++;
834 if (fread(buffer,1,(division.quot*h),file)!=(unsigned int)(division.quot*h)) return ERR_UNKNOWN;
835
836 GSM_ClearBitmap(&bitmap->Bitmap[i]);
837
838 pos=0;pos2=7;
839 for (y=0;y<h;y++) {
840 for (x=0;x<w;x++) {
841 if ((buffer[pos]&(1<<pos2))>0) {
842 if (y<bitmap->Bitmap[i].BitmapHeight && x<bitmap->Bitmap[i].BitmapWidth) GSM_SetPointBitmap(&bitmap->Bitmap[i],x,y);
843 }
844 pos2--;
845 /* going to new byte */
846 if (pos2<0) {pos2=7;pos++;}
847 }
848 /* for startup logos-new line means new byte */
849 if (pos2!=7) {pos2=7;pos++;}
850 }
851 bitmap->Number++;
852 if (bitmap->Number == MAX_MULTI_BITMAP) break;
853 }
854 return (ERR_NONE);
855}
856
857static GSM_Error loadnolngg(FILE *file, GSM_MultiBitmap *bitmap, bool nolformat)
858{
859 unsigned char buffer[2000];
860 int i,h,w,x,y;
861
862 fread(buffer, 1, 6, file);
863
864 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
865 if (nolformat) {
866 fread(buffer, 1, 4, file);
867 sprintf(bitmap->Bitmap[0].NetworkCode, "%d %02d", buffer[0]+256*buffer[1], buffer[2]);
868 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
869 }
870
871 fread(buffer, 1, 4, file);
872 w = buffer[0];
873 h = buffer[2];
874 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[0].Type, &bitmap->Bitmap[0].BitmapWidth, &bitmap->Bitmap[0].BitmapHeight);
875 if (h < bitmap->Bitmap[0].BitmapHeight) bitmap->Bitmap[0].BitmapHeight= h;
876 if (w < bitmap->Bitmap[0].BitmapWidth) bitmap->Bitmap[0].BitmapWidth= w;
877
878 /* Unknown bytes. */
879 fread(buffer, 1, 6, file);
880
881 GSM_ClearBitmap(&bitmap->Bitmap[0]);
882
883 x=0; y=0;
884 for (i=0; i<w*h; i++) {
885 if (fread(buffer, 1, 1, file)!=1) return ERR_UNKNOWN;
886 if (buffer[0]=='1') GSM_SetPointBitmap(&bitmap->Bitmap[0],x,y);
887 x++;
888 if (x==w) {x=0; y++;}
889 }
890
891#ifdef DEBUG
892 /* Some programs writes here fileinfo */
893 if (fread(buffer, 1, 1, file)==1) {
894 dbgprintf("Fileinfo: %c",buffer[0]);
895 while (fread(buffer, 1, 1, file)==1) {
896 if (buffer[0]!=0x0A) dbgprintf("%c",buffer[0]);
897 }
898 dbgprintf("\n");
899 }
900#endif
901 bitmap->Number = 1;
902 return(ERR_NONE);
903}
904
905static GSM_Error loadnsl(FILE *file, GSM_MultiBitmap *bitmap)
906{
907 unsigned char block[6],buffer[505];
908 int block_size;
909 GSM_Bitmap_TypesOldType;
910
911 while (fread(block,1,6,file)==6) {
912 block_size = block[4]*256 + block[5];
913 dbgprintf("Block %c%c%c%c, size %i\n",block[0],block[1],block[2],block[3],block_size);
914 if (!strncmp(block, "FORM", 4)) {
915 dbgprintf("File ID\n");
916 } else {
917 if (block_size>504) return ERR_UNKNOWN;
918 if (block_size!=0) {
919 fread(buffer,1,block_size,file);
920 /* if it's string, we end it with 0 */
921 buffer[block_size]=0;
922#ifdef DEBUG
923 if (!strncmp(block, "VERS", 4)) dbgprintf("File saved by: %s\n",buffer);
924 if (!strncmp(block, "MODL", 4)) dbgprintf("Logo saved from: %s\n",buffer);
925 if (!strncmp(block, "COMM", 4)) dbgprintf("Phone was connected to COM port: %s\n",buffer);
926#endif
927 if (!strncmp(block, "NSLD", 4)) {
928 bitmap->Bitmap[0].BitmapHeight = 48;
929 bitmap->Bitmap[0].BitmapWidth = 84;
930 OldType = bitmap->Bitmap[0].Type;
931 PHONE_DecodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
932 if (OldType != GSM_None) bitmap->Bitmap[0].Type = OldType;
933 dbgprintf("Startup logo (size %i)\n",block_size);
934 }
935 }
936 }
937 }
938 bitmap->Number = 1;
939 return(ERR_NONE);
940}
941
942static GSM_Error loadwbmp(FILE *file, GSM_MultiBitmap *bitmap)
943{
944 unsigned char buffer[10000];
945
946 fread(buffer,1,4,file);
947 bitmap->Bitmap[0].BitmapWidth = buffer[2];
948 bitmap->Bitmap[0].BitmapHeight = buffer[3];
949 bitmap->Number = 1;
950
951 fread(buffer,1,10000,file);
952 PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo, buffer, &bitmap->Bitmap[0]);
953 GSM_ReverseBitmap(&bitmap->Bitmap[0]);
954
955 return ERR_NONE;
956}
957
958GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
959{
960 FILE *file;
961 unsigned charbuffer[300];
962
963 file = fopen(FileName, "rb");
964 if (file == NULL) return ERR_CANTOPENFILE;
965
966 fread(buffer, 1, 9, file); /* Read the header of the file. */
967 rewind(file);
968
969 bitmap->Bitmap[0].DefaultBitmap = false;
970
971 /* Attempt to identify filetype */
972 if (memcmp(buffer, "BM",2)==0) {
973 return loadbmp(file,bitmap);
974 } else if (buffer[0] == 0x00 && buffer[1] == 0x00) {
975 return loadwbmp(file,bitmap);
976 } else if (memcmp(buffer, "NLM",3)==0) {
977 return loadnlm(file,bitmap);
978 } else if (memcmp(buffer, "NOL",3)==0) {
979 return loadnolngg(file,bitmap,true);
980 } else if (memcmp(buffer, "NGG",3)==0) {
981 return loadnolngg(file,bitmap,false);
982 } else if (memcmp(buffer, "FORM",4)==0) {
983 return loadnsl(file,bitmap);
984 }
985 return ERR_UNKNOWN;
986}
987
988void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length)
989{
990 int Width, Height;
991
992 Buffer[(*Length)++] = 0x00;
993 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
994 Buffer[(*Length)++] = Width;
995 Buffer[(*Length)++] = Height;
996 Buffer[(*Length)++] = 0x01;
997 PHONE_EncodeBitmap(Type, Buffer + (*Length), Bitmap);
998 (*Length) = (*Length) + PHONE_GetBitmapSize(Type,0,0);
999}
1000
1001/* How should editor hadle tabs in this file? Add editor commands here.
1002 * vim: noexpandtab sw=8 ts=8 sts=8:
1003 */