From 3991c54a27d35a82a0be512f694941277c966a20 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sun, 3 Sep 2006 18:28:26 +0000 Subject: Fix Pbmtonokia: magic missing from headers git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@32 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/pbm/pbmtonokia.c | 595 +++++++++++++++++++++++++++++++-------------- doc/HISTORY | 3 + 2 files changed, 409 insertions(+), 189 deletions(-) diff --git a/converter/pbm/pbmtonokia.c b/converter/pbm/pbmtonokia.c index 66678b7b..c94a80c5 100644 --- a/converter/pbm/pbmtonokia.c +++ b/converter/pbm/pbmtonokia.c @@ -1,225 +1,442 @@ -/* pbmtonokia.c - convert a portable bitmap to Nokia Smart Messaging +/* pbmtonokia.c - convert a PBM image to Nokia Smart Messaging Formats (NOL, NGG, HEX) -** Copyright (C)2001 OMS Open Media System GmbH, Tim Rühsen -** . -** -** Permission to use, copy, modify, and distribute this software and its -** documentation for any purpose and without fee is hereby granted, provided -** that the above copyright notice appear in all copies and that both that -** copyright notice and this permission notice appear in supporting -** documentation. This software is provided "as is" without express or -** implied warranty. + Copyright information is at end of file. +*/ -History - 07.06.2001 Created - 20.11.2001 Handle Picture Messages - new option -txt to embed text into Picture Messages - new option -net to specify operator network code for - Nokia Operator Logos +#define _BSD_SOURCE /* Make sure strcasecmp() is in string.h */ +#include -Notes: - - limited to rows <= 255 and columns <= 255 - - limited to b/w graphics, not animated +#include "pm_c_util.h" +#include "nstring.h" +#include "mallocvar.h" +#include "shhopt.h" +#include "pbm.h" -Testing: - Testing was done with SwissCom SMSC (Switzerland) and IC3S SMSC (Germany). - The data was send with EMI/UCP protocol over TCP/IP. +enum outputFormat { + FMT_HEX_NOL, + FMT_HEX_NGG, + FMT_HEX_NPM, + FMT_NOL, + FMT_NGG +}; - - 7.6.2001: tested with Nokia 3210: 72x14 Operator Logo - - 7.6.2001: tested with Nokia 6210: 72x14 Operator Logo and - 72x14 Group Graphic -Todo: - - more testing - - sendsms compatibility ? - - are -fmt NOL and -fmt NGG working ok? */ +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char * inputFileName; /* Filename of input files */ + int outputFormat; + const char * networkCode; + const char * txt; /* NULL means unspecified */ +}; -#define _BSD_SOURCE /* Make sure strcasecmp() is in string.h */ -#include -#include "nstring.h" -#include "pbm.h" -#define FMT_HEX_NOL 1 -#define FMT_HEX_NGG 2 -#define FMT_HEX_NPM 3 -#define FMT_NOL 4 -#define FMT_NGG 5 - -static void -usage(char *myname) -{ - pm_message("Copyright (C)2001 OMS GmbH"); - pm_message("Contact: Tim Ruehsen \n"); - pm_usage("[options] [pbmfile]\n" - " Options:\n" - " -fmt " - "Output format (default=HEX_NOL)\n" - " -net " - "Network code for NOL operator logos\n" - " -txt " - "Text for NMP picture messages\n"); - - exit(1); +static const char * +uppercase(const char * const subject) { + + char * buffer; + + buffer = malloc(strlen(subject) + 1); + + if (buffer == NULL) + pm_error("Out of memory allocating buffer for uppercasing a " + "%u-character string", strlen(subject)); + else { + unsigned int i; + + i = 0; + while (subject[i]) { + buffer[i] = TOUPPER(subject[i]); + ++i; + } + buffer[i] = '\0'; + } + return buffer; } -int -main(int argc, char *argv[]) -{ - FILE *fp; - bit **image; - unsigned int c; - int argpos, output=FMT_HEX_NOL, rows, cols, row, col, p, it, len; - char header[32], *myname; - char network_code[6+1]; - char *text=NULL; - - if ((myname=strrchr(argv[0],'/'))!=NULL) myname++; else myname=argv[0]; - pbm_init(&argc, argv); - strcpy(network_code, "62F210"); /* default is German D1 net */ - - for(argpos=1;argposargpos+1 && ISDIGIT(argv[argpos+1][0])) - {argpos++;break;} - } else if (STREQ(argv[argpos],"-fmt") && argc>argpos+1) { - ++argpos; - if (!strcasecmp(argv[argpos],"HEX_NOL")) output=FMT_HEX_NOL; - else if (!strcasecmp(argv[argpos],"HEX_NGG")) - output=FMT_HEX_NGG; - else if (!strcasecmp(argv[argpos],"HEX_NPM")) - output=FMT_HEX_NPM; - else if (!strcasecmp(argv[argpos],"NOL")) output=FMT_NOL; - else if (!strcasecmp(argv[argpos],"NGG")) output=FMT_NGG; - else usage(myname); - } else if (STREQ(argv[argpos],"-net") && argc>argpos+1) { - char * const network_code_arg=argv[++argpos]; - unsigned int it; - len=strlen(network_code_arg); - if (len!=6) - pm_error("Network code must be 6 hex-digits long"); - for (it=0;itargpos+1) { - text=argv[++argpos]; +static bool +ishexstring(const char * const subject) { + + bool retval; + unsigned int i; + + retval = TRUE; /* initial assumption */ + + for (i = 0; i < strlen(subject); ++i) + if (!ISXDIGIT(subject[i])) + retval = FALSE; + + return retval; +} + + + +static void +parseCommandLine(int argc, char ** argv, + struct cmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec array we return is stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + unsigned int fmtSpec, netSpec, txtSpec; + const char * fmtOpt; + const char * netOpt; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "fmt", OPT_STRING, &fmtOpt, + &fmtSpec, 0); + OPTENT3(0, "net", OPT_STRING, &netOpt, + &netSpec, 0); + OPTENT3(0, "txt", OPT_STRING, &cmdlineP->txt, + &txtSpec, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (fmtSpec) { + if (STRCASEEQ(fmtOpt, "HEX_NOL")) + cmdlineP->outputFormat = FMT_HEX_NOL; + else if (STRCASEEQ(fmtOpt, "HEX_NGG")) + cmdlineP->outputFormat = FMT_HEX_NGG; + else if (STRCASEEQ(fmtOpt, "HEX_NPM")) + cmdlineP->outputFormat = FMT_HEX_NPM; + else if (STRCASEEQ(fmtOpt, "NOL")) + cmdlineP->outputFormat = FMT_NOL; + else if (STRCASEEQ(fmtOpt, "NGG")) + cmdlineP->outputFormat = FMT_NGG; + else + pm_error("-fmt option must be HEX_NOL, HEX_NGG, HEX_NPM, " + "NOL, or NGG. You specified '%s'", fmtOpt); + } else + cmdlineP->outputFormat = FMT_HEX_NOL; + + if (netSpec) { + if (strlen(netOpt) != 6) + pm_error("-net option must be 6 hex digits long. " + "You specified %u characters", strlen(netOpt)); + else if (!ishexstring(netOpt)) + pm_error("-net option must be hexadecimal. You specified '%s'", + netOpt); + else + cmdlineP->networkCode = uppercase(netOpt); + } else + cmdlineP->networkCode = strdup("62F210"); /* German D1 net */ + + if (!txtSpec) + cmdlineP->txt = NULL; + + if (argc-1 == 0) + cmdlineP->inputFileName = "-"; + else if (argc-1 != 1) + pm_error("Program takes zero or one argument (filename). You " + "specified %d", argc-1); + else + cmdlineP->inputFileName = argv[1]; +} + + + +static void +freeCmdline(struct cmdlineInfo const cmdline) { + + strfree(cmdline.networkCode); +} + + + +static void +convertToHexNol(bit ** const image, + unsigned int const cols, + unsigned int const rows, + const char * const networkCode, + FILE * const ofP) { + + unsigned int row; + + /* header */ + fprintf(ofP, "06050415820000%s00%02X%02X01", networkCode, cols, rows); + + /* image */ + for (row = 0; row < rows; ++row) { + unsigned int col; + unsigned int p; + unsigned int c; + + c = 0; + + for (p = 0, col = 0; col < cols; ++col) { + if (image[row][col] == PBM_BLACK) + c |= 0x80 >> p; + if (++p == 8) { + fprintf(ofP, "%02X",c); + p = c = 0; } - else usage(myname); - } else break; + } + if (p > 0) + fprintf(ofP, "%02X", c); } +} - if (argpos==argc) { - image = pbm_readpbm(stdin, &cols, &rows); - } else { - fp=pm_openr(argv[argpos]); - image = pbm_readpbm(fp, &cols, &rows); - pm_close(fp); - } - memset(header,0,sizeof(header)); - switch (output) { - case FMT_HEX_NOL: - /* header */ - printf("06050415820000%s00%02X%02X01",network_code,cols,rows); - - /* image */ - for (row=0;row>p; - if (++p==8) { - printf("%02X",c); - p=c=0; - } +static void +convertToHexNgg(bit ** const image, + unsigned int const cols, + unsigned int const rows, + FILE * const ofP) { + + unsigned int row; + + /* header */ + fprintf(ofP, "0605041583000000%02X%02X01", cols, rows); + + /* image */ + for (row = 0; row < rows; ++row) { + unsigned int col; + unsigned int p; + unsigned int c; + + for (p = 0, c = 0, col = 0; col < cols; ++col) { + if (image[row][col] == PBM_BLACK) + c |= 0x80 >> p; + if (++p == 8) { + fprintf(ofP, "%02X", c); + p = c = 0; } - if (p) printf("%02X",c); } - break; - case FMT_HEX_NGG: - /* header */ - printf("0605041583000000%02X%02X01",cols,rows); - - /* image */ - for (row=0;row>p; - if (++p==8) { - printf("%02X",c); - p=c=0; - } + if (p > 0) + fprintf(ofP, "%02X", c); + } +} + + + + +static void +convertToHexNpm(bit ** const image, + unsigned int const cols, + unsigned int const rows, + const char * const text, + FILE * const ofP) { + + unsigned int row; + + /* header */ + fprintf(ofP, "060504158A0000"); + + /* text */ + if (text) { + size_t const len = strlen(text); + + unsigned int it; + + fprintf(ofP, "00%04X", len); + + for (it = 0; it < len; ++it) + fprintf(ofP, "%02X", text[it]); + } + + /* image */ + fprintf(ofP, "02%04X00%02X%02X01", (cols * rows) / 8 + 4, cols, rows); + + for (row = 0; row < rows; ++row) { + unsigned int col; + unsigned int p; + unsigned int c; + + for (p = 0, c = 0, col = 0; col < cols; ++col) { + if (image[row][col] == PBM_BLACK) + c |= 0x80 >> p; + if (++p == 8) { + fprintf(ofP, "%02X", c); + p = c = 0; } - if (p) printf("%02X",c); } - break; - case FMT_HEX_NPM: - /* header */ - printf("060504158A0000"); + if (p > 0) + fprintf(ofP, "%02X", c); + } +} + + + +static void +convertToNol(bit ** const image, + unsigned int const cols, + unsigned int const rows, + FILE * const ofP) { + + unsigned int row; + char header[32]; + + /* header - this is a hack */ + + header[ 0] = 'N'; + header[ 1] = 'O'; + header[ 2] = 'L'; + header[ 3] = 0; + header[ 4] = 1; + header[ 5] = 0; + header[ 6] = 4; + header[ 7] = 1; + header[ 8] = 1; + header[ 9] = 0; + header[10] = cols; + header[11] = 0; + header[12] = rows; + header[13] = 0; + header[14] = 1; + header[15] = 0; + header[16] = 1; + header[17] = 0; + header[18] = 0x53; + header[19] = 0; + + fwrite(header, 20, 1, ofP); + + /* image */ + for (row = 0; row < rows; ++row) { + unsigned int col; + unsigned int p; + unsigned int c; + + for (p = 0, c = 0, col = 0; col < cols; ++col) { + char const output = image[row][col] == PBM_BLACK ? '1' : '0'; - /* text */ - if (text!=NULL) { - printf("00%04X",(len=strlen(text))); - for (it=0;it>p; - if (++p==8) { - printf("%02X",c); - p=c=0; - } - } - if (p) printf("%02X",c); + + + +static void +convertToNgg(bit ** const image, + unsigned int const cols, + unsigned int const rows, + FILE * const ofP) { + + unsigned int row; + char header[32]; + + /* header - this is a hack */ + + header[ 0] = 'N'; + header[ 1] = 'G'; + header[ 2] = 'G'; + header[ 3] = 0; + header[ 4] = 1; + header[ 5] = 0; + header[ 6] = cols; + header[ 7] = 0; + header[ 8] = rows; + header[ 9] = 0; + header[10] = 1; + header[11] = 0; + header[12] = 1; + header[13] = 0; + header[14] = 0x4a; + header[15] = 0; + + fwrite(header, 16, 1, ofP); + + /* image */ + + for (row = 0; row < rows; ++row) { + unsigned int col; + unsigned int p; + unsigned int c; + + for (p = 0, c = 0, col = 0; col < cols; ++col) { + char const output = image[row][col] == PBM_BLACK ? '1' : '0'; + + putc(output, ofP); } + } +} + + + +int +main(int argc, + char * argv[]) { + + struct cmdlineInfo cmdline; + FILE * ifP; + bit ** bits; + int rows, cols; + + pbm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + ifP = pm_openr(cmdline.inputFileName); + bits = pbm_readpbm(ifP, &cols, &rows); + pm_close(ifP); + + switch (cmdline.outputFormat) { + case FMT_HEX_NOL: + convertToHexNol(bits, cols, rows, cmdline.networkCode, stdout); + break; + case FMT_HEX_NGG: + convertToHexNgg(bits, cols, rows, stdout); + break; + case FMT_HEX_NPM: + convertToHexNpm(bits, cols, rows, cmdline.txt, stdout); break; case FMT_NOL: - /* header - this is a hack */ - header[1]=header[4]=header[5]=header[11]=header[13]=1; - header[3]=4; - header[7]=cols; - header[9]=rows; - header[15]=0x53; - fwrite(header,17,1,stdout); - - /* image */ - for (row=0;row\n", - output); - return 1; } + +freeCmdline(cmdline); + return 0; } + + +/* Copyright (C)2001 OMS Open Media System GmbH, Tim Rühsen +** . +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. + + Created 2001.06.07 + +Notes: + - limited to rows <= 255 and columns <= 255 + - limited to b/w graphics, not animated + +Testing: + Testing was done with SwissCom SMSC (Switzerland) and IC3S SMSC (Germany). + The data was send with EMI/UCP protocol over TCP/IP. + + - 7.6.2001: tested with Nokia 3210: 72x14 Operator Logo + - 7.6.2001: tested with Nokia 6210: 72x14 Operator Logo and + 72x14 Group Graphic +*/ diff --git a/doc/HISTORY b/doc/HISTORY index 07ada5f3..fd51c67b 100644 --- a/doc/HISTORY +++ b/doc/HISTORY @@ -97,6 +97,9 @@ CHANGE HISTORY not yet BJH Release 10.36.0 + pbmtonokia: fix headers of NGG and NOL to include 3 character + magic. + Release allocated memory before longjmping from libnetpbm. Add pm_errormsg(), pm_setusererrormsg(), pm_setusermessage(). -- cgit 1.4.1