You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
12KB

  1. /*
  2. * PNM image format
  3. * Copyright (c) 2002, 2003 Fabrice Bellard.
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "avformat.h"
  22. static inline int pnm_space(int c)
  23. {
  24. return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
  25. }
  26. static void pnm_get(ByteIOContext *f, char *str, int buf_size)
  27. {
  28. char *s;
  29. int c;
  30. /* skip spaces and comments */
  31. for(;;) {
  32. c = url_fgetc(f);
  33. if (c == '#') {
  34. do {
  35. c = url_fgetc(f);
  36. } while (c != '\n' && c != URL_EOF);
  37. } else if (!pnm_space(c)) {
  38. break;
  39. }
  40. }
  41. s = str;
  42. while (c != URL_EOF && !pnm_space(c)) {
  43. if ((s - str) < buf_size - 1)
  44. *s++ = c;
  45. c = url_fgetc(f);
  46. }
  47. *s = '\0';
  48. }
  49. static int pnm_read1(ByteIOContext *f,
  50. int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque,
  51. int allow_yuv)
  52. {
  53. int i, n, linesize, h;
  54. char buf1[32];
  55. unsigned char *ptr;
  56. AVImageInfo info1, *info = &info1;
  57. int ret;
  58. pnm_get(f, buf1, sizeof(buf1));
  59. if (!strcmp(buf1, "P4")) {
  60. info->pix_fmt = PIX_FMT_MONOWHITE;
  61. } else if (!strcmp(buf1, "P5")) {
  62. if (allow_yuv)
  63. info->pix_fmt = PIX_FMT_YUV420P;
  64. else
  65. info->pix_fmt = PIX_FMT_GRAY8;
  66. } else if (!strcmp(buf1, "P6")) {
  67. info->pix_fmt = PIX_FMT_RGB24;
  68. } else {
  69. return AVERROR_INVALIDDATA;
  70. }
  71. pnm_get(f, buf1, sizeof(buf1));
  72. info->width = atoi(buf1);
  73. if (info->width <= 0)
  74. return AVERROR_INVALIDDATA;
  75. pnm_get(f, buf1, sizeof(buf1));
  76. info->height = atoi(buf1);
  77. if (info->height <= 0)
  78. return AVERROR_INVALIDDATA;
  79. if (info->pix_fmt != PIX_FMT_MONOWHITE) {
  80. pnm_get(f, buf1, sizeof(buf1));
  81. }
  82. /* more check if YUV420 */
  83. if (info->pix_fmt == PIX_FMT_YUV420P) {
  84. if ((info->width & 1) != 0)
  85. return AVERROR_INVALIDDATA;
  86. h = (info->height * 2);
  87. if ((h % 3) != 0)
  88. return AVERROR_INVALIDDATA;
  89. h /= 3;
  90. info->height = h;
  91. }
  92. ret = alloc_cb(opaque, info);
  93. if (ret)
  94. return ret;
  95. switch(info->pix_fmt) {
  96. default:
  97. return AVERROR_INVALIDDATA;
  98. case PIX_FMT_RGB24:
  99. n = info->width * 3;
  100. goto do_read;
  101. case PIX_FMT_GRAY8:
  102. n = info->width;
  103. goto do_read;
  104. case PIX_FMT_MONOWHITE:
  105. n = (info->width + 7) >> 3;
  106. do_read:
  107. ptr = info->pict.data[0];
  108. linesize = info->pict.linesize[0];
  109. for(i = 0; i < info->height; i++) {
  110. get_buffer(f, ptr, n);
  111. ptr += linesize;
  112. }
  113. break;
  114. case PIX_FMT_YUV420P:
  115. {
  116. unsigned char *ptr1, *ptr2;
  117. n = info->width;
  118. ptr = info->pict.data[0];
  119. linesize = info->pict.linesize[0];
  120. for(i = 0; i < info->height; i++) {
  121. get_buffer(f, ptr, n);
  122. ptr += linesize;
  123. }
  124. ptr1 = info->pict.data[1];
  125. ptr2 = info->pict.data[2];
  126. n >>= 1;
  127. h = info->height >> 1;
  128. for(i = 0; i < h; i++) {
  129. get_buffer(f, ptr1, n);
  130. get_buffer(f, ptr2, n);
  131. ptr1 += info->pict.linesize[1];
  132. ptr2 += info->pict.linesize[2];
  133. }
  134. }
  135. break;
  136. }
  137. return 0;
  138. }
  139. static int pnm_read(ByteIOContext *f,
  140. int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
  141. {
  142. return pnm_read1(f, alloc_cb, opaque, 0);
  143. }
  144. static int pgmyuv_read(ByteIOContext *f,
  145. int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
  146. {
  147. return pnm_read1(f, alloc_cb, opaque, 1);
  148. }
  149. static int pnm_write(ByteIOContext *pb, AVImageInfo *info)
  150. {
  151. int i, h, h1, c, n, linesize;
  152. char buf[100];
  153. uint8_t *ptr, *ptr1, *ptr2;
  154. h = info->height;
  155. h1 = h;
  156. switch(info->pix_fmt) {
  157. case PIX_FMT_MONOWHITE:
  158. c = '4';
  159. n = (info->width + 7) >> 3;
  160. break;
  161. case PIX_FMT_GRAY8:
  162. c = '5';
  163. n = info->width;
  164. break;
  165. case PIX_FMT_RGB24:
  166. c = '6';
  167. n = info->width * 3;
  168. break;
  169. case PIX_FMT_YUV420P:
  170. c = '5';
  171. n = info->width;
  172. h1 = (h * 3) / 2;
  173. break;
  174. default:
  175. return AVERROR_INVALIDDATA;
  176. }
  177. snprintf(buf, sizeof(buf),
  178. "P%c\n%d %d\n",
  179. c, info->width, h1);
  180. put_buffer(pb, buf, strlen(buf));
  181. if (info->pix_fmt != PIX_FMT_MONOWHITE) {
  182. snprintf(buf, sizeof(buf),
  183. "%d\n", 255);
  184. put_buffer(pb, buf, strlen(buf));
  185. }
  186. ptr = info->pict.data[0];
  187. linesize = info->pict.linesize[0];
  188. for(i=0;i<h;i++) {
  189. put_buffer(pb, ptr, n);
  190. ptr += linesize;
  191. }
  192. if (info->pix_fmt == PIX_FMT_YUV420P) {
  193. h >>= 1;
  194. n >>= 1;
  195. ptr1 = info->pict.data[1];
  196. ptr2 = info->pict.data[2];
  197. for(i=0;i<h;i++) {
  198. put_buffer(pb, ptr1, n);
  199. put_buffer(pb, ptr2, n);
  200. ptr1 += info->pict.linesize[1];
  201. ptr2 += info->pict.linesize[2];
  202. }
  203. }
  204. put_flush_packet(pb);
  205. return 0;
  206. }
  207. static int pam_read(ByteIOContext *f,
  208. int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque)
  209. {
  210. int i, n, linesize, h, w, depth, maxval;
  211. char buf1[32], tuple_type[32];
  212. unsigned char *ptr;
  213. AVImageInfo info1, *info = &info1;
  214. int ret;
  215. pnm_get(f, buf1, sizeof(buf1));
  216. if (strcmp(buf1, "P7") != 0)
  217. return AVERROR_INVALIDDATA;
  218. w = -1;
  219. h = -1;
  220. maxval = -1;
  221. depth = -1;
  222. tuple_type[0] = '\0';
  223. for(;;) {
  224. pnm_get(f, buf1, sizeof(buf1));
  225. if (!strcmp(buf1, "WIDTH")) {
  226. pnm_get(f, buf1, sizeof(buf1));
  227. w = strtol(buf1, NULL, 10);
  228. } else if (!strcmp(buf1, "HEIGHT")) {
  229. pnm_get(f, buf1, sizeof(buf1));
  230. h = strtol(buf1, NULL, 10);
  231. } else if (!strcmp(buf1, "DEPTH")) {
  232. pnm_get(f, buf1, sizeof(buf1));
  233. depth = strtol(buf1, NULL, 10);
  234. } else if (!strcmp(buf1, "MAXVAL")) {
  235. pnm_get(f, buf1, sizeof(buf1));
  236. maxval = strtol(buf1, NULL, 10);
  237. } else if (!strcmp(buf1, "TUPLETYPE")) {
  238. pnm_get(f, buf1, sizeof(buf1));
  239. pstrcpy(tuple_type, sizeof(tuple_type), buf1);
  240. } else if (!strcmp(buf1, "ENDHDR")) {
  241. break;
  242. } else {
  243. return AVERROR_INVALIDDATA;
  244. }
  245. }
  246. /* check that all tags are present */
  247. if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0')
  248. return AVERROR_INVALIDDATA;
  249. info->width = w;
  250. info->height = h;
  251. if (depth == 1) {
  252. if (maxval == 1)
  253. info->pix_fmt = PIX_FMT_MONOWHITE;
  254. else
  255. info->pix_fmt = PIX_FMT_GRAY8;
  256. } else if (depth == 3) {
  257. info->pix_fmt = PIX_FMT_RGB24;
  258. } else if (depth == 4) {
  259. info->pix_fmt = PIX_FMT_RGBA32;
  260. } else {
  261. return AVERROR_INVALIDDATA;
  262. }
  263. ret = alloc_cb(opaque, info);
  264. if (ret)
  265. return ret;
  266. switch(info->pix_fmt) {
  267. default:
  268. return AVERROR_INVALIDDATA;
  269. case PIX_FMT_RGB24:
  270. n = info->width * 3;
  271. goto do_read;
  272. case PIX_FMT_GRAY8:
  273. n = info->width;
  274. goto do_read;
  275. case PIX_FMT_MONOWHITE:
  276. n = (info->width + 7) >> 3;
  277. do_read:
  278. ptr = info->pict.data[0];
  279. linesize = info->pict.linesize[0];
  280. for(i = 0; i < info->height; i++) {
  281. get_buffer(f, ptr, n);
  282. ptr += linesize;
  283. }
  284. break;
  285. case PIX_FMT_RGBA32:
  286. ptr = info->pict.data[0];
  287. linesize = info->pict.linesize[0];
  288. for(i = 0; i < info->height; i++) {
  289. int j, r, g, b, a;
  290. for(j = 0;j < w; j++) {
  291. r = get_byte(f);
  292. g = get_byte(f);
  293. b = get_byte(f);
  294. a = get_byte(f);
  295. ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
  296. }
  297. ptr += linesize;
  298. }
  299. break;
  300. }
  301. return 0;
  302. }
  303. static int pam_write(ByteIOContext *pb, AVImageInfo *info)
  304. {
  305. int i, h, w, n, linesize, depth, maxval;
  306. const char *tuple_type;
  307. char buf[100];
  308. uint8_t *ptr;
  309. h = info->height;
  310. w = info->width;
  311. switch(info->pix_fmt) {
  312. case PIX_FMT_MONOWHITE:
  313. n = (info->width + 7) >> 3;
  314. depth = 1;
  315. maxval = 1;
  316. tuple_type = "BLACKANDWHITE";
  317. break;
  318. case PIX_FMT_GRAY8:
  319. n = info->width;
  320. depth = 1;
  321. maxval = 255;
  322. tuple_type = "GRAYSCALE";
  323. break;
  324. case PIX_FMT_RGB24:
  325. n = info->width * 3;
  326. depth = 3;
  327. maxval = 255;
  328. tuple_type = "RGB";
  329. break;
  330. case PIX_FMT_RGBA32:
  331. n = info->width * 4;
  332. depth = 4;
  333. maxval = 255;
  334. tuple_type = "RGB_ALPHA";
  335. break;
  336. default:
  337. return AVERROR_INVALIDDATA;
  338. }
  339. snprintf(buf, sizeof(buf),
  340. "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLETYPE %s\nENDHDR\n",
  341. w, h, depth, maxval, tuple_type);
  342. put_buffer(pb, buf, strlen(buf));
  343. ptr = info->pict.data[0];
  344. linesize = info->pict.linesize[0];
  345. if (info->pix_fmt == PIX_FMT_RGBA32) {
  346. int j;
  347. unsigned int v;
  348. for(i=0;i<h;i++) {
  349. for(j=0;j<w;j++) {
  350. v = ((uint32_t *)ptr)[j];
  351. put_byte(pb, (v >> 16) & 0xff);
  352. put_byte(pb, (v >> 8) & 0xff);
  353. put_byte(pb, (v) & 0xff);
  354. put_byte(pb, (v >> 24) & 0xff);
  355. }
  356. ptr += linesize;
  357. }
  358. } else {
  359. for(i=0;i<h;i++) {
  360. put_buffer(pb, ptr, n);
  361. ptr += linesize;
  362. }
  363. }
  364. put_flush_packet(pb);
  365. return 0;
  366. }
  367. static int pnm_probe(AVProbeData *pd)
  368. {
  369. const char *p = pd->buf;
  370. if (pd->buf_size >= 8 &&
  371. p[0] == 'P' &&
  372. p[1] >= '4' && p[1] <= '6' &&
  373. pnm_space(p[2]) )
  374. return AVPROBE_SCORE_MAX - 1; /* to permit pgmyuv probe */
  375. else
  376. return 0;
  377. }
  378. static int pgmyuv_probe(AVProbeData *pd)
  379. {
  380. if (match_ext(pd->filename, "pgmyuv"))
  381. return AVPROBE_SCORE_MAX;
  382. else
  383. return 0;
  384. }
  385. static int pam_probe(AVProbeData *pd)
  386. {
  387. const char *p = pd->buf;
  388. if (pd->buf_size >= 8 &&
  389. p[0] == 'P' &&
  390. p[1] == '7' &&
  391. p[2] == '\n')
  392. return AVPROBE_SCORE_MAX;
  393. else
  394. return 0;
  395. }
  396. AVImageFormat pnm_image_format = {
  397. "pnm",
  398. NULL,
  399. pnm_probe,
  400. pnm_read,
  401. 0,
  402. NULL,
  403. };
  404. AVImageFormat pbm_image_format = {
  405. "pbm",
  406. "pbm",
  407. NULL,
  408. NULL,
  409. (1 << PIX_FMT_MONOWHITE),
  410. pnm_write,
  411. };
  412. AVImageFormat pgm_image_format = {
  413. "pgm",
  414. "pgm",
  415. NULL,
  416. NULL,
  417. (1 << PIX_FMT_GRAY8),
  418. pnm_write,
  419. };
  420. AVImageFormat ppm_image_format = {
  421. "ppm",
  422. "ppm",
  423. NULL,
  424. NULL,
  425. (1 << PIX_FMT_RGB24),
  426. pnm_write,
  427. };
  428. AVImageFormat pam_image_format = {
  429. "pam",
  430. "pam",
  431. pam_probe,
  432. pam_read,
  433. (1 << PIX_FMT_MONOWHITE) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_RGB24) |
  434. (1 << PIX_FMT_RGBA32),
  435. pam_write,
  436. };
  437. AVImageFormat pgmyuv_image_format = {
  438. "pgmyuv",
  439. "pgmyuv",
  440. pgmyuv_probe,
  441. pgmyuv_read,
  442. (1 << PIX_FMT_YUV420P),
  443. pnm_write,
  444. };