PageRenderTime 26ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/jni/LibVNCServer-0.9.9/test/bmp.c

https://bitbucket.org/felixlong/android-rdp
C | 389 lines | 325 code | 50 blank | 14 comment | 81 complexity | 79e46d3c1d8c2918b0eec87629f5fe44 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0, GPL-2.0
  1. /* Copyright (C)2004 Landmark Graphics Corporation
  2. * Copyright (C)2005 Sun Microsystems, Inc.
  3. * Copyright (C)2010, 2012 D. R. Commander
  4. *
  5. * This library is free software and may be redistributed and/or modified under
  6. * the terms of the wxWindows Library License, Version 3.1 or (at your option)
  7. * any later version. The full license is in the LICENSE.txt file included
  8. * with this distribution.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * wxWindows Library License for more details.
  14. */
  15. #include <fcntl.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <errno.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #ifdef _WIN32
  23. #include <io.h>
  24. #else
  25. #include <unistd.h>
  26. #endif
  27. #include "./tjutil.h"
  28. #include "./bmp.h"
  29. #define byteswap(i) ( \
  30. (((i) & 0xff000000) >> 24) | \
  31. (((i) & 0x00ff0000) >> 8) | \
  32. (((i) & 0x0000ff00) << 8) | \
  33. (((i) & 0x000000ff) << 24) )
  34. #define byteswap16(i) ( \
  35. (((i) & 0xff00) >> 8) | \
  36. (((i) & 0x00ff) << 8) )
  37. static __inline int littleendian(void)
  38. {
  39. unsigned int value=1;
  40. unsigned char *ptr=(unsigned char *)(&value);
  41. if(ptr[0]==1 && ptr[3]==0) return 1;
  42. else return 0;
  43. }
  44. #ifndef BI_BITFIELDS
  45. #define BI_BITFIELDS 3L
  46. #endif
  47. #ifndef BI_RGB
  48. #define BI_RGB 0L
  49. #endif
  50. #define BMPHDRSIZE 54
  51. typedef struct _bmphdr
  52. {
  53. unsigned short bfType;
  54. unsigned int bfSize;
  55. unsigned short bfReserved1, bfReserved2;
  56. unsigned int bfOffBits;
  57. unsigned int biSize;
  58. int biWidth, biHeight;
  59. unsigned short biPlanes, biBitCount;
  60. unsigned int biCompression, biSizeImage;
  61. int biXPelsPerMeter, biYPelsPerMeter;
  62. unsigned int biClrUsed, biClrImportant;
  63. } bmphdr;
  64. static const char *__bmperr="No error";
  65. static const int ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
  66. static const int roffset[BMPPIXELFORMATS]={0, 0, 2, 2, 3, 1};
  67. static const int goffset[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2};
  68. static const int boffset[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
  69. #define _throw(m) {__bmperr=m; retcode=-1; goto finally;}
  70. #define _unix(f) {if((f)==-1) _throw(strerror(errno));}
  71. #define _catch(f) {if((f)==-1) {retcode=-1; goto finally;}}
  72. #define readme(fd, addr, size) \
  73. if((bytesread=read(fd, addr, (size)))==-1) _throw(strerror(errno)); \
  74. if(bytesread!=(size)) _throw("Read error");
  75. void pixelconvert(unsigned char *srcbuf, enum BMPPIXELFORMAT srcformat,
  76. int srcpitch, unsigned char *dstbuf, enum BMPPIXELFORMAT dstformat, int dstpitch,
  77. int w, int h, int flip)
  78. {
  79. unsigned char *srcptr, *srcptr0, *dstptr, *dstptr0;
  80. int i, j;
  81. srcptr=flip? &srcbuf[srcpitch*(h-1)]:srcbuf;
  82. for(j=0, dstptr=dstbuf; j<h; j++,
  83. srcptr+=flip? -srcpitch:srcpitch, dstptr+=dstpitch)
  84. {
  85. for(i=0, srcptr0=srcptr, dstptr0=dstptr; i<w; i++,
  86. srcptr0+=ps[srcformat], dstptr0+=ps[dstformat])
  87. {
  88. dstptr0[roffset[dstformat]]=srcptr0[roffset[srcformat]];
  89. dstptr0[goffset[dstformat]]=srcptr0[goffset[srcformat]];
  90. dstptr0[boffset[dstformat]]=srcptr0[boffset[srcformat]];
  91. }
  92. }
  93. }
  94. int loadppm(int *fd, unsigned char **buf, int *w, int *h,
  95. enum BMPPIXELFORMAT f, int align, int dstbottomup, int ascii)
  96. {
  97. FILE *fs=NULL; int retcode=0, scalefactor, dstpitch;
  98. unsigned char *tempbuf=NULL; char temps[255], temps2[255];
  99. int numread=0, totalread=0, pixel[3], i, j;
  100. if((fs=fdopen(*fd, "r"))==NULL) _throw(strerror(errno));
  101. do
  102. {
  103. if(!fgets(temps, 255, fs)) _throw("Read error");
  104. if(strlen(temps)==0 || temps[0]=='\n') continue;
  105. if(sscanf(temps, "%s", temps2)==1 && temps2[1]=='#') continue;
  106. switch(totalread)
  107. {
  108. case 0:
  109. if((numread=sscanf(temps, "%d %d %d", w, h, &scalefactor))==EOF)
  110. _throw("Read error");
  111. break;
  112. case 1:
  113. if((numread=sscanf(temps, "%d %d", h, &scalefactor))==EOF)
  114. _throw("Read error");
  115. break;
  116. case 2:
  117. if((numread=sscanf(temps, "%d", &scalefactor))==EOF)
  118. _throw("Read error");
  119. break;
  120. }
  121. totalread+=numread;
  122. } while(totalread<3);
  123. if((*w)<1 || (*h)<1 || scalefactor<1) _throw("Corrupt PPM header");
  124. dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));
  125. if((*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
  126. _throw("Memory allocation error");
  127. if(ascii)
  128. {
  129. for(j=0; j<*h; j++)
  130. {
  131. for(i=0; i<*w; i++)
  132. {
  133. if(fscanf(fs, "%d%d%d", &pixel[0], &pixel[1], &pixel[2])!=3)
  134. _throw("Read error");
  135. (*buf)[j*dstpitch+i*ps[f]+roffset[f]]=(unsigned char)(pixel[0]*255/scalefactor);
  136. (*buf)[j*dstpitch+i*ps[f]+goffset[f]]=(unsigned char)(pixel[1]*255/scalefactor);
  137. (*buf)[j*dstpitch+i*ps[f]+boffset[f]]=(unsigned char)(pixel[2]*255/scalefactor);
  138. }
  139. }
  140. }
  141. else
  142. {
  143. if(scalefactor!=255)
  144. _throw("Binary PPMs must have 8-bit components");
  145. if((tempbuf=(unsigned char *)malloc((*w)*(*h)*3))==NULL)
  146. _throw("Memory allocation error");
  147. if(fread(tempbuf, (*w)*(*h)*3, 1, fs)!=1) _throw("Read error");
  148. pixelconvert(tempbuf, BMP_RGB, (*w)*3, *buf, f, dstpitch, *w, *h, dstbottomup);
  149. }
  150. finally:
  151. if(fs) {fclose(fs); *fd=-1;}
  152. if(tempbuf) free(tempbuf);
  153. return retcode;
  154. }
  155. int loadbmp(char *filename, unsigned char **buf, int *w, int *h,
  156. enum BMPPIXELFORMAT f, int align, int dstbottomup)
  157. {
  158. int fd=-1, bytesread, srcpitch, srcbottomup=1, srcps, dstpitch,
  159. retcode=0;
  160. unsigned char *tempbuf=NULL;
  161. bmphdr bh; int flags=O_RDONLY;
  162. dstbottomup=dstbottomup? 1:0;
  163. #ifdef _WIN32
  164. flags|=O_BINARY;
  165. #endif
  166. if(!filename || !buf || !w || !h || f<0 || f>BMPPIXELFORMATS-1 || align<1)
  167. _throw("invalid argument to loadbmp()");
  168. if((align&(align-1))!=0)
  169. _throw("Alignment must be a power of 2");
  170. _unix(fd=open(filename, flags));
  171. readme(fd, &bh.bfType, sizeof(unsigned short));
  172. if(!littleendian()) bh.bfType=byteswap16(bh.bfType);
  173. if(bh.bfType==0x3650)
  174. {
  175. _catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 0));
  176. goto finally;
  177. }
  178. if(bh.bfType==0x3350)
  179. {
  180. _catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 1));
  181. goto finally;
  182. }
  183. readme(fd, &bh.bfSize, sizeof(unsigned int));
  184. readme(fd, &bh.bfReserved1, sizeof(unsigned short));
  185. readme(fd, &bh.bfReserved2, sizeof(unsigned short));
  186. readme(fd, &bh.bfOffBits, sizeof(unsigned int));
  187. readme(fd, &bh.biSize, sizeof(unsigned int));
  188. readme(fd, &bh.biWidth, sizeof(int));
  189. readme(fd, &bh.biHeight, sizeof(int));
  190. readme(fd, &bh.biPlanes, sizeof(unsigned short));
  191. readme(fd, &bh.biBitCount, sizeof(unsigned short));
  192. readme(fd, &bh.biCompression, sizeof(unsigned int));
  193. readme(fd, &bh.biSizeImage, sizeof(unsigned int));
  194. readme(fd, &bh.biXPelsPerMeter, sizeof(int));
  195. readme(fd, &bh.biYPelsPerMeter, sizeof(int));
  196. readme(fd, &bh.biClrUsed, sizeof(unsigned int));
  197. readme(fd, &bh.biClrImportant, sizeof(unsigned int));
  198. if(!littleendian())
  199. {
  200. bh.bfSize=byteswap(bh.bfSize);
  201. bh.bfOffBits=byteswap(bh.bfOffBits);
  202. bh.biSize=byteswap(bh.biSize);
  203. bh.biWidth=byteswap(bh.biWidth);
  204. bh.biHeight=byteswap(bh.biHeight);
  205. bh.biPlanes=byteswap16(bh.biPlanes);
  206. bh.biBitCount=byteswap16(bh.biBitCount);
  207. bh.biCompression=byteswap(bh.biCompression);
  208. bh.biSizeImage=byteswap(bh.biSizeImage);
  209. bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
  210. bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
  211. bh.biClrUsed=byteswap(bh.biClrUsed);
  212. bh.biClrImportant=byteswap(bh.biClrImportant);
  213. }
  214. if(bh.bfType!=0x4d42 || bh.bfOffBits<BMPHDRSIZE
  215. || bh.biWidth<1 || bh.biHeight==0)
  216. _throw("Corrupt bitmap header");
  217. if((bh.biBitCount!=24 && bh.biBitCount!=32) || bh.biCompression!=BI_RGB)
  218. _throw("Only uncompessed RGB bitmaps are supported");
  219. *w=bh.biWidth; *h=bh.biHeight; srcps=bh.biBitCount/8;
  220. if(*h<0) {*h=-(*h); srcbottomup=0;}
  221. srcpitch=(((*w)*srcps)+3)&(~3);
  222. dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));
  223. if(srcpitch*(*h)+bh.bfOffBits!=bh.bfSize) _throw("Corrupt bitmap header");
  224. if((tempbuf=(unsigned char *)malloc(srcpitch*(*h)))==NULL
  225. || (*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
  226. _throw("Memory allocation error");
  227. if(lseek(fd, (long)bh.bfOffBits, SEEK_SET)!=(long)bh.bfOffBits)
  228. _throw(strerror(errno));
  229. _unix(bytesread=read(fd, tempbuf, srcpitch*(*h)));
  230. if(bytesread!=srcpitch*(*h)) _throw("Read error");
  231. pixelconvert(tempbuf, BMP_BGR, srcpitch, *buf, f, dstpitch, *w, *h,
  232. srcbottomup!=dstbottomup);
  233. finally:
  234. if(tempbuf) free(tempbuf);
  235. if(fd!=-1) close(fd);
  236. return retcode;
  237. }
  238. #define writeme(fd, addr, size) \
  239. if((byteswritten=write(fd, addr, (size)))==-1) _throw(strerror(errno)); \
  240. if(byteswritten!=(size)) _throw("Write error");
  241. int saveppm(char *filename, unsigned char *buf, int w, int h,
  242. enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
  243. {
  244. FILE *fs=NULL; int retcode=0;
  245. unsigned char *tempbuf=NULL;
  246. if((fs=fopen(filename, "wb"))==NULL) _throw(strerror(errno));
  247. if(fprintf(fs, "P6\n")<1) _throw("Write error");
  248. if(fprintf(fs, "%d %d\n", w, h)<1) _throw("Write error");
  249. if(fprintf(fs, "255\n")<1) _throw("Write error");
  250. if((tempbuf=(unsigned char *)malloc(w*h*3))==NULL)
  251. _throw("Memory allocation error");
  252. pixelconvert(buf, f, srcpitch, tempbuf, BMP_RGB, w*3, w, h,
  253. srcbottomup);
  254. if((fwrite(tempbuf, w*h*3, 1, fs))!=1) _throw("Write error");
  255. finally:
  256. if(tempbuf) free(tempbuf);
  257. if(fs) fclose(fs);
  258. return retcode;
  259. }
  260. int savebmp(char *filename, unsigned char *buf, int w, int h,
  261. enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
  262. {
  263. int fd=-1, byteswritten, dstpitch, retcode=0;
  264. int flags=O_RDWR|O_CREAT|O_TRUNC;
  265. unsigned char *tempbuf=NULL; char *temp;
  266. bmphdr bh; int mode;
  267. #ifdef _WIN32
  268. flags|=O_BINARY; mode=_S_IREAD|_S_IWRITE;
  269. #else
  270. mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
  271. #endif
  272. if(!filename || !buf || w<1 || h<1 || f<0 || f>BMPPIXELFORMATS-1 || srcpitch<0)
  273. _throw("bad argument to savebmp()");
  274. if(srcpitch==0) srcpitch=w*ps[f];
  275. if((temp=strrchr(filename, '.'))!=NULL)
  276. {
  277. if(!strcasecmp(temp, ".ppm"))
  278. return saveppm(filename, buf, w, h, f, srcpitch, srcbottomup);
  279. }
  280. _unix(fd=open(filename, flags, mode));
  281. dstpitch=((w*3)+3)&(~3);
  282. bh.bfType=0x4d42;
  283. bh.bfSize=BMPHDRSIZE+dstpitch*h;
  284. bh.bfReserved1=0; bh.bfReserved2=0;
  285. bh.bfOffBits=BMPHDRSIZE;
  286. bh.biSize=40;
  287. bh.biWidth=w; bh.biHeight=h;
  288. bh.biPlanes=0; bh.biBitCount=24;
  289. bh.biCompression=BI_RGB; bh.biSizeImage=0;
  290. bh.biXPelsPerMeter=0; bh.biYPelsPerMeter=0;
  291. bh.biClrUsed=0; bh.biClrImportant=0;
  292. if(!littleendian())
  293. {
  294. bh.bfType=byteswap16(bh.bfType);
  295. bh.bfSize=byteswap(bh.bfSize);
  296. bh.bfOffBits=byteswap(bh.bfOffBits);
  297. bh.biSize=byteswap(bh.biSize);
  298. bh.biWidth=byteswap(bh.biWidth);
  299. bh.biHeight=byteswap(bh.biHeight);
  300. bh.biPlanes=byteswap16(bh.biPlanes);
  301. bh.biBitCount=byteswap16(bh.biBitCount);
  302. bh.biCompression=byteswap(bh.biCompression);
  303. bh.biSizeImage=byteswap(bh.biSizeImage);
  304. bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
  305. bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
  306. bh.biClrUsed=byteswap(bh.biClrUsed);
  307. bh.biClrImportant=byteswap(bh.biClrImportant);
  308. }
  309. writeme(fd, &bh.bfType, sizeof(unsigned short));
  310. writeme(fd, &bh.bfSize, sizeof(unsigned int));
  311. writeme(fd, &bh.bfReserved1, sizeof(unsigned short));
  312. writeme(fd, &bh.bfReserved2, sizeof(unsigned short));
  313. writeme(fd, &bh.bfOffBits, sizeof(unsigned int));
  314. writeme(fd, &bh.biSize, sizeof(unsigned int));
  315. writeme(fd, &bh.biWidth, sizeof(int));
  316. writeme(fd, &bh.biHeight, sizeof(int));
  317. writeme(fd, &bh.biPlanes, sizeof(unsigned short));
  318. writeme(fd, &bh.biBitCount, sizeof(unsigned short));
  319. writeme(fd, &bh.biCompression, sizeof(unsigned int));
  320. writeme(fd, &bh.biSizeImage, sizeof(unsigned int));
  321. writeme(fd, &bh.biXPelsPerMeter, sizeof(int));
  322. writeme(fd, &bh.biYPelsPerMeter, sizeof(int));
  323. writeme(fd, &bh.biClrUsed, sizeof(unsigned int));
  324. writeme(fd, &bh.biClrImportant, sizeof(unsigned int));
  325. if((tempbuf=(unsigned char *)malloc(dstpitch*h))==NULL)
  326. _throw("Memory allocation error");
  327. pixelconvert(buf, f, srcpitch, tempbuf, BMP_BGR, dstpitch, w, h,
  328. !srcbottomup);
  329. if((byteswritten=write(fd, tempbuf, dstpitch*h))!=dstpitch*h)
  330. _throw(strerror(errno));
  331. finally:
  332. if(tempbuf) free(tempbuf);
  333. if(fd!=-1) close(fd);
  334. return retcode;
  335. }
  336. const char *bmpgeterr(void)
  337. {
  338. return __bmperr;
  339. }