fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <math.h>
  5. #include <string.h>
  6.  
  7. /* #define DEBUG */
  8. #if defined(DEBUG)
  9. #include "xmalloc.h"
  10. #else
  11. #define xmalloc(x, y) malloc(x)
  12. #define xfree(x, y) free(x)
  13. #define xrealloc(x, y, z) realloc(x, y)
  14. #define xmallocdump()
  15. #endif
  16. /* for xmalloc.c */
  17. #define IDRGB 1001
  18. #define IDPALETTE 1002
  19. #define IDBMP 1003
  20.  
  21. #define NBYTE 1
  22. #define NWORD 2
  23. #define NDWORD 4
  24.  
  25. int LittleEndianRead(unsigned long *data, int size, FILE *fp) {
  26. unsigned char lsb;
  27. unsigned long msb;
  28. if (size == 0) {
  29. *data = 0;
  30. return 1;
  31. }
  32. if (fread(&lsb, 1, 1, fp) != 1)
  33. return -1;
  34. if (LittleEndianRead(&msb, size - 1, fp) < 0)
  35. return -1;
  36. *data = (unsigned long)lsb | (msb << 8);
  37. return 1;
  38. }
  39.  
  40. typedef struct {
  41. unsigned long bfType1;
  42. unsigned long bfType2;
  43. unsigned long bfSize;
  44. unsigned long bfReserved1;
  45. unsigned long bfReserved2;
  46. unsigned long bfOffBits;
  47. } BitmapFileHeader;
  48.  
  49. int bmHeaderCheck(FILE *fp, BitmapFileHeader *bh) {
  50. assert(sizeof(unsigned long) >= 4);
  51. if (LittleEndianRead(&(bh->bfType1), NBYTE, fp) < 0)
  52. goto error_NotRead;
  53. if (LittleEndianRead(&(bh->bfType2), NBYTE, fp) < 0)
  54. goto error_NotRead;
  55. if (LittleEndianRead(&bh->bfSize, NDWORD, fp) < 0)
  56. goto error_NotRead;
  57. if (LittleEndianRead(&bh->bfReserved1, NWORD, fp) < 0)
  58. goto error_NotRead;
  59. if (LittleEndianRead(&bh->bfReserved2, NWORD, fp) < 0)
  60. goto error_NotRead;
  61. if (LittleEndianRead(&bh->bfOffBits, NDWORD, fp) < 0)
  62. goto error_NotRead;
  63. #if 0
  64. printf("read:bfType1: %c\n", (char)bh->bfType1);
  65. printf("read:bfType2: %c\n", (char)bh->bfType2);
  66. printf("read:bfSize: %lu\n", bh->bfSize);
  67. printf("read:bfReserved1: %lu\n", bh->bfReserved1);
  68. printf("read:bfReserved2: %lu\n", bh->bfReserved2);
  69. printf("read:bfOffBits: %lu\n", bh->bfOffBits);
  70. putchar('\n');
  71. #endif
  72. if (bh->bfType1 != 'B' || bh->bfType2 != 'M')
  73. goto error_NotBitmap;
  74. if (bh->bfReserved1 != 0 || bh->bfReserved2 != 0)
  75. goto error_NotBitmap;
  76. return 1;
  77.  
  78. error_NotBitmap:
  79. fprintf(stderr, "cannot find bmp header\n");
  80. return 0;
  81. error_NotRead:
  82. fprintf(stderr, "cannot read bmp header\n");
  83. return 0;
  84. }
  85.  
  86. typedef struct {
  87. unsigned long biSize;
  88. long biWidth;
  89. long biHeight;
  90. unsigned long biPlanes;
  91. unsigned long biBitCount;
  92. unsigned long biCompression;
  93. unsigned long biSizeImage;
  94. long biXPixPerMeter;
  95. long biYPixPerMeter;
  96. unsigned long biClrUsed;
  97. unsigned long biClrImportant;
  98. } BitmapInfoHeader;
  99.  
  100. int bmInfoHeaderCheck(FILE *fp, BitmapInfoHeader *bi) {
  101. assert(sizeof(unsigned long) >= 4);
  102. assert(sizeof(long) >= 4);
  103. if (LittleEndianRead(&bi->biSize, NDWORD, fp) < 0)
  104. goto error_NotRead;
  105. if (bi->biSize == 12) {
  106. /* not supported */
  107. } else if (bi->biSize == 40) {
  108. if (LittleEndianRead((unsigned long *)&bi->biWidth, NDWORD, fp) < 0)
  109. goto error_NotRead;
  110. if (LittleEndianRead((unsigned long *)&bi->biHeight, NDWORD, fp) < 0)
  111. goto error_NotRead;
  112. if (LittleEndianRead(&bi->biPlanes, NWORD, fp) < 0)
  113. goto error_NotRead;
  114. if (LittleEndianRead(&bi->biBitCount, NWORD, fp) < 0)
  115. goto error_NotRead;
  116. if (LittleEndianRead(&bi->biCompression, NDWORD, fp) < 0)
  117. goto error_NotRead;
  118. if (LittleEndianRead(&bi->biSizeImage, NDWORD, fp) < 0)
  119. goto error_NotRead;
  120. if (LittleEndianRead((unsigned long *)&bi->biXPixPerMeter, NDWORD, fp) < 0)
  121. goto error_NotRead;
  122. if (LittleEndianRead((unsigned long *)&bi->biYPixPerMeter, NDWORD, fp) < 0)
  123. goto error_NotRead;
  124. if (LittleEndianRead(&bi->biClrUsed, NDWORD, fp) < 0)
  125. goto error_NotRead;
  126. if (LittleEndianRead(&bi->biClrImportant, NDWORD, fp) < 0)
  127. goto error_NotRead;
  128. } else {
  129. goto error_NotSupported1;
  130. }
  131. #if 0
  132. printf("read:biSize: %lu\n", bi->biSize);
  133. printf("read:biWidth: %ld\n", bi->biWidth);
  134. printf("read:biHeight: %ld\n", bi->biHeight);
  135. printf("read:biPlanes: %lu\n", bi->biPlanes);
  136. printf("read:biBitcount: %lu\n", bi->biBitCount);
  137. if (bi->biSize == 40) {
  138. printf("read:biCompression: %lu\n", bi->biCompression);
  139. printf("read:biSizeImage: %lu\n", bi->biSizeImage);
  140. printf("read:biXPixPerMeter %ld\n", bi->biXPixPerMeter);
  141. printf("read:biYPixPerMeter %ld\n", bi->biYPixPerMeter);
  142. printf("read:biClrUsed: %lu\n", bi->biClrUsed);
  143. printf("read:biClrImporant: %lu\n", bi->biClrImportant);
  144. }
  145. #endif
  146. if (bi->biSize != 40)
  147. goto error_NotSupported1;
  148. if (bi->biPlanes != 1)
  149. goto error_NotSupported2;
  150. if (bi->biBitCount != 24 && bi->biBitCount != 8 && bi->biBitCount != 4)
  151. goto error_NotSupported3;
  152. if (bi->biCompression != 0)
  153. goto error_NotSupported4;
  154. return 1;
  155.  
  156. error_NotSupported1:
  157. fprintf(stderr, "info header size: %lu, this format is not supported\n", bi->biSize);
  158. return 0;
  159. error_NotSupported2:
  160. fprintf(stderr, "biPlanes: %lu, this format is not supported\n", bi->biPlanes);
  161. return 0;
  162. error_NotSupported3:
  163. fprintf(stderr, "biBitCount: %lu, this format is not supported\n", bi->biBitCount);
  164. return 0;
  165. error_NotSupported4:
  166. fprintf(stderr, "biCompression: %lu, this format is not supported\n", bi->biCompression);
  167. return 0;
  168. error_NotRead:
  169. #if 0
  170. printf("read:biSize: %lu\n", bi->biSize);
  171. printf("read:biWidth: %ld\n", bi->biWidth);
  172. printf("read:biHeight: %ld\n", bi->biHeight);
  173. printf("read:biPlanes: %lu\n", bi->biPlanes);
  174. printf("read:biBitcount: %lu\n", bi->biBitCount);
  175. if (bi->biSize == 40) {
  176. printf("read:biCompression: %lu\n", bi->biCompression);
  177. printf("read:biSizeImage: %lu\n", bi->biSizeImage);
  178. printf("read:biXPixPerMeter %ld\n", bi->biXPixPerMeter);
  179. printf("read:biYPixPerMeter %ld\n", bi->biYPixPerMeter);
  180. printf("read:biClrUsed: %lu\n", bi->biClrUsed);
  181. printf("read:biClrImporant: %lu\n", bi->biClrImportant);
  182. }
  183. #endif
  184. fprintf(stderr, "cannot read bmp info header\n");
  185. return 0;
  186. }
  187.  
  188. int isFtellGood(FILE *fp, unsigned long pos) {
  189. return (unsigned long)ftell(fp) == pos;
  190. }
  191.  
  192. long iabs(long n) {
  193. return (n > 0) ? n : -n;
  194. }
  195.  
  196.  
  197. void task_read24(FILE *fp, BitmapFileHeader *bheader, BitmapInfoHeader *binfo,
  198. unsigned char **dataR, unsigned char **dataG,
  199. unsigned char **dataB)
  200. {
  201. long x, y, n;
  202. unsigned char dummy;
  203. int c;
  204. if (!isFtellGood(fp, bheader->bfOffBits)) {
  205. fprintf(stderr, "Header or Image Data is corrupted.\n");
  206. return;
  207. }
  208. *dataR = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  209. *dataG = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  210. *dataB = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  211. if (*dataR == NULL || *dataG == NULL || *dataB == NULL) {
  212. fprintf(stderr, "cannot alloc. enough memory.\n");
  213. return;
  214. }
  215. for (y = 0; y < iabs(binfo->biHeight); y++) {
  216. c = 0;
  217. for (x = 0; x < iabs(binfo->biWidth); x++) {
  218. fread((*dataB + y * iabs(binfo->biWidth) + x), 1, 1, fp);
  219. fread((*dataG + y * iabs(binfo->biWidth) + x), 1, 1, fp);
  220. fread((*dataR + y * iabs(binfo->biWidth) + x), 1, 1, fp);
  221. c += 3;
  222. }
  223. while (c % 4 != 0) {
  224. fread(&dummy, 1, 1, fp);
  225. c++;
  226. }
  227. }
  228. n = iabs(binfo->biWidth) * 3;
  229. if (n % 4 > 0)
  230. n += 4 - (n % 4);
  231. binfo->biSizeImage = n * iabs(binfo->biHeight);
  232. bheader->bfSize = binfo->biSizeImage + binfo->biSize + 14;
  233. }
  234.  
  235. void task_read_palette(FILE *fp, BitmapFileHeader *bh, BitmapInfoHeader *bi,
  236. unsigned char **dataPalette)
  237. {
  238. int i, max;
  239. unsigned char dummy;
  240. if ((max = bi->biClrUsed) == 0) {
  241. switch (bi->biBitCount) {
  242. case 4:
  243. max = 16;
  244. break;
  245. case 8:
  246. max = 256;
  247. break;
  248. }
  249. }
  250. *dataPalette = xmalloc(sizeof(char) * 3 * max, IDPALETTE);
  251. if (*dataPalette == NULL) {
  252. fprintf(stderr, "cannot alloc. enough memory.\n");
  253. return;
  254. }
  255. for (i = 0; i < max; i++) {
  256. fread((*dataPalette + 3 * i + 0), 1, 1, fp);
  257. fread((*dataPalette + 3 * i + 1), 1, 1, fp);
  258. fread((*dataPalette + 3 * i + 2), 1, 1, fp);
  259. fread(&dummy, 1, 1, fp);
  260. }
  261. }
  262.  
  263. void task_read8(FILE *fp, BitmapFileHeader *bheader, BitmapInfoHeader *binfo,
  264. unsigned char **dataR, unsigned char **dataG,
  265. unsigned char **dataB, unsigned char *dataPalette)
  266. {
  267. long x, y, n;
  268. unsigned char data;
  269. int c;
  270.  
  271. if (!isFtellGood(fp, bheader->bfOffBits)) {
  272. fprintf(stderr, "Header or Image Data is corrupted.\n");
  273. return;
  274. }
  275. *dataR = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  276. *dataG = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  277. *dataB = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  278. if (*dataR == NULL || *dataG == NULL || *dataB == NULL) {
  279. fprintf(stderr, "cannot alloc. enough memory.\n");
  280. return;
  281. }
  282. for (y = 0; y < iabs(binfo->biHeight); y++) {
  283. c = 0;
  284. for (x = 0; x < iabs(binfo->biWidth); x++) {
  285. fread(&data, 1, 1, fp);
  286. *(*dataB + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 0];
  287. *(*dataG + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 1];
  288. *(*dataR + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 2];
  289. c++;
  290. }
  291. while (c % 4 != 0) {
  292. fread(&data, 1, 1, fp);
  293. c++;
  294. }
  295. }
  296. n = iabs(binfo->biWidth) * 3;
  297. if (n % 4 > 0)
  298. n += 4 - (n % 4);
  299. binfo->biSizeImage = n * iabs(binfo->biHeight);
  300. bheader->bfSize = binfo->biSizeImage + binfo->biSize + 14;
  301. bheader->bfOffBits = 54;
  302. binfo->biBitCount = 24;
  303. binfo->biClrUsed = 0;
  304. binfo->biClrImportant = 0;
  305. }
  306.  
  307. void task_read4(FILE *fp, BitmapFileHeader *bheader, BitmapInfoHeader *binfo,
  308. unsigned char **dataR, unsigned char **dataG,
  309. unsigned char **dataB, unsigned char *dataPalette)
  310. {
  311. long x, y, n;
  312. unsigned char data, rdata;
  313. int c;
  314. int bitHighLow;
  315.  
  316. if (!isFtellGood(fp, bheader->bfOffBits)) {
  317. fprintf(stderr, "Header or Image Data is corrupted.\n");
  318. return;
  319. }
  320. *dataR = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  321. *dataG = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  322. *dataB = xmalloc(sizeof(char) * iabs(binfo->biWidth) * iabs(binfo->biHeight), IDRGB);
  323. if (*dataR == NULL || *dataG == NULL || *dataB == NULL) {
  324. fprintf(stderr, "cannot alloc. enough memory.\n");
  325. return;
  326. }
  327. bitHighLow = 1;
  328. for (y = 0; y < iabs(binfo->biHeight); y++) {
  329. c = 0;
  330. for (x = 0; x < iabs(binfo->biWidth); x++) {
  331. if (bitHighLow) {
  332. fread(&rdata, 1, 1, fp);
  333. data = rdata & 0xf0;
  334. data >>= 4;
  335. bitHighLow = 0;
  336. } else {
  337. data = rdata & 0x0f;
  338. bitHighLow = 1;
  339. }
  340. *(*dataB + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 0];
  341. *(*dataG + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 1];
  342. *(*dataR + y * iabs(binfo->biWidth) + x) = dataPalette[3 * data + 2];
  343. c++;
  344. }
  345. while (c % 4 != 0) {
  346. fread(&data, 1, 1, fp);
  347. c++;
  348. }
  349. }
  350. n = iabs(binfo->biWidth) * 3;
  351. if (n % 4 > 0)
  352. n += 4 - (n % 4);
  353. binfo->biSizeImage = n * iabs(binfo->biHeight);
  354. bheader->bfSize = binfo->biSizeImage + binfo->biSize + 14;
  355. bheader->bfOffBits = 54;
  356. binfo->biBitCount = 24;
  357. binfo->biClrUsed = 0;
  358. binfo->biClrImportant = 0;
  359. }
  360.  
  361. void LittleEndianWrite(unsigned long *data, int size, FILE *fp) {
  362. unsigned char lsb;
  363. unsigned long msb;
  364. if (size == 0)
  365. return;
  366. lsb = (unsigned char)(*data & 0xff);
  367. fwrite(&lsb, 1, 1, fp);
  368. msb = *data >> 8;
  369. LittleEndianWrite(&msb, size - 1, fp);
  370. }
  371.  
  372. void task_write_header(FILE *fp, BitmapFileHeader *bh) {
  373. assert(sizeof(unsigned long) >= 4);
  374. assert(sizeof(long) >= 4);
  375. LittleEndianWrite(&(bh->bfType1), NBYTE, fp);
  376. LittleEndianWrite(&(bh->bfType2), NBYTE, fp);
  377. LittleEndianWrite(&(bh->bfSize), NDWORD, fp);
  378. LittleEndianWrite(&(bh->bfReserved1), NWORD, fp);
  379. LittleEndianWrite(&(bh->bfReserved2), NWORD, fp);
  380. LittleEndianWrite(&(bh->bfOffBits), NDWORD, fp);
  381. #if 0
  382. printf("write:bfType1: %c\n", (char)bh->bfType1);
  383. printf("write:bfType2: %c\n", (char)bh->bfType2);
  384. printf("write:bfSize: %lu\n", bh->bfSize);
  385. printf("write:bfReserved1: %lu\n", bh->bfReserved1);
  386. printf("write:bfReserved2: %lu\n", bh->bfReserved2);
  387. printf("write:bfOffBits: %lu\n", bh->bfOffBits);
  388. #endif
  389. }
  390.  
  391. void task_write_info(FILE *fp, BitmapInfoHeader *bi) {
  392. assert(sizeof(unsigned short) == 2);
  393. assert(sizeof(unsigned long) == 4);
  394. assert(sizeof(long) == 4);
  395. LittleEndianWrite(&(bi->biSize), NDWORD, fp);
  396. LittleEndianWrite((unsigned long *)&(bi->biWidth), NDWORD, fp);
  397. LittleEndianWrite((unsigned long *)&(bi->biHeight), NDWORD, fp);
  398. LittleEndianWrite(&(bi->biPlanes), NWORD, fp);
  399. LittleEndianWrite(&(bi->biBitCount), NWORD, fp);
  400. LittleEndianWrite(&(bi->biCompression), NDWORD, fp);
  401. LittleEndianWrite(&(bi->biSizeImage), NDWORD, fp);
  402. LittleEndianWrite((unsigned long *)&(bi->biXPixPerMeter), NDWORD, fp);
  403. LittleEndianWrite((unsigned long *)&(bi->biYPixPerMeter), NDWORD, fp);
  404. LittleEndianWrite(&(bi->biClrUsed), NDWORD, fp);
  405. LittleEndianWrite(&(bi->biClrImportant), NDWORD, fp);
  406. #if 0
  407. printf("write:biSize: %lu\n", bi->biSize);
  408. printf("write:biWidth: %ld\n", bi->biWidth);
  409. printf("write:biHeight: %ld\n", bi->biHeight);
  410. printf("write:biPlanes: %lu\n", bi->biPlanes);
  411. printf("write:biBitcount: %lu\n", bi->biBitCount);
  412. printf("write:biCompression: %lu\n", bi->biCompression);
  413. printf("write:biSizeImage: %lu\n", bi->biSizeImage);
  414. printf("write:biXPixPerMeter %ld\n", bi->biXPixPerMeter);
  415. printf("write:biYPixPerMeter %ld\n", bi->biYPixPerMeter);
  416. printf("write:biClrUsed: %lu\n", bi->biClrUsed);
  417. printf("write:biClrImporant: %lu\n", bi->biClrImportant);
  418. #endif
  419. }
  420.  
  421. void task_write24(FILE *fp,
  422. BitmapFileHeader *bh, BitmapInfoHeader *bi,
  423. unsigned char *dataR,
  424. unsigned char *dataG,
  425. unsigned char *dataB) {
  426. int x, y;
  427. int c;
  428. unsigned char dummy = '\0';
  429. task_write_header(fp, bh);
  430. task_write_info(fp, bi);
  431. for (y = 0; y < iabs(bi->biHeight); y++) {
  432. c = 0;
  433. for (x = 0; x < iabs(bi->biWidth); x++) {
  434. fwrite(&dataB[y * iabs(bi->biWidth) + x], 1, 1, fp);
  435. fwrite(&dataG[y * iabs(bi->biWidth) + x], 1, 1, fp);
  436. fwrite(&dataR[y * iabs(bi->biWidth) + x], 1, 1, fp);
  437. c += 3;
  438. }
  439. while (c % 4 != 0) {
  440. fwrite(&dummy, 1, 1, fp);
  441. c++;
  442. }
  443. }
  444. }
  445.  
  446. /* ------------------------------------------------------------------------- */
  447. struct BMP24 {
  448. BitmapFileHeader bh;
  449. BitmapInfoHeader bi;
  450. unsigned char *dataR;
  451. unsigned char *dataG;
  452. unsigned char *dataB;
  453. unsigned char *dataPalette;
  454. };
  455.  
  456. int BMP24_read(FILE *fp, struct BMP24 *bmp) {
  457. if (!bmHeaderCheck(fp, &(bmp->bh)))
  458. return 0;
  459. if (!bmInfoHeaderCheck(fp, &(bmp->bi)))
  460. return 0;
  461. bmp->dataR = bmp->dataG = bmp->dataB = bmp->dataPalette = NULL;
  462. if ((bmp->bi).biBitCount == 24) {
  463. task_read24(fp, &(bmp->bh), &(bmp->bi),
  464. &(bmp->dataR), &(bmp->dataG), &(bmp->dataB));
  465. } else if ((bmp->bi).biBitCount == 8) {
  466. task_read_palette(fp, &bmp->bh, &bmp->bi, &bmp->dataPalette);
  467. task_read8(fp, &bmp->bh, &bmp->bi,
  468. &bmp->dataR, &bmp->dataG, &bmp->dataB, bmp->dataPalette);
  469. xfree(bmp->dataPalette, IDPALETTE);
  470. bmp->dataPalette = NULL;
  471. } else if ((bmp->bi).biBitCount == 4) {
  472. task_read_palette(fp, &bmp->bh, &bmp->bi, &bmp->dataPalette);
  473. task_read4(fp, &bmp->bh, &bmp->bi,
  474. &bmp->dataR, &bmp->dataG, &bmp->dataB, bmp->dataPalette);
  475. xfree(bmp->dataPalette, IDPALETTE);
  476. bmp->dataPalette = NULL;
  477. }
  478. if (!(bmp->dataR && bmp->dataG && bmp->dataB)) {
  479. xfree(bmp->dataR, IDRGB);
  480. xfree(bmp->dataG, IDRGB);
  481. xfree(bmp->dataB, IDRGB);
  482. return 0;
  483. }
  484. return 1;
  485. }
  486.  
  487. void BMP24_write(FILE *fp, struct BMP24 *bmp) {
  488. task_write24(fp, &bmp->bh, &bmp->bi,
  489. bmp->dataR, bmp->dataG, bmp->dataB);
  490. }
  491.  
  492. void BMP24_release(struct BMP24 *bmp) {
  493. if (bmp->dataR) xfree(bmp->dataR, IDRGB);
  494. if (bmp->dataG) xfree(bmp->dataG, IDRGB);
  495. if (bmp->dataB) xfree(bmp->dataB, IDRGB);
  496. if (bmp->dataPalette) xfree(bmp->dataPalette, IDPALETTE);
  497. }
  498.  
  499. /* ------------------------------------------------------------------------- */
  500. void task_bmp2pgm(FILE *fpbmp, FILE *fppgm) {
  501. struct BMP24 *bmp;
  502. long Width, Height, y, x;
  503.  
  504. bmp = xmalloc(sizeof(struct BMP24), IDBMP);
  505. if (!BMP24_read(fpbmp, bmp)) {
  506. fprintf(stderr, "not a bitmap file, aborted.\n");
  507. xfree(bmp, IDBMP);
  508. return;
  509. }
  510. Width = iabs((bmp->bi).biWidth);
  511. Height = iabs((bmp->bi).biHeight);
  512. fprintf(fppgm, "P5\n");
  513. fprintf(fppgm, "%ld %ld\n", Width, Height);
  514. fprintf(fppgm, "255\n");
  515. if ((bmp->bi).biHeight < 0) {
  516. for (y = 0; y < Height; y++) {
  517. for (x = 0; x < Width; x++) {
  518. fprintf(fppgm, "%3d ", bmp->dataR[y * Width + x]);
  519. fprintf(fppgm, "%3d ", bmp->dataG[y * Width + x]);
  520. fprintf(fppgm, "%3d ", bmp->dataB[y * Width + x]);
  521. }
  522. fprintf(fppgm, "\n");
  523. }
  524. } else {
  525. for (y = Height - 1; y >= 0; y--) {
  526. for (x = 0; x < Width; x++) {
  527. fprintf(fppgm, "%3d ", bmp->dataR[y * Width + x]);
  528. fprintf(fppgm, "%3d ", bmp->dataG[y * Width + x]);
  529. fprintf(fppgm, "%3d ", bmp->dataB[y * Width + x]);
  530. }
  531. fprintf(fppgm, "\n");
  532. }
  533. }
  534. BMP24_release(bmp);
  535. xfree(bmp, IDBMP);
  536. }
  537.  
  538. int main(int argc, char **argv) {
  539. FILE *fpbmp, *fppgm;
  540. if (argc != 3) {
  541. fprintf(stderr, "usage: %s <filename:bmp> <filename:pgm>\n", argv[0]);
  542. exit(-1);
  543. }
  544. if ((fpbmp = fopen(argv[1], "r")) == 0) {
  545. fprintf(stderr, "cannot open the .bmp file for reading\n");
  546. exit(-1);
  547. }
  548. if ((fppgm = fopen(argv[2], "w")) == 0) {
  549. fprintf(stderr, "cannot open the .bgm file for writing\n");
  550. fclose(fpbmp);
  551. exit(-1);
  552. }
  553. task_bmp2pgm(fpbmp, fppgm);
  554. fclose(fpbmp);
  555. fclose(fppgm);
  556. xmallocdump();
  557. return 0;
  558. }
  559. /* end */
  560.  
Runtime error #stdin #stdout #stderr 0s 5680KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
usage: ./prog <filename:bmp> <filename:pgm>