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.

123 lines
3.8KB

  1. /*
  2. * XBM image format
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * Libav is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "libavutil/avstring.h"
  21. #include "avcodec.h"
  22. #include "internal.h"
  23. #include "mathops.h"
  24. static int xbm_decode_frame(AVCodecContext *avctx, void *data,
  25. int *got_frame, AVPacket *avpkt)
  26. {
  27. AVFrame *p = data;
  28. int ret, linesize, i;
  29. int width = 0;
  30. int height = 0;
  31. const uint8_t *ptr = avpkt->data;
  32. uint8_t *dst;
  33. avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
  34. while (!width || !height) {
  35. ptr += strcspn(ptr, "#");
  36. if (ptr >= avpkt->data + avpkt->size) {
  37. av_log(avctx, AV_LOG_ERROR, "End of file reached.\n");
  38. return AVERROR_INVALIDDATA;
  39. }
  40. if (strncmp(ptr, "#define", 7) != 0) {
  41. av_log(avctx, AV_LOG_ERROR,
  42. "Unexpected preprocessor directive.\n");
  43. return AVERROR_INVALIDDATA;
  44. }
  45. // skip the name
  46. ptr += strcspn(ptr, "_") + 1;
  47. // get width or height
  48. if (strncmp(ptr, "width", 5) == 0) {
  49. ptr += strcspn(ptr, " ");
  50. width = strtol(ptr, NULL, 10);
  51. } else if (strncmp(ptr, "height", 6) == 0) {
  52. ptr += strcspn(ptr, " ");
  53. height = strtol(ptr, NULL, 10);
  54. } else {
  55. // skip offset and unknown variables
  56. av_log(avctx, AV_LOG_VERBOSE,
  57. "Ignoring preprocessor directive.\n");
  58. }
  59. }
  60. if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
  61. return ret;
  62. if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
  63. return ret;
  64. // go to start of image data
  65. ptr += strcspn(ptr, "{");
  66. linesize = (avctx->width + 7) / 8;
  67. for (i = 0; i < avctx->height; i++) {
  68. int eol = 0, e = 0;
  69. dst = p->data[0] + i * p->linesize[0];
  70. if (ptr >= avpkt->data + avpkt->size) {
  71. av_log(avctx, AV_LOG_ERROR, "End of file reached.\n");
  72. return AVERROR_INVALIDDATA;
  73. }
  74. do {
  75. int val;
  76. uint8_t *endptr;
  77. ptr += strcspn(ptr, "x") - 1; // -1 to get 0x
  78. val = strtol(ptr, (char **)&endptr, 16);
  79. if (endptr - ptr == 4) {
  80. // XBM X11 format
  81. *dst++ = ff_reverse[val];
  82. eol = linesize;
  83. } else if (endptr - ptr == 6) {
  84. // XBM X10 format
  85. *dst++ = ff_reverse[val >> 8];
  86. *dst++ = ff_reverse[val & 0xFF];
  87. eol = linesize / 2; // 2 bytes read
  88. } else {
  89. av_log(avctx, AV_LOG_ERROR,
  90. "Unexpected data at %.8s.\n", ptr);
  91. return AVERROR_INVALIDDATA;
  92. }
  93. ptr = endptr;
  94. } while (++e < eol);
  95. }
  96. p->key_frame = 1;
  97. p->pict_type = AV_PICTURE_TYPE_I;
  98. *got_frame = 1;
  99. return avpkt->size;
  100. }
  101. AVCodec ff_xbm_decoder = {
  102. .name = "xbm",
  103. .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
  104. .type = AVMEDIA_TYPE_VIDEO,
  105. .id = AV_CODEC_ID_XBM,
  106. .decode = xbm_decode_frame,
  107. .capabilities = AV_CODEC_CAP_DR1,
  108. };