Imported gammu 0.90.7
[gammu.git] / common / service / gsmlogo.c
blob6d4a931a26bfb9ee110a3276edbf64ea36f47b18
2 #include <string.h>
3 #include <stdlib.h>
5 #include "../misc/misc.h"
6 #include "../misc/coding/coding.h"
7 #include "gsmlogo.h"
8 #include "gsmnet.h"
10 void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height)
12 *width = 0;
13 *height = 0;
14 switch (Type) {
15 case GSM_EMSSmallPicture : *width=8; *height=8; break;
16 case GSM_EMSMediumPicture : *width=16; *height=16; break;
17 case GSM_EMSBigPicture : *width=32; *height=32; break;
18 case GSM_NokiaOperatorLogo :
19 case GSM_NokiaCallerLogo : *width=72; *height=14; break;
20 case GSM_NokiaPictureImage : *width=72; *height=28; break;
21 case GSM_Nokia7110OperatorLogo :
22 case GSM_Nokia6510OperatorLogo : *width=78; *height=21; break;
23 case GSM_NokiaStartupLogo : *width=84; *height=48; break;
24 case GSM_Nokia6210StartupLogo : *width=96; *height=60; break;
25 case GSM_Nokia7110StartupLogo : *width=96; *height=65; break;
26 case GSM_EMSVariablePicture : break;
30 int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int Width, int Height)
32 int width, height, x;
34 PHONE_GetBitmapWidthHeight(Type, &width, &height);
35 if (width == 0 && height == 0) {
36 width = Width;
37 height = Height;
39 switch (Type) {
40 case GSM_Nokia6510OperatorLogo:
41 x = width * height;
42 return (x / 8) + (x % 8 > 0);
43 case GSM_Nokia7110OperatorLogo:
44 return (width*height + 7)/8;
45 case GSM_NokiaStartupLogo:
46 case GSM_NokiaOperatorLogo:
47 case GSM_NokiaCallerLogo:
48 case GSM_NokiaPictureImage:
49 case GSM_EMSSmallPicture:
50 case GSM_EMSMediumPicture:
51 case GSM_EMSBigPicture:
52 case GSM_EMSVariablePicture:
53 return height*width/8;
54 case GSM_Nokia7110StartupLogo:
55 case GSM_Nokia6210StartupLogo:
56 return (height+7)/8*width;
58 return 0;
61 static bool PHONE_IsPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
63 int i=0, pixel;
65 switch (Type) {
66 case GSM_NokiaStartupLogo:
67 case GSM_Nokia6210StartupLogo:
68 case GSM_Nokia7110StartupLogo:
69 case GSM_Nokia6510OperatorLogo:
70 i=(buffer[((y/8)*width) + x] & 1<<((y%8)));
71 break;
72 case GSM_NokiaOperatorLogo:
73 case GSM_Nokia7110OperatorLogo:
74 case GSM_NokiaCallerLogo:
75 case GSM_EMSVariablePicture:
76 case GSM_EMSSmallPicture:
77 case GSM_EMSMediumPicture:
78 case GSM_EMSBigPicture:
79 pixel=width*y + x;
80 i=(buffer[pixel/8] & 1<<(7-(pixel%8)));
81 break;
82 case GSM_NokiaPictureImage:
83 i=(buffer[9*y + (x/8)] & 1<<(7-(x%8)));
84 break;
86 if (i) return true; else return false;
89 static void PHONE_SetPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
91 int pixel;
93 switch (Type) {
94 case GSM_NokiaStartupLogo:
95 case GSM_Nokia6210StartupLogo:
96 case GSM_Nokia7110StartupLogo:
97 case GSM_Nokia6510OperatorLogo:
98 buffer[((y/8)*width)+x] |= 1 << (y%8);
99 break;
100 case GSM_NokiaOperatorLogo:
101 case GSM_Nokia7110OperatorLogo:
102 case GSM_NokiaCallerLogo:
103 case GSM_EMSSmallPicture:
104 case GSM_EMSMediumPicture:
105 case GSM_EMSBigPicture:
106 case GSM_EMSVariablePicture:
107 pixel = width*y + x;
108 buffer[pixel/8] |= 1 << (7-(pixel%8));
109 break;
110 case GSM_NokiaPictureImage:
111 buffer[9*y + (x/8)] |= 1 << (7-(x%8));
112 break;
116 void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
118 int width, height, x,y;
120 PHONE_GetBitmapWidthHeight(Type, &width, &height);
121 if (Type != GSM_Nokia6510OperatorLogo && Type != GSM_Nokia7110OperatorLogo && Type != GSM_EMSVariablePicture) {
122 Bitmap->Height = height;
123 Bitmap->Width = width;
125 switch (Type) {
126 case GSM_NokiaOperatorLogo :
127 case GSM_Nokia7110OperatorLogo :
128 case GSM_Nokia6510OperatorLogo : Bitmap->Type=GSM_OperatorLogo; break;
129 case GSM_NokiaCallerLogo : Bitmap->Type=GSM_CallerLogo; break;
130 case GSM_NokiaStartupLogo :
131 case GSM_Nokia7110StartupLogo :
132 case GSM_Nokia6210StartupLogo : Bitmap->Type=GSM_StartupLogo; break;
133 case GSM_NokiaPictureImage :
134 case GSM_EMSVariablePicture :
135 case GSM_EMSSmallPicture :
136 case GSM_EMSMediumPicture :
137 case GSM_EMSBigPicture : Bitmap->Type=GSM_PictureImage; break;
140 GSM_ClearBitmap(Bitmap);
141 for (x=0;x<Bitmap->Width;x++) {
142 for (y=0;y<Bitmap->Height;y++) {
143 if (PHONE_IsPointBitmap(Type, buffer, x, y, Bitmap->Width, Bitmap->Height)) {
144 GSM_SetPointBitmap(Bitmap,x,y);
150 void PHONE_ClearBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height)
152 memset(buffer,0,PHONE_GetBitmapSize(Type,width,height));
155 void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
157 int width, height;
158 int x, y;
159 GSM_Bitmap dest;
161 PHONE_GetBitmapWidthHeight(Type, &width, &height);
162 if (width == 0 && height == 0) {
163 width = Bitmap->Width;
164 height = Bitmap->Height;
166 GSM_ResizeBitmap(&dest, Bitmap, width, height);
167 PHONE_ClearBitmap(Type, buffer, width, height);
169 for (x=0;x<width;x++) {
170 for (y=0;y<height;y++) {
171 if (GSM_IsPointBitmap(&dest,x,y)) PHONE_SetPointBitmap(Type, buffer, x, y, width, height);
176 void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height)
178 switch (Type) {
179 case GSM_CallerLogo : *width=72; *height=14; break;
180 case GSM_OperatorLogo : *width=101;*height=21; break;
181 case GSM_StartupLogo : *width=96; *height=65; break;
182 case GSM_PictureImage : *width=72; *height=28; break;
183 default : break;
187 void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
189 SetBit(bmp->Bitmap,y*bmp->Width+x);
192 void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
194 ClearBit(bmp->Bitmap,y*bmp->Width+x);
197 bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
199 if (GetBit(bmp->Bitmap,y*bmp->Width+x)) return true; else return false;
202 void GSM_ClearBitmap(GSM_Bitmap *bmp)
204 memset(bmp->Bitmap,0,GSM_GetBitmapSize(bmp));
207 int GSM_GetBitmapSize(GSM_Bitmap *bmp)
209 return bmp->Width*bmp->Height/8+1;
212 void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
214 int x,y;
216 for (y=0;y<bitmap->Height;y++) {
217 for (x=0;x<bitmap->Width;x++) {
218 if (GSM_IsPointBitmap(bitmap,x,y)) {
219 fprintf(file,"#");
220 } else {
221 fprintf(file," ");
224 fprintf(file,"\n");
228 void GSM_ReverseBitmap(GSM_Bitmap *Bitmap)
230 int x, y;
232 for (x=0;x<Bitmap->Width;x++) {
233 for (y=0;y<Bitmap->Height;y++) {
234 if (GSM_IsPointBitmap(Bitmap,x,y)) {
235 GSM_ClearPointBitmap(Bitmap, x, y);
236 } else {
237 GSM_SetPointBitmap(Bitmap, x, y);
243 void GSM_ResizeBitmap(GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height)
245 int startx=0,endx=0,setx=0;
246 int starty=0,endy=0,sety=0;
247 int x, y;
249 if (src->Width<=width) {
250 startx = 0;
251 endx = src->Width;
252 setx = (width-src->Width)/2;
253 } else {
254 startx = (src->Width-width)/2;
255 endx = startx + width;
256 setx = 0;
258 if (src->Height<=height) {
259 starty = 0;
260 endy = src->Height;
261 sety = (height-src->Height)/2;
262 } else {
263 starty = (src->Height-height)/2;
264 endy = starty + height;
265 sety = 0;
267 dest->Height = height;
268 dest->Width = width;
269 GSM_ClearBitmap(dest);
270 for (x=startx;x<endx;x++) {
271 for (y=starty;y<endy;y++) {
272 if (GSM_IsPointBitmap(src,x,y))
273 GSM_SetPointBitmap(dest,setx+x-startx,sety+y-starty);
278 GSM_Error Bitmap2BMP(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
280 int x,y,pos,i,sizeimage,buffpos=0;
281 unsigned char buff[1];
282 div_t division;
283 bool isfile=false;
285 unsigned char header[]={
286 /*1'st header*/ 'B','M', /* BMP file ID */
287 0x00,0x00,0x00,0x00, /* Size of file */
288 0x00,0x00, /* Reserved for future use */
289 0x00,0x00, /* Reserved for future use */
290 62,0x00,0x00,0x00, /* Offset for image data */
292 /*2'nd header*/ 40,0x00,0x00,0x00, /* Length of this part of header */
293 0x00,0x00,0x00,0x00, /* Width of image */
294 0x00,0x00,0x00,0x00, /* Height of image */
295 1,0x00, /* How many planes in target device */
296 1,0x00, /* How many colors in image. 1 means 2^1=2 colors */
297 0x00,0x00,0x00,0x00, /* Type of compression. 0 means no compression */
298 /*Sometimes */ 0x00,0x00,0x00,0x00, /* Size of part with image data */
299 /*ttttttt...*/ 0xE8,0x03,0x00,0x00, /* XPelsPerMeter */
300 /*hhiiiiissss*/ 0xE8,0x03,0x00,0x00, /* YPelsPerMeter */
301 /*part of header*/0x02,0x00,0x00,0x00, /* How many colors from palette is used */
302 /*doesn't exist*/ 0x00,0x00,0x00,0x00, /* How many colors from palette is required to display image. 0 means all */
304 /*Color palette*/ 0x00,0x00,0x00, /* First color in palette in Blue, Green, Red. Here white */
305 0x00, /* Each color in palette is end by 4'th byte */
306 102, 204, 102, /* Second color in palette in Blue, Green, Red. Here green */
307 0x00}; /* Each color in palette is end by 4'th byte */
309 if (file!=NULL) isfile=true;
311 header[22]=bitmap->Height;
312 header[18]=bitmap->Width;
314 pos = 7;
315 sizeimage = 0;
316 /*lines are written from the last to the first*/
317 for (y=bitmap->Height-1;y>=0;y--) {
318 i=1;
319 for (x=0;x<bitmap->Width;x++) {
320 /*new byte !*/
321 if (pos==7) {
322 if (x!=0) sizeimage++;
323 i++;
324 /*each line is written in multiply of 4 bytes*/
325 if(i==5) i=1;
327 pos--;
328 /*going to new byte*/
329 if (pos<0) pos=7;
331 /*going to new byte*/
332 pos=7;
333 sizeimage++;
334 if (i!=1) {
335 /*each line is written in multiply of 4 bytes*/
336 while (i!=5) {
337 sizeimage++;
338 i++;
342 dbgprintf("Data size in BMP file: %i\n",sizeimage);
343 division=div(sizeimage,256);
344 header[35]=division.quot;
345 header[34]=sizeimage-(division.quot*256);
346 sizeimage=sizeimage+sizeof(header);
347 dbgprintf("Size of BMP file: %i\n",sizeimage);
348 division=div(sizeimage,256);
349 header[3]=division.quot;
350 header[2]=sizeimage-(division.quot*256);
352 if (isfile) fwrite(header,1,sizeof(header),file);
353 else {
354 memcpy(buffer,header,sizeof(header));
355 buffpos += sizeof(header);
358 pos=7;
359 /*lines are written from the last to the first*/
360 for (y=bitmap->Height-1;y>=0;y--) {
361 i=1;
362 for (x=0;x<bitmap->Width;x++) {
363 /*new byte !*/
364 if (pos==7) {
365 if (x!=0) {
366 if (isfile) fwrite(buff, 1, sizeof(buff), file);
367 else {
368 memcpy (buffer+buffpos,buff,1);
369 buffpos++;
372 i++;
373 /*each line is written in multiply of 4 bytes*/
374 if(i==5) i=1;
375 buff[0]=0;
377 if (!GSM_IsPointBitmap(bitmap,x,y)) buff[0]|=(1<<pos);
378 pos--;
379 /*going to new byte*/
380 if (pos<0) pos=7;
382 /*going to new byte*/
383 pos=7;
384 if (isfile) fwrite(buff, 1, sizeof(buff), file);
385 else {
386 memcpy (buffer+buffpos,buff,1);
387 buffpos++;
389 if (i!=1) {
390 /*each line is written in multiply of 4 bytes*/
391 while (i!=5) {
392 buff[0]=0;
393 if (isfile) fwrite(buff, 1, sizeof(buff), file);
394 else {
395 memcpy (buffer+buffpos,buff,1);
396 buffpos++;
398 i++;
402 return GE_NONE;
405 static GSM_Error savebmp(FILE *file, GSM_MultiBitmap *bitmap)
407 GSM_Error error;
409 error=Bitmap2BMP(NULL,file,&bitmap->Bitmap[0]);
410 return error;
413 static void PrivSaveNLMWBMP(FILE *file, GSM_Bitmap *Bitmap)
415 unsigned char buffer[1000];
416 int x,y,pos,pos2;
417 div_t division;
419 pos=0;pos2=7;
420 for (y=0;y<Bitmap->Height;y++) {
421 for (x=0;x<Bitmap->Width;x++) {
422 if (pos2==7) buffer[pos]=0;
423 if (GSM_IsPointBitmap(Bitmap,x,y)) buffer[pos]|=(1<<pos2);
424 pos2--;
425 /* going to new line */
426 if (pos2<0) {pos2=7;pos++;}
428 /* for startup logos - new line with new byte */
429 if (pos2!=7) {pos2=7;pos++;}
432 division=div(Bitmap->Width,8);
433 /* For startup logos */
434 if (division.rem!=0) division.quot++;
436 fwrite(buffer,1,(division.quot*Bitmap->Height),file);
439 static GSM_Error savenlm(FILE *file, GSM_MultiBitmap *bitmap)
441 int i;
442 char header[]={
443 'N','L','M',' ', /* Nokia Logo Manager file ID. */
444 0x01,
445 0x00, /* 0x00 (OP), 0x01 (CLI), 0x02 (Startup), 0x03 (Picture)*/
446 0x00, /* Number of images inside file - 1. 0x01==2 images, 0x03==4 images, etc. */
447 0x00, /* Width. */
448 0x00, /* Height. */
449 0x01};
451 switch (bitmap->Bitmap[0].Type) {
452 case GSM_OperatorLogo : header[5]=0x00; break;
453 case GSM_CallerLogo : header[5]=0x01; break;
454 case GSM_StartupLogo : header[5]=0x02; break;
455 case GSM_PictureImage : header[5]=0x03; break;
456 default : return GE_UNKNOWN;
458 header[6] = bitmap->Number - 1;
459 header[7] = bitmap->Bitmap[0].Width;
460 header[8] = bitmap->Bitmap[0].Height;
461 fwrite(header,1,sizeof(header),file);
463 for (i=0;i<bitmap->Number;i++) {
464 PrivSaveNLMWBMP(file, &bitmap->Bitmap[i]);
467 return GE_NONE;
470 static void PrivSaveNGGNOL(FILE *file, GSM_MultiBitmap *bitmap)
472 char buffer[GSM_BITMAP_SIZE];
473 int x,y,current=0;
475 for (y=0;y<bitmap->Bitmap[0].Height;y++) {
476 for (x=0;x<bitmap->Bitmap[0].Width;x++) {
477 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
478 buffer[current++] = '1';
479 } else {
480 buffer[current++] = '0';
484 fwrite(buffer,1,current,file);
487 static GSM_Error savengg(FILE *file, GSM_MultiBitmap *bitmap)
489 char header[]={
490 'N','G','G',0x00,0x01,0x00,
491 0x00,0x00, /* Width */
492 0x00,0x00, /* Height */
493 0x01,0x00,0x01,0x00,
494 0x00, /* Unknown.Can't be checksum - for */
495 /* the same logo files can be different */
496 0x00};
498 header[6] = bitmap->Bitmap[0].Width;
499 header[8] = bitmap->Bitmap[0].Height;
500 fwrite(header,1,sizeof(header),file);
502 PrivSaveNGGNOL(file,bitmap);
504 return GE_NONE;
507 static GSM_Error savenol(FILE *file, GSM_MultiBitmap *bitmap)
509 int country,net;
510 char header[]={
511 'N','O','L',0x00,0x01,0x00,
512 0x00,0x00, /* MCC */
513 0x00,0x00, /* MNC */
514 0x00,0x00, /* Width */
515 0x00,0x00, /* Height */
516 0x01,0x00,0x01,0x00,
517 0x00, /* Unknown.Can't be checksum - for */
518 /* the same logo files can be different */
519 0x00};
521 if (bitmap->Bitmap[0].Type == GSM_OperatorLogo) sscanf(bitmap->Bitmap[0].NetworkCode, "%d %d", &country, &net);
523 header[6] = country%256;
524 header[7] = country/256;
525 header[8] = net%256;
526 header[9] = net/256;
527 header[10] = bitmap->Bitmap[0].Width;
528 header[12] = bitmap->Bitmap[0].Height;
529 fwrite(header,1,sizeof(header),file);
531 PrivSaveNGGNOL(file,bitmap);
533 return GE_NONE;
536 static GSM_Error savexpm(FILE *file, GSM_MultiBitmap *bitmap)
538 int x,y;
540 fprintf(file,"/* XPM */\n");
541 fprintf(file,"static char * ala_xpm[] = {\n");
542 fprintf(file,"\"%i %i 2 1\",\n",bitmap->Bitmap[0].Width,bitmap->Bitmap[0].Height);
543 fprintf(file,"\". s c m #000000 g4 #000000 g #000000 c #000000\",\n");
544 fprintf(file,"\"# s c m #ffffff g4 #ffffff g #ffffff c #ffffff\",\n");
546 for (y=0;y<bitmap->Bitmap[0].Height;y++) {
547 fprintf(file,"\"");
548 for (x=0;x<bitmap->Bitmap[0].Width;x++)
549 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y))
550 fprintf(file,".");
551 else
552 fprintf(file,"#");
553 fprintf(file,"\"");
554 if (y==bitmap->Bitmap[0].Height-1)
555 fprintf(file,"};\n");
556 else
557 fprintf(file,",\n");
560 return GE_NONE;
563 static GSM_Error savensl(FILE *file, GSM_MultiBitmap *bitmap)
565 char buffer[GSM_BITMAP_SIZE];
566 unsigned char header[]={
567 'F','O','R','M', 0x01,0xFE, /* File ID block, size 1*256+0xFE=510*/
568 'N','S','L','D', 0x01,0xF8}; /* Startup Logo block, size 1*256+0xF8=504*/
570 fwrite(header,1,sizeof(header),file);
571 PHONE_EncodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
572 fwrite(buffer,1,PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0),file);
574 return GE_NONE;
577 static GSM_Error savewbmp(FILE *file, GSM_MultiBitmap *bitmap)
579 unsigned char buffer[4];
581 buffer[0] = 0x00;
582 buffer[1] = 0x00;
583 buffer[2] = bitmap->Bitmap[0].Width;
584 buffer[3] = bitmap->Bitmap[0].Height;
585 fwrite(buffer,1,4,file);
587 PrivSaveNLMWBMP(file, &bitmap->Bitmap[0]);
589 return GE_NONE;
592 GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
594 FILE *file;
595 GSM_Error error=GE_NONE;
597 file = fopen(FileName, "wb");
598 if (file == NULL) return(GE_CANTOPENFILE);
600 /* Attempt to identify filetype */
601 if (strstr(FileName,".nlm")) {
602 error=savenlm(file,bitmap);
603 } else if (strstr(FileName,".ngg")) {
604 error=savengg(file,bitmap);
605 } else if (strstr(FileName,".nol")) {
606 error=savenol(file,bitmap);
607 } else if (strstr(FileName,".xpm")) {
608 error=savexpm(file,bitmap);
609 } else if (strstr(FileName,".nsl")) {
610 error=savensl(file,bitmap);
611 } else if (strstr(FileName,".wbmp")) {
612 error=savewbmp(file,bitmap);
613 } else {
614 error=savebmp(file,bitmap);
616 fclose(file);
618 return error;
621 GSM_Error BMP2Bitmap(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
623 bool first_white,isfile=false;
624 unsigned char buff[34];
625 int w,h,pos,y,x,i,buffpos=0;
626 #ifdef DEBUG
627 int sizeimage=0;
628 #endif
630 if (bitmap->Type == GSM_None) bitmap->Type = GSM_StartupLogo;
631 if (file!=NULL) isfile=true;
632 if (isfile) {
633 fread(buff, 1, 34, file);
634 } else {
635 memcpy(buff,buffer,34);
638 /* height and width of image in the file */
639 h=buff[22]+256*buff[21];
640 w=buff[18]+256*buff[17];
641 dbgprintf("Image Size in BMP file: %dx%d\n",w,h);
643 GSM_GetMaxBitmapWidthHeight(bitmap->Type, &bitmap->Width, &bitmap->Height);
644 if (h<bitmap->Height) bitmap->Height=h;
645 if (w<bitmap->Width) bitmap->Width=w;
646 dbgprintf("Height %i %i, width %i %i\n",h,bitmap->Height,w,bitmap->Width);
648 GSM_ClearBitmap(bitmap);
650 #ifdef DEBUG
651 dbgprintf("Number of colors in BMP file: ");
652 switch (buff[28]) {
653 case 1 : dbgprintf("2 (supported)\n"); break;
654 case 4 : dbgprintf("16 (NOT SUPPORTED)\n"); break;
655 case 8 : dbgprintf("256 (NOT SUPPORTED)\n"); break;
656 case 24 : dbgprintf("True Color (NOT SUPPORTED)\n"); break;
657 default : dbgprintf("unknown\n"); break;
659 #endif
660 if (buff[28]!=1) {
661 dbgprintf("Wrong number of colors\n");
662 return GE_FILENOTSUPPORTED;
665 #ifdef DEBUG
666 dbgprintf("Compression in BMP file: ");
667 switch (buff[30]) {
668 case 0 :dbgprintf("no compression (supported)\n"); break;
669 case 1 :dbgprintf("RLE8 (NOT SUPPORTED)\n"); break;
670 case 2 :dbgprintf("RLE4 (NOT SUPPORTED)\n"); break;
671 default :dbgprintf("unknown\n"); break;
673 #endif
674 if (buff[30]!=0) {
675 dbgprintf("Compression type not supported\n");
676 return GE_FILENOTSUPPORTED;
679 /* read rest of header (if exists) and color palette */
680 if (isfile) {
681 pos=buff[10]-34;
682 fread(buff, 1, pos, file);
683 } else {
684 pos=buff[10]-34;
685 buffpos=buff[10];
686 memcpy (buff,buffer+34,pos);
689 #ifdef DEBUG
690 dbgprintf("First color in BMP file: %i %i %i ",buff[pos-8], buff[pos-7], buff[pos-6]);
691 if (buff[pos-8]==0 && buff[pos-7]==0 && buff[pos-6]==0) dbgprintf("(white)");
692 if (buff[pos-8]==0xFF && buff[pos-7]==0xFF && buff[pos-6]==0xFF) dbgprintf("(black)");
693 if (buff[pos-8]==102 && buff[pos-7]==204 && buff[pos-6]==102) dbgprintf("(green)");
694 dbgprintf("\n");
695 dbgprintf("Second color in BMP file: %i %i %i ",buff[pos-38], buff[pos-37], buff[pos-36]);
696 if (buff[pos-4]==0 && buff[pos-3]==0 && buff[pos-2]==0) dbgprintf("(white)");
697 if (buff[pos-4]==0xFF && buff[pos-3]==0xFF && buff[pos-2]==0xFF) dbgprintf("(black)");
698 dbgprintf("\n");
699 #endif
700 first_white=true;
701 if (buff[pos-8]!=0 || buff[pos-7]!=0 || buff[pos-6]!=0) first_white=false;
703 pos=7;
704 /* lines are written from the last to the first */
705 for (y=h-1;y>=0;y--) { i=1;
706 for (x=0;x<w;x++) { /* new byte ! */
707 if (pos==7) { if (isfile) {
708 fread(buff, 1, 1, file);
709 } else {
710 memcpy (buff,buffer+buffpos,1);
711 buffpos++;
713 #ifdef DEBUG
714 sizeimage++;
715 #endif
716 i++;
717 /* each line is written in multiply of 4 bytes */
718 if(i==5) i=1;
720 /* we have top left corner ! */
721 if (x<=bitmap->Width && y<=bitmap->Height) { if (first_white) {
722 if ((buff[0]&(1<<pos))<=0) GSM_SetPointBitmap(bitmap,x,y);
723 } else {
724 if ((buff[0]&(1<<pos))>0) GSM_SetPointBitmap(bitmap,x,y);
727 pos--;
728 /* going to new byte */
729 if (pos<0) pos=7;
731 /* going to new byte */
732 pos=7;
733 if (i!=1) {
734 /* each line is written in multiply of 4 bytes */
735 while (i!=5) {
736 if (isfile) {
737 fread(buff, 1, 1, file);
738 } else {
739 memcpy (buff,buffer+buffpos,1);
740 buffpos++;
742 #ifdef DEBUG
743 sizeimage++;
744 #endif
745 i++;
749 #ifdef DEBUG
750 dbgprintf("Data size in BMP file: %i\n",sizeimage);
751 #endif
752 return(GE_NONE);
755 static GSM_Error loadbmp(FILE *file, GSM_MultiBitmap *bitmap)
757 GSM_Error error;
759 error=BMP2Bitmap(NULL,file,&bitmap->Bitmap[0]);
760 bitmap->Number = 1;
761 return error;
764 static GSM_Error loadnlm (FILE *file, GSM_MultiBitmap *bitmap)
766 unsigned char buffer[1000];
767 int pos,pos2,x,y,h,w,i,number;
768 div_t division;
770 fread(buffer,1,5,file);
772 fread(buffer,1,1,file);
773 switch (buffer[0]) {
774 case 0x00:
775 dbgprintf("Operator logo\n");
776 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
777 break;
778 case 0x01:
779 dbgprintf("Caller logo\n");
780 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerLogo;
781 break;
782 case 0x02:
783 dbgprintf("Startup logo\n");
784 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_StartupLogo;
785 break;
786 case 0x03:
787 dbgprintf("Picture Image logo\n");
788 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_PictureImage;
789 break;
792 bitmap->Number = 0;
793 fread(buffer,1,4,file);
794 number = buffer[0] + 1;
795 w = buffer[1];
796 h = buffer[2];
797 for (i=0;i<number;i++) {
798 bitmap->Bitmap[i].Type = bitmap->Bitmap[0].Type;
799 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[i].Type, &bitmap->Bitmap[i].Width, &bitmap->Bitmap[i].Height);
800 if (h < bitmap->Bitmap[i].Height) bitmap->Bitmap[i].Height = h;
801 if (w < bitmap->Bitmap[i].Width) bitmap->Bitmap[i].Width = w;
803 division=div(w,8);
804 /* For startup logos */
805 if (division.rem!=0) division.quot++;
806 if (fread(buffer,1,(division.quot*h),file)!=(unsigned int)(division.quot*h)) return GE_UNKNOWN;
808 GSM_ClearBitmap(&bitmap->Bitmap[i]);
810 pos=0;pos2=7;
811 for (y=0;y<h;y++) {
812 for (x=0;x<w;x++) {
813 if ((buffer[pos]&(1<<pos2))>0) {
814 if (y<bitmap->Bitmap[i].Height && x<bitmap->Bitmap[i].Width) GSM_SetPointBitmap(&bitmap->Bitmap[i],x,y);
816 pos2--;
817 /* going to new byte */
818 if (pos2<0) {pos2=7;pos++;}
820 /* for startup logos-new line means new byte */
821 if (pos2!=7) {pos2=7;pos++;}
823 bitmap->Number++;
824 if (bitmap->Number == MAX_MULTI_BITMAP) break;
826 return (GE_NONE);
829 static GSM_Error loadnolngg(FILE *file, GSM_MultiBitmap *bitmap, bool nolformat)
831 unsigned char buffer[2000];
832 int i,h,w,x,y;
834 fread(buffer, 1, 6, file);
836 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerLogo;
837 if (nolformat) {
838 fread(buffer, 1, 4, file);
839 sprintf(bitmap->Bitmap[0].NetworkCode, "%d %02d", buffer[0]+256*buffer[1], buffer[2]);
840 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
843 fread(buffer, 1, 4, file);
844 w = buffer[0];
845 h = buffer[2];
846 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[0].Type, &bitmap->Bitmap[0].Width, &bitmap->Bitmap[0].Height);
847 if (h < bitmap->Bitmap[0].Height) bitmap->Bitmap[0].Height = h;
848 if (w < bitmap->Bitmap[0].Width) bitmap->Bitmap[0].Width = w;
850 /* Unknown bytes. */
851 fread(buffer, 1, 6, file);
853 GSM_ClearBitmap(&bitmap->Bitmap[0]);
855 x=0; y=0;
856 for (i=0; i<w*h; i++) {
857 if (fread(buffer, 1, 1, file)!=1) return GE_UNKNOWN;
858 if (buffer[0]=='1') GSM_SetPointBitmap(&bitmap->Bitmap[0],x,y);
859 x++;
860 if (x==w) {x=0; y++;}
863 #ifdef DEBUG
864 /* Some programs writes here fileinfo */
865 if (fread(buffer, 1, 1, file)==1) {
866 dbgprintf("Fileinfo: %c",buffer[0]);
867 while (fread(buffer, 1, 1, file)==1) {
868 if (buffer[0]!=0x0A) dbgprintf("%c",buffer[0]);
870 dbgprintf("\n");
872 #endif
873 bitmap->Number = 1;
874 return(GE_NONE);
877 static GSM_Error loadnsl(FILE *file, GSM_MultiBitmap *bitmap)
879 unsigned char block[6],buffer[505];
880 int block_size;
881 GSM_Bitmap_Types OldType;
883 while (fread(block,1,6,file)==6) {
884 block_size = block[4]*256 + block[5];
885 dbgprintf("Block %c%c%c%c, size %i\n",block[0],block[1],block[2],block[3],block_size);
886 if (!strncmp(block, "FORM", 4)) {
887 dbgprintf("File ID\n");
888 } else {
889 if (block_size>504) return(GE_UNKNOWN);
890 if (block_size!=0) {
891 fread(buffer,1,block_size,file);
892 /* if it's string, we end it with 0 */
893 buffer[block_size]=0;
894 #ifdef DEBUG
895 if (!strncmp(block, "VERS", 4)) dbgprintf("File saved by: %s\n",buffer);
896 if (!strncmp(block, "MODL", 4)) dbgprintf("Logo saved from: %s\n",buffer);
897 if (!strncmp(block, "COMM", 4)) dbgprintf("Phone was connected to COM port: %s\n",buffer);
898 #endif
899 if (!strncmp(block, "NSLD", 4)) {
900 bitmap->Bitmap[0].Height = 48;
901 bitmap->Bitmap[0].Width = 84;
902 OldType = bitmap->Bitmap[0].Type;
903 PHONE_DecodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
904 if (OldType != GSM_None) bitmap->Bitmap[0].Type = OldType;
905 dbgprintf("Startup logo (size %i)\n",block_size);
910 bitmap->Number = 1;
911 return(GE_NONE);
914 static GSM_Error loadwbmp(FILE *file, GSM_MultiBitmap *bitmap)
916 unsigned char buffer[10000];
918 fread(buffer,1,4,file);
919 bitmap->Bitmap[0].Width = buffer[2];
920 bitmap->Bitmap[0].Height = buffer[3];
921 bitmap->Number = 1;
923 fread(buffer,1,10000,file);
924 PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo, buffer, &bitmap->Bitmap[0]);
925 GSM_ReverseBitmap(&bitmap->Bitmap[0]);
927 return(GE_NONE);
930 GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
932 FILE *file;
933 unsigned char buffer[300];
935 file = fopen(FileName, "rb");
936 if (file == NULL) return(GE_CANTOPENFILE);
938 fread(buffer, 1, 9, file); /* Read the header of the file. */
939 rewind(file);
941 bitmap->Bitmap[0].DefaultBitmap = false;
943 /* Attempt to identify filetype */
944 if (memcmp(buffer, "BM",2)==0) {
945 return loadbmp(file,bitmap);
946 } else if (buffer[0] == 0x00 && buffer[1] == 0x00) {
947 return loadwbmp(file,bitmap);
948 } else if (memcmp(buffer, "NLM",3)==0) {
949 return loadnlm(file,bitmap);
950 } else if (memcmp(buffer, "NOL",3)==0) {
951 return loadnolngg(file,bitmap,true);
952 } else if (memcmp(buffer, "NGG",3)==0) {
953 return loadnolngg(file,bitmap,false);
954 } else if (memcmp(buffer, "FORM",4)==0) {
955 return loadnsl(file,bitmap);
957 return GE_UNKNOWN;
960 void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length)
962 int Width, Height;
964 Buffer[(*Length)++] = 0x00;
965 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
966 Buffer[(*Length)++] = Width;
967 Buffer[(*Length)++] = Height;
968 Buffer[(*Length)++] = 0x01;
969 PHONE_EncodeBitmap(Type, Buffer + (*Length), Bitmap);
970 (*Length) = (*Length) + PHONE_GetBitmapSize(Type,0,0);
973 /* How should editor hadle tabs in this file? Add editor commands here.
974 * vim: noexpandtab sw=8 ts=8 sts=8: