Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

seewbmp.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /* seebmp -- simple viewer for WBMP images (image/vnd.wap.wbmp) */
00058 
00059 /*
00060  * 
00061  * Copyright (c) Richard Braakman <dark@xs4all.nl>
00062  * All rights reserved.
00063  * 
00064  * Redistribution and use in source and binary forms, with or without
00065  * modification, are permitted provided that the following conditions
00066  * are met:
00067  * 1. Redistributions of source code must retain the above copyright
00068  *    notice, this list of conditions and the following disclaimer.
00069  * 2. Redistributions in binary form must reproduce the above copyright
00070  *    notice, this list of conditions and the following disclaimer in the
00071  *    documentation and/or other materials provided with the distribution.
00072  * 
00073  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00074  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00075  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00076  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00077  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00078  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00079  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00080  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00081  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00082  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00083  * SUCH DAMAGE.
00084  * 
00085  */
00086 
00087 
00088 #include <stdio.h>
00089 #include <stddef.h>
00090 #include <stdlib.h>
00091 #include <string.h>
00092 
00093 /* The spec includes a multi-byte integer format.  For reasons of simplicity, we
00094  * only handle integers that end up fitting in 31 bits.  This limits picture
00095  * sizes to about 2 billion pixels width or height, which I think we can live
00096  * with. */
00097 /* The function returns -1 in case of an error. */
00098 static long get_mbi(FILE *infile) {
00099     int c;
00100     long result = 0;
00101 
00102     do {
00103         c = getc(infile);
00104         if (c < 0) return -1;
00105         result = (result << 7) | (c & 0x7f);
00106     } while (c & 0x80);
00107 
00108     return result;
00109 }
00110 
00111 /* This function is like get_mbi, but it ignores the value of the result.
00112  * So it's not limited to 31 bits, and it ends up skipping all bytes that
00113  * have their high bit set. */
00114 /* The function returns 0 for success, or -1 in case of an error. */
00115 static int skip_mbi(FILE *infile) {
00116     int c;
00117 
00118     do {
00119         c = getc(infile);
00120         if (c < 0) return -1;
00121     } while (c & 0x80);
00122 
00123     return 0;
00124 }
00125 
00126 static int show_image_from_file(char *bmpname, FILE *bmpfile,
00127             long width, long height) {
00128     long w, h;
00129 
00130     for (h = 0; h < height; h++) {
00131         /* w is incremented in its inner loop */
00132         for (w = 0; w < width; ) {
00133             int c;
00134             unsigned int bit;
00135 
00136             c = getc(bmpfile);
00137             if (c < 0) {
00138                 perror(bmpname);
00139                 return -1;
00140             }
00141 
00142             for (bit = 0x80; bit > 0 && w < width; bit >>= 1, w++) {
00143                 putc((c & bit) ? '*' : ' ', stdout);
00144             }
00145         }
00146         putc('\n', stdout);
00147     }
00148 
00149     return 0;
00150 }
00151 
00152 /* These are global because that's easier.  In a real parser they would
00153  * be part of an image descriptor structure */
00154 struct parm {
00155     struct parm *next;
00156     char *name;
00157     char *value;
00158 };
00159 
00160 struct parm *extparms = NULL;
00161 
00162 static void clear_extparms(void) {
00163     while (extparms) {
00164         struct parm *tmp = extparms;
00165         extparms = extparms->next;
00166         free(tmp->name);
00167         free(tmp->value);
00168         free(tmp);
00169     }
00170 }
00171 
00172 /* Record a new parameter.  The name and value will be used directly,
00173  * not copied. */
00174 static int new_extparm(char *name, char *value) {
00175     struct parm *new;
00176     struct parm *p;
00177     
00178     /* Construct a new node */
00179     new = (struct parm *)malloc(sizeof(struct parm));
00180     if (!new)
00181         return -1;
00182 
00183     new->name = name;
00184     new->value = value;
00185     new->next = NULL;
00186 
00187     /* Add it to the end of the list. */
00188     if (!extparms) {
00189         extparms = new;
00190     } else {
00191         p = extparms;
00192         while (p->next) { 
00193             p = p->next;
00194         }
00195         p->next = new;
00196     }
00197 
00198     return 0;
00199 }
00200 
00201 static void print_extparms(FILE *outfile) {
00202     struct parm *p;
00203 
00204     for (p = extparms; p; p = p->next) {
00205         fprintf(outfile, "%s=%s\n", p->name, p->value);
00206     }
00207 }
00208 
00209 static int parse_headers(FILE *bmpfile) {
00210     int c;
00211     int exttype;
00212 
00213     clear_extparms();
00214 
00215     c = getc(bmpfile);
00216     if (c < 0) return -1;
00217     if (!(c & 0x80)) {
00218         /* No extension headers follow */
00219         return 0;
00220     }
00221     exttype = (c >> 5) & 0x03;
00222     /* None of these headers do much at this time, but they
00223      * might be meaningful with later specifications */
00224     switch (exttype) {
00225         case 0: 
00226             /* All we know of type 0 headers is that
00227              * the high bit is a continuation bit.
00228              * That makes them exactly like an MBI. */
00229             if (skip_mbi(bmpfile) < 0) return -1;
00230             break;
00231         case 1: case 2:
00232             /* We don't know what to do with these */
00233             return -1;
00234         case 3:
00235             /* A sequence of parameter/value combinations */
00236             do {
00237                 int namelen, valuelen;
00238                 char *name, *value;
00239                 c = getc(bmpfile);
00240                 if (c < 0) return -1;
00241 
00242                 namelen = (c >> 4) & 0x07;
00243                 name = malloc(namelen + 1);
00244                 if (!name) return -1;
00245                 if (fread(name, namelen, 1, bmpfile) < (size_t) namelen)
00246                     return -1;
00247 
00248                 valuelen = c & 0x0f;
00249                 value = malloc(valuelen + 1);
00250                 if (!value) { free(name); return -1; }
00251                 if (fread(value, valuelen, 1, bmpfile) < (size_t) valuelen)
00252                     return -1;
00253             
00254                 new_extparm(name, value);
00255             } while (c & 0x80);
00256             break;
00257     }
00258     return 0;
00259 }
00260 
00261 /* Return 0 for success, < 0 for failure */
00262 static int show_wbmp_from_file(char *bmpname, FILE *bmpfile) {
00263     long typefield;
00264     long width, height;
00265 
00266     typefield = get_mbi(bmpfile);
00267     if (typefield < 0) {
00268         perror(bmpname);
00269         return -1;
00270     }
00271 
00272     if (parse_headers(bmpfile) < 0) {
00273         fprintf(stderr, "%s: format error in headers\n", bmpname);
00274         return -1;
00275     }
00276     
00277     width = get_mbi(bmpfile);
00278     height = get_mbi(bmpfile);
00279     if (width < 0 || height < 0) {
00280         fprintf(stderr, "%s: error reading height and width\n",
00281             bmpname);
00282         return -1;
00283     }
00284 
00285     switch (typefield) {
00286         case 0:
00287             printf("%s, %ldx%ld B/W bitmap, no compression\n",
00288                 bmpname, width, height);
00289             print_extparms(stdout);
00290             if (show_image_from_file(bmpname, bmpfile,
00291                         width, height) < 0) {
00292                 return -1;
00293             }
00294             break;
00295         default:
00296             fprintf(stderr, "%s: cannot handle level %ld wbmp\n",
00297                 bmpname, typefield);
00298             return -1;
00299     }
00300 
00301     return 0;
00302 }
00303 
00304 int main(int argc, char *argv[]) {
00305     int i;
00306     /* 1 means an I/O error.  No other error values are used yet. */
00307     int exitvalue = 0;
00308 
00309     if (argc > 1) {
00310         for (i = 1; i < argc; i++) {
00311             FILE *bmpfile;
00312 
00313             bmpfile = fopen(argv[i], "r");
00314             if (bmpfile) {
00315                 if (show_wbmp_from_file(argv[i], bmpfile) < 0) {
00316                     /* We've already reported the error */
00317                     exitvalue = 1;
00318                 }
00319                 if (fclose(bmpfile) < 0) {
00320                     perror(argv[i]);
00321                     exitvalue = 1;
00322                 }
00323             } else {
00324                 perror(argv[i]);
00325                 exitvalue = 1;
00326             }
00327             if (i < argc - 1) {
00328                 /* more files follow -- separate them */
00329                 printf("\n");
00330             }
00331         }
00332     } else {
00333         /* No files specified -- read from standard input */
00334         if (show_wbmp_from_file("stdin", stdin)) {
00335             exitvalue = 1;
00336         }
00337     }
00338 
00339     return exitvalue;
00340 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.