summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service/gsmlogo.c
Side-by-side diff
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 @@
+/* (c) 2001-2004 by Marcin Wiacek */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "../misc/misc.h"
+#include "../misc/coding/coding.h"
+#include "gsmlogo.h"
+#include "gsmnet.h"
+
+void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height)
+{
+ *width = 0;
+ *height = 0;
+ switch (Type) {
+ case GSM_EMSSmallPicture : *width=8; *height=8; break;
+ case GSM_EMSMediumPicture : *width=16; *height=16; break;
+ case GSM_EMSBigPicture : *width=32; *height=32; break;
+ case GSM_NokiaOperatorLogo :
+ case GSM_NokiaCallerLogo : *width=72; *height=14; break;
+ case GSM_NokiaPictureImage : *width=72; *height=28; break;
+ case GSM_Nokia7110OperatorLogo :
+ case GSM_Nokia6510OperatorLogo : *width=78; *height=21; break;
+ case GSM_NokiaStartupLogo : *width=84; *height=48; break;
+ case GSM_Nokia6210StartupLogo : *width=96; *height=60; break;
+ case GSM_Nokia7110StartupLogo : *width=96; *height=65; break;
+ case GSM_EMSVariablePicture : break;
+ case GSM_AlcatelBMMIPicture : break;
+ }
+}
+
+int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int Width, int Height)
+{
+ int width, height, x;
+
+ PHONE_GetBitmapWidthHeight(Type, &width, &height);
+ if (width == 0 && height == 0) {
+ width = Width;
+ height = Height;
+ }
+ switch (Type) {
+ case GSM_Nokia6510OperatorLogo:
+ x = width * height;
+ return x/8 + (x%8 > 0);
+ case GSM_Nokia7110OperatorLogo:
+ return (width*height + 7)/8;
+ case GSM_NokiaStartupLogo:
+ case GSM_NokiaOperatorLogo:
+ case GSM_NokiaCallerLogo:
+ case GSM_NokiaPictureImage:
+ case GSM_EMSSmallPicture:
+ case GSM_EMSMediumPicture:
+ case GSM_EMSBigPicture:
+ case GSM_EMSVariablePicture:
+ return height*width/8;
+ case GSM_Nokia7110StartupLogo:
+ case GSM_Nokia6210StartupLogo:
+ return (height+7)/8*width;
+ case GSM_AlcatelBMMIPicture:
+ return width*((height+7)/8);
+ }
+ return 0;
+}
+
+static bool PHONE_IsPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
+{
+ int i=0, pixel;
+
+ switch (Type) {
+ case GSM_NokiaStartupLogo:
+ case GSM_Nokia6210StartupLogo:
+ case GSM_Nokia7110StartupLogo:
+ case GSM_Nokia6510OperatorLogo:
+ i=(buffer[(y/8*width) + x] & 1<<(y%8));
+ break;
+ case GSM_NokiaOperatorLogo:
+ case GSM_Nokia7110OperatorLogo:
+ case GSM_NokiaCallerLogo:
+ case GSM_EMSVariablePicture:
+ case GSM_EMSSmallPicture:
+ case GSM_EMSMediumPicture:
+ case GSM_EMSBigPicture:
+ pixel=width*y + x;
+ i=(buffer[pixel/8] & 1<<(7-(pixel%8)));
+ break;
+ case GSM_NokiaPictureImage:
+ i=(buffer[9*y + x/8] & 1<<(7-(x%8)));
+ break;
+ case GSM_AlcatelBMMIPicture:
+ break;
+ }
+ if (i) return true; else return false;
+}
+
+static void PHONE_SetPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
+{
+ int pixel;
+
+ switch (Type) {
+ case GSM_NokiaStartupLogo:
+ case GSM_Nokia6210StartupLogo:
+ case GSM_Nokia7110StartupLogo:
+ case GSM_Nokia6510OperatorLogo:
+ buffer[(y/8*width)+x] |= 1 << (y%8);
+ break;
+ case GSM_NokiaOperatorLogo:
+ case GSM_Nokia7110OperatorLogo:
+ case GSM_NokiaCallerLogo:
+ case GSM_EMSSmallPicture:
+ case GSM_EMSMediumPicture:
+ case GSM_EMSBigPicture:
+ case GSM_EMSVariablePicture:
+ pixel = width*y + x;
+ buffer[pixel/8] |= 1 << (7-(pixel%8));
+ break;
+ case GSM_NokiaPictureImage:
+ buffer[9*y + x/8] |= 1 << (7-(x%8));
+ break;
+ case GSM_AlcatelBMMIPicture:
+ pixel = height / 8;
+ if ((height % 8) != 0) pixel++;
+ buffer[pixel*x + y/8] |= 1 << (7 - (y%8));
+ break;
+ }
+}
+
+void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
+{
+ int width, height, x,y;
+
+ PHONE_GetBitmapWidthHeight(Type, &width, &height);
+ if (Type != GSM_Nokia6510OperatorLogo && Type != GSM_Nokia7110OperatorLogo && Type != GSM_EMSVariablePicture) {
+ Bitmap->BitmapHeight = height;
+ Bitmap->BitmapWidth = width;
+ }
+ switch (Type) {
+ case GSM_NokiaOperatorLogo :
+ case GSM_Nokia7110OperatorLogo :
+ case GSM_Nokia6510OperatorLogo : Bitmap->Type=GSM_OperatorLogo; break;
+ case GSM_NokiaCallerLogo : Bitmap->Type=GSM_CallerGroupLogo; break;
+ case GSM_AlcatelBMMIPicture :
+ case GSM_NokiaStartupLogo :
+ case GSM_Nokia7110StartupLogo :
+ case GSM_Nokia6210StartupLogo : Bitmap->Type=GSM_StartupLogo; break;
+ case GSM_NokiaPictureImage :
+ case GSM_EMSVariablePicture :
+ case GSM_EMSSmallPicture :
+ case GSM_EMSMediumPicture :
+ case GSM_EMSBigPicture : Bitmap->Type=GSM_PictureImage; break;
+ }
+
+ Bitmap->Location = 0;
+ Bitmap->Text[0] = 0;
+ Bitmap->Text[1] = 0;
+ Bitmap->BitmapEnabled = false;
+ Bitmap->DefaultName = false;
+ Bitmap->DefaultBitmap = false;
+ Bitmap->DefaultRingtone = false;
+ Bitmap->RingtoneID = 0;
+ Bitmap->NetworkCode[0] = 0;
+ Bitmap->Sender[0] = 0;
+ Bitmap->Sender[1] = 0;
+ Bitmap->ID = 0;
+
+ GSM_ClearBitmap(Bitmap);
+ for (x=0;x<Bitmap->BitmapWidth;x++) {
+ for (y=0;y<Bitmap->BitmapHeight;y++) {
+ if (PHONE_IsPointBitmap(Type, buffer, x, y, Bitmap->BitmapWidth, Bitmap->BitmapHeight)) {
+ GSM_SetPointBitmap(Bitmap,x,y);
+ }
+ }
+ }
+}
+
+void PHONE_ClearBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height)
+{
+ memset(buffer,0,PHONE_GetBitmapSize(Type,width,height));
+}
+
+void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
+{
+ int width, height, x, y;
+ GSM_Bitmap dest;
+
+ PHONE_GetBitmapWidthHeight(Type, &width, &height);
+ if (width == 0 && height == 0) {
+ width = Bitmap->BitmapWidth;
+ height = Bitmap->BitmapHeight;
+ }
+ GSM_ResizeBitmap(&dest, Bitmap, width, height);
+ PHONE_ClearBitmap(Type, buffer, width, height);
+
+ for (x=0;x<width;x++) {
+ for (y=0;y<height;y++) {
+ if (GSM_IsPointBitmap(&dest,x,y)) PHONE_SetPointBitmap(Type, buffer, x, y, width, height);
+ }
+ }
+}
+
+void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height)
+{
+ switch (Type) {
+ case GSM_CallerGroupLogo: *width=72; *height=14; break;
+ case GSM_OperatorLogo : *width=101;*height=21; break;
+ case GSM_StartupLogo : *width=96; *height=65; break;
+ case GSM_PictureImage : *width=72; *height=28; break;
+ default : break;
+ }
+}
+
+void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
+{
+ SetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
+}
+
+void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
+{
+ ClearBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
+}
+
+bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
+{
+ if (GetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x)) return true; else return false;
+}
+
+void GSM_ClearBitmap(GSM_Bitmap *bmp)
+{
+ memset(bmp->BitmapPoints,0,GSM_GetBitmapSize(bmp));
+}
+
+int GSM_GetBitmapSize(GSM_Bitmap *bmp)
+{
+ return bmp->BitmapWidth*bmp->BitmapHeight/8+1;
+}
+
+void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
+{
+ int x,y;
+
+ for (y=0;y<bitmap->BitmapHeight;y++) {
+ for (x=0;x<bitmap->BitmapWidth;x++) {
+ if (GSM_IsPointBitmap(bitmap,x,y)) {
+ fprintf(file,"#");
+ } else {
+ fprintf(file," ");
+ }
+ }
+ fprintf(file,"\n");
+ }
+}
+
+void GSM_ReverseBitmap(GSM_Bitmap *Bitmap)
+{
+ int x, y;
+
+ for (x=0;x<Bitmap->BitmapWidth;x++) {
+ for (y=0;y<Bitmap->BitmapHeight;y++) {
+ if (GSM_IsPointBitmap(Bitmap,x,y)) {
+ GSM_ClearPointBitmap(Bitmap, x, y);
+ } else {
+ GSM_SetPointBitmap(Bitmap, x, y);
+ }
+ }
+ }
+}
+
+void GSM_ResizeBitmap(GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height)
+{
+ int startx=0,endx=0,setx=0, starty=0,endy=0,sety=0, x, y;
+
+ if (src->BitmapWidth<=width) {
+ startx = 0;
+ endx = src->BitmapWidth;
+ setx = (width-src->BitmapWidth)/2;
+ } else {
+ startx = (src->BitmapWidth-width)/2;
+ endx = startx + width;
+ setx = 0;
+ }
+ if (src->BitmapHeight<=height) {
+ starty = 0;
+ endy = src->BitmapHeight;
+ sety = (height-src->BitmapHeight)/2;
+ } else {
+ starty = (src->BitmapHeight-height)/2;
+ endy = starty + height;
+ sety = 0;
+ }
+ dest->BitmapHeight = height;
+ dest->BitmapWidth = width;
+ GSM_ClearBitmap(dest);
+ for (x=startx;x<endx;x++) {
+ for (y=starty;y<endy;y++) {
+ if (GSM_IsPointBitmap(src,x,y))
+ GSM_SetPointBitmap(dest,setx+x-startx,sety+y-starty);
+ }
+ }
+}
+
+GSM_Error Bitmap2BMP(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
+{
+ int x,y,pos,i,sizeimage,buffpos=0;
+ unsigned char buff[1];
+ div_t division;
+ bool isfile=false;
+
+ unsigned char header[]={
+/*1'st header*/ 'B','M', /* BMP file ID */
+ 0x00,0x00,0x00,0x00, /* Size of file */
+ 0x00,0x00, /* Reserved for future use */
+ 0x00,0x00, /* Reserved for future use */
+ 62,0x00,0x00,0x00, /* Offset for image data */
+
+/*2'nd header*/ 40,0x00,0x00,0x00, /* Length of this part of header */
+ 0x00,0x00,0x00,0x00, /* Width of image */
+ 0x00,0x00,0x00,0x00, /* Height of image */
+ 1,0x00, /* How many planes in target device */
+ 1,0x00, /* How many colors in image. 1 means 2^1=2 colors */
+ 0x00,0x00,0x00,0x00, /* Type of compression. 0 means no compression */
+/*Sometimes */ 0x00,0x00,0x00,0x00, /* Size of part with image data */
+/*ttttttt...*/ 0xE8,0x03,0x00,0x00, /* XPelsPerMeter */
+/*hhiiiiissss*/ 0xE8,0x03,0x00,0x00, /* YPelsPerMeter */
+/*part of header*/0x02,0x00,0x00,0x00, /* How many colors from palette is used */
+/*doesn't exist*/ 0x00,0x00,0x00,0x00, /* How many colors from palette is required to display image. 0 means all */
+
+/*Color palette*/ 0x00,0x00,0x00, /* First color in palette in Blue, Green, Red. Here white */
+ 0x00, /* Each color in palette is end by 4'th byte */
+ 102, 204, 102, /* Second color in palette in Blue, Green, Red. Here green */
+ 0x00}; /* Each color in palette is end by 4'th byte */
+
+ if (file!=NULL) isfile=true;
+
+ header[22]=bitmap->BitmapHeight;
+ header[18]=bitmap->BitmapWidth;
+
+ pos = 7;
+ sizeimage = 0;
+ /*lines are written from the last to the first*/
+ for (y=bitmap->BitmapHeight-1;y>=0;y--) {
+ i=1;
+ for (x=0;x<bitmap->BitmapWidth;x++) {
+ /*new byte !*/
+ if (pos==7) {
+ if (x!=0) sizeimage++;
+ i++;
+ /*each line is written in multiply of 4 bytes*/
+ if(i==5) i=1;
+ }
+ pos--;
+ /*going to new byte*/
+ if (pos<0) pos=7;
+ }
+ /*going to new byte*/
+ pos=7;
+ sizeimage++;
+ if (i!=1) {
+ /*each line is written in multiply of 4 bytes*/
+ while (i!=5) {
+ sizeimage++;
+ i++;
+ }
+ }
+ }
+ dbgprintf("Data size in BMP file: %i\n",sizeimage);
+ division=div(sizeimage,256);
+ header[35]=division.quot;
+ header[34]=sizeimage-(division.quot*256);
+ sizeimage=sizeimage+sizeof(header);
+ dbgprintf("Size of BMP file: %i\n",sizeimage);
+ division=div(sizeimage,256);
+ header[3]=division.quot;
+ header[2]=sizeimage-(division.quot*256);
+
+ if (isfile) {
+ fwrite(header,1,sizeof(header),file);
+ } else {
+ memcpy(buffer,header,sizeof(header));
+ buffpos += sizeof(header);
+ }
+
+ pos=7;
+ /*lines are written from the last to the first*/
+ for (y=bitmap->BitmapHeight-1;y>=0;y--) {
+ i=1;
+ for (x=0;x<bitmap->BitmapWidth;x++) {
+ /*new byte !*/
+ if (pos==7) {
+ if (x!=0) {
+ if (isfile) {
+ fwrite(buff, 1, sizeof(buff), file);
+ } else {
+ memcpy (buffer+buffpos,buff,1);
+ buffpos++;
+ }
+ }
+ i++;
+ /*each line is written in multiply of 4 bytes*/
+ if(i==5) i=1;
+ buff[0]=0;
+ }
+ if (!GSM_IsPointBitmap(bitmap,x,y)) buff[0]|=(1<<pos);
+ pos--;
+ /*going to new byte*/
+ if (pos<0) pos=7;
+ }
+ /*going to new byte*/
+ pos=7;
+ if (isfile) {
+ fwrite(buff, 1, sizeof(buff), file);
+ } else {
+ memcpy (buffer+buffpos,buff,1);
+ buffpos++;
+ }
+ if (i!=1) {
+ /*each line is written in multiply of 4 bytes*/
+ while (i!=5) {
+ buff[0]=0;
+ if (isfile) {
+ fwrite(buff, 1, sizeof(buff), file);
+ } else {
+ memcpy (buffer+buffpos,buff,1);
+ buffpos++;
+ }
+ i++;
+ }
+ }
+ }
+ return ERR_NONE;
+}
+
+static GSM_Error savebmp(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ GSM_Error error;
+
+ error=Bitmap2BMP(NULL,file,&bitmap->Bitmap[0]);
+ return error;
+}
+
+static void PrivSaveNLMWBMP(FILE *file, GSM_Bitmap *Bitmap)
+{
+ unsigned char buffer[1000];
+ int x,y,pos,pos2;
+ div_t division;
+
+ pos=0;pos2=7;
+ for (y=0;y<Bitmap->BitmapHeight;y++) {
+ for (x=0;x<Bitmap->BitmapWidth;x++) {
+ if (pos2==7) buffer[pos]=0;
+ if (GSM_IsPointBitmap(Bitmap,x,y)) buffer[pos]|=(1<<pos2);
+ pos2--;
+ /* going to new line */
+ if (pos2<0) {pos2=7;pos++;}
+ }
+ /* for startup logos - new line with new byte */
+ if (pos2!=7) {pos2=7;pos++;}
+ }
+
+ division=div(Bitmap->BitmapWidth,8);
+ /* For startup logos */
+ if (division.rem!=0) division.quot++;
+
+ fwrite(buffer,1,(division.quot*Bitmap->BitmapHeight),file);
+}
+
+static GSM_Error savenlm(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ int i;
+ char header[]={
+ 'N','L','M',' ', /* Nokia Logo Manager file ID. */
+ 0x01,
+ 0x00, /* 0x00 (OP), 0x01 (CLI), 0x02 (Startup), 0x03 (Picture)*/
+ 0x00, /* Number of images inside file - 1. 0x01==2 images, 0x03==4 images, etc. */
+ 0x00, /* Width. */
+ 0x00, /* Height. */
+ 0x01};
+
+ switch (bitmap->Bitmap[0].Type) {
+ case GSM_OperatorLogo : header[5]=0x00; break;
+ case GSM_CallerGroupLogo : header[5]=0x01; break;
+ case GSM_StartupLogo : header[5]=0x02; break;
+ case GSM_PictureImage : header[5]=0x03; break;
+ default : return ERR_UNKNOWN;
+ }
+ header[6] = bitmap->Number - 1;
+ header[7] = bitmap->Bitmap[0].BitmapWidth;
+ header[8] = bitmap->Bitmap[0].BitmapHeight;
+ fwrite(header,1,sizeof(header),file);
+
+ for (i=0;i<bitmap->Number;i++) {
+ PrivSaveNLMWBMP(file, &bitmap->Bitmap[i]);
+ }
+
+ return ERR_NONE;
+}
+
+static void PrivSaveNGGNOL(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ char buffer[GSM_BITMAP_SIZE];
+ int x,y,current=0;
+
+ for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
+ for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++) {
+ if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
+ buffer[current++] = '1';
+ } else {
+ buffer[current++] = '0';
+ }
+ }
+ }
+ fwrite(buffer,1,current,file);
+}
+
+static GSM_Error savengg(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ char header[]={
+ 'N','G','G',0x00,0x01,0x00,
+ 0x00,0x00, /* Width */
+ 0x00,0x00, /* Height */
+ 0x01,0x00,0x01,0x00,
+ 0x00, /* Unknown.Can't be checksum - for */
+ /* the same logo files can be different */
+ 0x00};
+
+ header[6] = bitmap->Bitmap[0].BitmapWidth;
+ header[8] = bitmap->Bitmap[0].BitmapHeight;
+ fwrite(header,1,sizeof(header),file);
+
+ PrivSaveNGGNOL(file,bitmap);
+
+ return ERR_NONE;
+}
+
+static GSM_Error savenol(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ int country,net;
+ char header[]={
+ 'N','O','L',0x00,0x01,0x00,
+ 0x00,0x00, /* MCC */
+ 0x00,0x00, /* MNC */
+ 0x00,0x00, /* Width */
+ 0x00,0x00, /* Height */
+ 0x01,0x00,0x01,0x00,
+ 0x00, /* Unknown.Can't be checksum - for */
+ /* the same logo files can be different */
+ 0x00};
+
+ if (bitmap->Bitmap[0].Type == GSM_OperatorLogo) sscanf(bitmap->Bitmap[0].NetworkCode, "%d %d", &country, &net);
+
+ header[6] = country%256;
+ header[7] = country/256;
+ header[8] = net%256;
+ header[9] = net/256;
+ header[10] = bitmap->Bitmap[0].BitmapWidth;
+ header[12] = bitmap->Bitmap[0].BitmapHeight;
+ fwrite(header,1,sizeof(header),file);
+
+ PrivSaveNGGNOL(file,bitmap);
+
+ return ERR_NONE;
+}
+
+static GSM_Error savexpm(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ int x,y;
+
+ fprintf(file,"/* XPM */\n");
+ fprintf(file,"static char * ala_xpm[] = {\n");
+ fprintf(file,"\"%i %i 2 1\",\n",bitmap->Bitmap[0].BitmapWidth,bitmap->Bitmap[0].BitmapHeight);
+ fprintf(file,"\". s c m #000000 g4 #000000 g #000000 c #000000\",\n");
+ fprintf(file,"\"# s c m #ffffff g4 #ffffff g #ffffff c #ffffff\",\n");
+
+ for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
+ fprintf(file,"\"");
+ for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++)
+ if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
+ fprintf(file,".");
+ } else {
+ fprintf(file,"#");
+ }
+ fprintf(file,"\"");
+ if (y==bitmap->Bitmap[0].BitmapHeight-1) {
+ fprintf(file,"};\n");
+ } else {
+ fprintf(file,",\n");
+ }
+ }
+
+ return ERR_NONE;
+}
+
+static GSM_Error savensl(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ char buffer[GSM_BITMAP_SIZE];
+ unsigned char header[]={
+ 'F','O','R','M', 0x01,0xFE, /* File ID block, size 1*256+0xFE=510*/
+ 'N','S','L','D', 0x01,0xF8}; /* Startup Logo block, size 1*256+0xF8=504*/
+
+ fwrite(header,1,sizeof(header),file);
+ PHONE_EncodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
+ fwrite(buffer,1,PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0),file);
+
+ return ERR_NONE;
+}
+
+static GSM_Error savewbmp(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ unsigned char buffer[4];
+
+ buffer[0] = 0x00;
+ buffer[1] = 0x00;
+ buffer[2] = bitmap->Bitmap[0].BitmapWidth;
+ buffer[3] = bitmap->Bitmap[0].BitmapHeight;
+ fwrite(buffer,1,4,file);
+
+ PrivSaveNLMWBMP(file, &bitmap->Bitmap[0]);
+
+ return ERR_NONE;
+}
+
+GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
+{
+ FILE *file;
+ GSM_Error error=ERR_NONE;
+
+ file = fopen(FileName, "wb");
+ if (file == NULL) return ERR_CANTOPENFILE;
+
+ /* Attempt to identify filetype */
+ if (strstr(FileName,".nlm")) {
+ error=savenlm(file,bitmap);
+ } else if (strstr(FileName,".ngg")) {
+ error=savengg(file,bitmap);
+ } else if (strstr(FileName,".nol")) {
+ error=savenol(file,bitmap);
+ } else if (strstr(FileName,".xpm")) {
+ error=savexpm(file,bitmap);
+ } else if (strstr(FileName,".nsl")) {
+ error=savensl(file,bitmap);
+ } else if (strstr(FileName,".wbmp")) {
+ error=savewbmp(file,bitmap);
+ } else {
+ error=savebmp(file,bitmap);
+ }
+ fclose(file);
+
+ return error;
+}
+
+GSM_Error BMP2Bitmap(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
+{
+ bool first_white,isfile=false;
+ unsigned char buff[34];
+ int w,h,pos,y,x,i,buffpos=0;
+#ifdef DEBUG
+ int sizeimage=0;
+#endif
+
+ if (bitmap->Type == GSM_None) bitmap->Type = GSM_StartupLogo;
+ if (file!=NULL) isfile=true;
+ if (isfile) {
+ fread(buff, 1, 34, file);
+ } else {
+ memcpy(buff,buffer,34);
+ }
+
+ /* height and width of image in the file */
+ h=buff[22]+256*buff[21];
+ w=buff[18]+256*buff[17];
+ dbgprintf("Image Size in BMP file: %dx%d\n",w,h);
+
+ GSM_GetMaxBitmapWidthHeight(bitmap->Type, &bitmap->BitmapWidth, &bitmap->BitmapHeight);
+ if (h<bitmap->BitmapHeight) bitmap->BitmapHeight=h;
+ if (w<bitmap->BitmapWidth) bitmap->BitmapWidth=w;
+ dbgprintf("Height %i %i, width %i %i\n",h,bitmap->BitmapHeight,w,bitmap->BitmapWidth);
+
+ GSM_ClearBitmap(bitmap);
+
+#ifdef DEBUG
+ dbgprintf("Number of colors in BMP file: ");
+ switch (buff[28]) {
+ case 1 : dbgprintf("2 (supported)\n"); break;
+ case 4 : dbgprintf("16 (NOT SUPPORTED)\n"); break;
+ case 8 : dbgprintf("256 (NOT SUPPORTED)\n"); break;
+ case 24 : dbgprintf("True Color (NOT SUPPORTED)\n"); break;
+ default : dbgprintf("unknown\n"); break;
+ }
+#endif
+ if (buff[28]!=1) {
+ dbgprintf("Wrong number of colors\n");
+ return ERR_FILENOTSUPPORTED;
+ }
+
+#ifdef DEBUG
+ dbgprintf("Compression in BMP file: ");
+ switch (buff[30]) {
+ case 0 :dbgprintf("no compression (supported)\n"); break;
+ case 1 :dbgprintf("RLE8 (NOT SUPPORTED)\n"); break;
+ case 2 :dbgprintf("RLE4 (NOT SUPPORTED)\n"); break;
+ default :dbgprintf("unknown\n"); break;
+ }
+#endif
+ if (buff[30]!=0) {
+ dbgprintf("Compression type not supported\n");
+ return ERR_FILENOTSUPPORTED;
+ }
+
+ /* read rest of header (if exists) and color palette */
+ if (isfile) {
+ pos=buff[10]-34;
+ fread(buff, 1, pos, file);
+ } else {
+ pos=buff[10]-34;
+ buffpos=buff[10];
+ memcpy (buff,buffer+34,pos);
+ }
+
+#ifdef DEBUG
+ dbgprintf("First color in BMP file: %i %i %i ",buff[pos-8], buff[pos-7], buff[pos-6]);
+ if (buff[pos-8]==0 && buff[pos-7]==0 && buff[pos-6]==0) dbgprintf("(white)");
+ if (buff[pos-8]==0xFF && buff[pos-7]==0xFF && buff[pos-6]==0xFF) dbgprintf("(black)");
+ if (buff[pos-8]==102 && buff[pos-7]==204 && buff[pos-6]==102) dbgprintf("(green)");
+ dbgprintf("\n");
+ dbgprintf("Second color in BMP file: %i %i %i ",buff[pos-38], buff[pos-37], buff[pos-36]);
+ if (buff[pos-4]==0 && buff[pos-3]==0 && buff[pos-2]==0) dbgprintf("(white)");
+ if (buff[pos-4]==0xFF && buff[pos-3]==0xFF && buff[pos-2]==0xFF) dbgprintf("(black)");
+ dbgprintf("\n");
+#endif
+ first_white=true;
+ if (buff[pos-8]!=0 || buff[pos-7]!=0 || buff[pos-6]!=0) first_white=false;
+
+ pos=7;
+ /* lines are written from the last to the first */
+ for (y=h-1;y>=0;y--) { i=1;
+ for (x=0;x<w;x++) { /* new byte ! */
+ if (pos==7) { if (isfile) {
+ fread(buff, 1, 1, file);
+ } else {
+ memcpy (buff,buffer+buffpos,1);
+ buffpos++;
+ }
+#ifdef DEBUG
+ sizeimage++;
+#endif
+ i++;
+ /* each line is written in multiply of 4 bytes */
+ if(i==5) i=1;
+ }
+ /* we have top left corner ! */
+ if (x<=bitmap->BitmapWidth && y<=bitmap->BitmapHeight) { if (first_white) {
+ if ((buff[0]&(1<<pos))<=0) GSM_SetPointBitmap(bitmap,x,y);
+ } else {
+ if ((buff[0]&(1<<pos))>0) GSM_SetPointBitmap(bitmap,x,y);
+ }
+ }
+ pos--;
+ /* going to new byte */
+ if (pos<0) pos=7;
+ }
+ /* going to new byte */
+ pos=7;
+ if (i!=1) {
+ /* each line is written in multiply of 4 bytes */
+ while (i!=5) {
+ if (isfile) {
+ fread(buff, 1, 1, file);
+ } else {
+ memcpy (buff,buffer+buffpos,1);
+ buffpos++;
+ }
+#ifdef DEBUG
+ sizeimage++;
+#endif
+ i++;
+ }
+ }
+ }
+#ifdef DEBUG
+ dbgprintf("Data size in BMP file: %i\n",sizeimage);
+#endif
+ return(ERR_NONE);
+}
+
+static GSM_Error loadbmp(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ GSM_Error error;
+
+ error=BMP2Bitmap(NULL,file,&bitmap->Bitmap[0]);
+ bitmap->Number = 1;
+ return error;
+}
+
+static GSM_Error loadnlm (FILE *file, GSM_MultiBitmap *bitmap)
+{
+ unsigned char buffer[1000];
+ int pos,pos2,x,y,h,w,i,number;
+ div_t division;
+
+ fread(buffer,1,5,file);
+
+ fread(buffer,1,1,file);
+ switch (buffer[0]) {
+ case 0x00:
+ dbgprintf("Operator logo\n");
+ if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
+ break;
+ case 0x01:
+ dbgprintf("Caller logo\n");
+ if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
+ break;
+ case 0x02:
+ dbgprintf("Startup logo\n");
+ if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_StartupLogo;
+ break;
+ case 0x03:
+ dbgprintf("Picture Image logo\n");
+ if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_PictureImage;
+ break;
+ }
+
+ bitmap->Number = 0;
+ fread(buffer,1,4,file);
+ number = buffer[0] + 1;
+ w = buffer[1];
+ h = buffer[2];
+ for (i=0;i<number;i++) {
+ bitmap->Bitmap[i].Type = bitmap->Bitmap[0].Type;
+ GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[i].Type, &bitmap->Bitmap[i].BitmapWidth, &bitmap->Bitmap[i].BitmapHeight);
+ if (h < bitmap->Bitmap[i].BitmapHeight) bitmap->Bitmap[i].BitmapHeight = h;
+ if (w < bitmap->Bitmap[i].BitmapWidth) bitmap->Bitmap[i].BitmapWidth = w;
+
+ division=div(w,8);
+ /* For startup logos */
+ if (division.rem!=0) division.quot++;
+ if (fread(buffer,1,(division.quot*h),file)!=(unsigned int)(division.quot*h)) return ERR_UNKNOWN;
+
+ GSM_ClearBitmap(&bitmap->Bitmap[i]);
+
+ pos=0;pos2=7;
+ for (y=0;y<h;y++) {
+ for (x=0;x<w;x++) {
+ if ((buffer[pos]&(1<<pos2))>0) {
+ if (y<bitmap->Bitmap[i].BitmapHeight && x<bitmap->Bitmap[i].BitmapWidth) GSM_SetPointBitmap(&bitmap->Bitmap[i],x,y);
+ }
+ pos2--;
+ /* going to new byte */
+ if (pos2<0) {pos2=7;pos++;}
+ }
+ /* for startup logos-new line means new byte */
+ if (pos2!=7) {pos2=7;pos++;}
+ }
+ bitmap->Number++;
+ if (bitmap->Number == MAX_MULTI_BITMAP) break;
+ }
+ return (ERR_NONE);
+}
+
+static GSM_Error loadnolngg(FILE *file, GSM_MultiBitmap *bitmap, bool nolformat)
+{
+ unsigned char buffer[2000];
+ int i,h,w,x,y;
+
+ fread(buffer, 1, 6, file);
+
+ if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
+ if (nolformat) {
+ fread(buffer, 1, 4, file);
+ sprintf(bitmap->Bitmap[0].NetworkCode, "%d %02d", buffer[0]+256*buffer[1], buffer[2]);
+ if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
+ }
+
+ fread(buffer, 1, 4, file);
+ w = buffer[0];
+ h = buffer[2];
+ GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[0].Type, &bitmap->Bitmap[0].BitmapWidth, &bitmap->Bitmap[0].BitmapHeight);
+ if (h < bitmap->Bitmap[0].BitmapHeight) bitmap->Bitmap[0].BitmapHeight = h;
+ if (w < bitmap->Bitmap[0].BitmapWidth) bitmap->Bitmap[0].BitmapWidth = w;
+
+ /* Unknown bytes. */
+ fread(buffer, 1, 6, file);
+
+ GSM_ClearBitmap(&bitmap->Bitmap[0]);
+
+ x=0; y=0;
+ for (i=0; i<w*h; i++) {
+ if (fread(buffer, 1, 1, file)!=1) return ERR_UNKNOWN;
+ if (buffer[0]=='1') GSM_SetPointBitmap(&bitmap->Bitmap[0],x,y);
+ x++;
+ if (x==w) {x=0; y++;}
+ }
+
+#ifdef DEBUG
+ /* Some programs writes here fileinfo */
+ if (fread(buffer, 1, 1, file)==1) {
+ dbgprintf("Fileinfo: %c",buffer[0]);
+ while (fread(buffer, 1, 1, file)==1) {
+ if (buffer[0]!=0x0A) dbgprintf("%c",buffer[0]);
+ }
+ dbgprintf("\n");
+ }
+#endif
+ bitmap->Number = 1;
+ return(ERR_NONE);
+}
+
+static GSM_Error loadnsl(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ unsigned char block[6],buffer[505];
+ int block_size;
+ GSM_Bitmap_Types OldType;
+
+ while (fread(block,1,6,file)==6) {
+ block_size = block[4]*256 + block[5];
+ dbgprintf("Block %c%c%c%c, size %i\n",block[0],block[1],block[2],block[3],block_size);
+ if (!strncmp(block, "FORM", 4)) {
+ dbgprintf("File ID\n");
+ } else {
+ if (block_size>504) return ERR_UNKNOWN;
+ if (block_size!=0) {
+ fread(buffer,1,block_size,file);
+ /* if it's string, we end it with 0 */
+ buffer[block_size]=0;
+#ifdef DEBUG
+ if (!strncmp(block, "VERS", 4)) dbgprintf("File saved by: %s\n",buffer);
+ if (!strncmp(block, "MODL", 4)) dbgprintf("Logo saved from: %s\n",buffer);
+ if (!strncmp(block, "COMM", 4)) dbgprintf("Phone was connected to COM port: %s\n",buffer);
+#endif
+ if (!strncmp(block, "NSLD", 4)) {
+ bitmap->Bitmap[0].BitmapHeight = 48;
+ bitmap->Bitmap[0].BitmapWidth = 84;
+ OldType = bitmap->Bitmap[0].Type;
+ PHONE_DecodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
+ if (OldType != GSM_None) bitmap->Bitmap[0].Type = OldType;
+ dbgprintf("Startup logo (size %i)\n",block_size);
+ }
+ }
+ }
+ }
+ bitmap->Number = 1;
+ return(ERR_NONE);
+}
+
+static GSM_Error loadwbmp(FILE *file, GSM_MultiBitmap *bitmap)
+{
+ unsigned char buffer[10000];
+
+ fread(buffer,1,4,file);
+ bitmap->Bitmap[0].BitmapWidth = buffer[2];
+ bitmap->Bitmap[0].BitmapHeight = buffer[3];
+ bitmap->Number = 1;
+
+ fread(buffer,1,10000,file);
+ PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo, buffer, &bitmap->Bitmap[0]);
+ GSM_ReverseBitmap(&bitmap->Bitmap[0]);
+
+ return ERR_NONE;
+}
+
+GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
+{
+ FILE *file;
+ unsigned char buffer[300];
+
+ file = fopen(FileName, "rb");
+ if (file == NULL) return ERR_CANTOPENFILE;
+
+ fread(buffer, 1, 9, file); /* Read the header of the file. */
+ rewind(file);
+
+ bitmap->Bitmap[0].DefaultBitmap = false;
+
+ /* Attempt to identify filetype */
+ if (memcmp(buffer, "BM",2)==0) {
+ return loadbmp(file,bitmap);
+ } else if (buffer[0] == 0x00 && buffer[1] == 0x00) {
+ return loadwbmp(file,bitmap);
+ } else if (memcmp(buffer, "NLM",3)==0) {
+ return loadnlm(file,bitmap);
+ } else if (memcmp(buffer, "NOL",3)==0) {
+ return loadnolngg(file,bitmap,true);
+ } else if (memcmp(buffer, "NGG",3)==0) {
+ return loadnolngg(file,bitmap,false);
+ } else if (memcmp(buffer, "FORM",4)==0) {
+ return loadnsl(file,bitmap);
+ }
+ return ERR_UNKNOWN;
+}
+
+void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length)
+{
+ int Width, Height;
+
+ Buffer[(*Length)++] = 0x00;
+ PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
+ Buffer[(*Length)++] = Width;
+ Buffer[(*Length)++] = Height;
+ Buffer[(*Length)++] = 0x01;
+ PHONE_EncodeBitmap(Type, Buffer + (*Length), Bitmap);
+ (*Length) = (*Length) + PHONE_GetBitmapSize(Type,0,0);
+}
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */