seewbmp.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:7k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /* seebmp -- simple viewer for WBMP images (image/vnd.wap.wbmp) */
  2. /*
  3.  * 
  4.  * Copyright (c) Richard Braakman <dark@xs4all.nl>
  5.  * All rights reserved.
  6.  * 
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 
  16.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26.  * SUCH DAMAGE.
  27.  * 
  28.  */
  29. #include <stdio.h>
  30. #include <stddef.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. /* The spec includes a multi-byte integer format.  For reasons of simplicity, we
  34.  * only handle integers that end up fitting in 31 bits.  This limits picture
  35.  * sizes to about 2 billion pixels width or height, which I think we can live
  36.  * with. */
  37. /* The function returns -1 in case of an error. */
  38. static long get_mbi(FILE *infile) {
  39. int c;
  40. long result = 0;
  41. do {
  42. c = getc(infile);
  43. if (c < 0) return -1;
  44. result = (result << 7) | (c & 0x7f);
  45. } while (c & 0x80);
  46. return result;
  47. }
  48. /* This function is like get_mbi, but it ignores the value of the result.
  49.  * So it's not limited to 31 bits, and it ends up skipping all bytes that
  50.  * have their high bit set. */
  51. /* The function returns 0 for success, or -1 in case of an error. */
  52. static int skip_mbi(FILE *infile) {
  53. int c;
  54. do {
  55. c = getc(infile);
  56. if (c < 0) return -1;
  57. } while (c & 0x80);
  58. return 0;
  59. }
  60. static int show_image_from_file(char *bmpname, FILE *bmpfile,
  61. long width, long height) {
  62. long w, h;
  63. for (h = 0; h < height; h++) {
  64. /* w is incremented in its inner loop */
  65. for (w = 0; w < width; ) {
  66. int c;
  67. unsigned int bit;
  68. c = getc(bmpfile);
  69. if (c < 0) {
  70. perror(bmpname);
  71. return -1;
  72. }
  73. for (bit = 0x80; bit > 0 && w < width; bit >>= 1, w++) {
  74. putc((c & bit) ? '*' : ' ', stdout);
  75. }
  76. }
  77. putc('n', stdout);
  78. }
  79. return 0;
  80. }
  81. /* These are global because that's easier.  In a real parser they would
  82.  * be part of an image descriptor structure */
  83. struct parm {
  84. struct parm *next;
  85. char *name;
  86. char *value;
  87. };
  88. struct parm *extparms = NULL;
  89. static void clear_extparms(void) {
  90. while (extparms) {
  91. struct parm *tmp = extparms;
  92. extparms = extparms->next;
  93. free(tmp->name);
  94. free(tmp->value);
  95. free(tmp);
  96. }
  97. }
  98. /* Record a new parameter.  The name and value will be used directly,
  99.  * not copied. */
  100. static int new_extparm(char *name, char *value) {
  101. struct parm *new;
  102. struct parm *p;
  103. /* Construct a new node */
  104. new = (struct parm *)malloc(sizeof(struct parm));
  105. if (!new)
  106. return -1;
  107. new->name = name;
  108. new->value = value;
  109. new->next = NULL;
  110. /* Add it to the end of the list. */
  111. if (!extparms) {
  112. extparms = new;
  113. } else {
  114. p = extparms;
  115. while (p->next) { 
  116. p = p->next;
  117. }
  118. p->next = new;
  119. }
  120. return 0;
  121. }
  122. static void print_extparms(FILE *outfile) {
  123. struct parm *p;
  124. for (p = extparms; p; p = p->next) {
  125. fprintf(outfile, "%s=%sn", p->name, p->value);
  126. }
  127. }
  128. static int parse_headers(FILE *bmpfile) {
  129. int c;
  130. int exttype;
  131. clear_extparms();
  132. c = getc(bmpfile);
  133. if (c < 0) return -1;
  134. if (!(c & 0x80)) {
  135. /* No extension headers follow */
  136. return 0;
  137. }
  138. exttype = (c >> 5) & 0x03;
  139. /* None of these headers do much at this time, but they
  140.  * might be meaningful with later specifications */
  141. switch (exttype) {
  142. case 0: 
  143. /* All we know of type 0 headers is that
  144.  * the high bit is a continuation bit.
  145.  * That makes them exactly like an MBI. */
  146. if (skip_mbi(bmpfile) < 0) return -1;
  147. break;
  148. case 1: case 2:
  149. /* We don't know what to do with these */
  150. return -1;
  151. case 3:
  152. /* A sequence of parameter/value combinations */
  153. do {
  154. int namelen, valuelen;
  155. char *name, *value;
  156. c = getc(bmpfile);
  157. if (c < 0) return -1;
  158. namelen = (c >> 4) & 0x07;
  159. name = malloc(namelen + 1);
  160. if (!name) return -1;
  161. if (fread(name, namelen, 1, bmpfile) < (size_t) namelen)
  162. return -1;
  163. valuelen = c & 0x0f;
  164. value = malloc(valuelen + 1);
  165. if (!value) { free(name); return -1; }
  166. if (fread(value, valuelen, 1, bmpfile) < (size_t) valuelen)
  167. return -1;
  168. new_extparm(name, value);
  169. } while (c & 0x80);
  170. break;
  171. }
  172. return 0;
  173. }
  174. /* Return 0 for success, < 0 for failure */
  175. static int show_wbmp_from_file(char *bmpname, FILE *bmpfile) {
  176. long typefield;
  177. long width, height;
  178. typefield = get_mbi(bmpfile);
  179. if (typefield < 0) {
  180. perror(bmpname);
  181. return -1;
  182. }
  183. if (parse_headers(bmpfile) < 0) {
  184. fprintf(stderr, "%s: format error in headersn", bmpname);
  185. return -1;
  186. }
  187. width = get_mbi(bmpfile);
  188. height = get_mbi(bmpfile);
  189. if (width < 0 || height < 0) {
  190. fprintf(stderr, "%s: error reading height and widthn",
  191. bmpname);
  192. return -1;
  193. }
  194. switch (typefield) {
  195. case 0:
  196. printf("%s, %ldx%ld B/W bitmap, no compressionn",
  197. bmpname, width, height);
  198. print_extparms(stdout);
  199. if (show_image_from_file(bmpname, bmpfile,
  200. width, height) < 0) {
  201. return -1;
  202. }
  203. break;
  204. default:
  205. fprintf(stderr, "%s: cannot handle level %ld wbmpn",
  206. bmpname, typefield);
  207. return -1;
  208. }
  209. return 0;
  210. }
  211. int main(int argc, char *argv[]) {
  212. int i;
  213. /* 1 means an I/O error.  No other error values are used yet. */
  214. int exitvalue = 0;
  215. if (argc > 1) {
  216. for (i = 1; i < argc; i++) {
  217. FILE *bmpfile;
  218. bmpfile = fopen(argv[i], "r");
  219. if (bmpfile) {
  220. if (show_wbmp_from_file(argv[i], bmpfile) < 0) {
  221. /* We've already reported the error */
  222. exitvalue = 1;
  223. }
  224. if (fclose(bmpfile) < 0) {
  225. perror(argv[i]);
  226. exitvalue = 1;
  227. }
  228. } else {
  229. perror(argv[i]);
  230. exitvalue = 1;
  231. }
  232. if (i < argc - 1) {
  233. /* more files follow -- separate them */
  234. printf("n");
  235. }
  236. }
  237. } else {
  238. /* No files specified -- read from standard input */
  239. if (show_wbmp_from_file("stdin", stdin)) {
  240. exitvalue = 1;
  241. }
  242. }
  243. return exitvalue;
  244. }