SunRleDecode.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * THIS IS WORK IN PROGRESS
  3. *
  4. * The Python Imaging Library.
  5. * $Id$
  6. *
  7. * decoder for SUN RLE data.
  8. *
  9. * history:
  10. * 97-01-04 fl Created
  11. *
  12. * Copyright (c) Fredrik Lundh 1997.
  13. * Copyright (c) Secret Labs AB 1997.
  14. *
  15. * See the README file for information on usage and redistribution.
  16. */
  17. #include "Imaging.h"
  18. int
  19. ImagingSunRleDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t bytes)
  20. {
  21. int n;
  22. UINT8* ptr;
  23. UINT8 extra_data = 0;
  24. UINT8 extra_bytes = 0;
  25. ptr = buf;
  26. for (;;) {
  27. if (bytes < 1)
  28. return ptr - buf;
  29. if (ptr[0] == 0x80) {
  30. if (bytes < 2)
  31. break;
  32. n = ptr[1];
  33. if (n == 0) {
  34. /* Literal 0x80 (2 bytes) */
  35. n = 1;
  36. state->buffer[state->x] = 0x80;
  37. ptr += 2;
  38. bytes -= 2;
  39. } else {
  40. /* Run (3 bytes) */
  41. if (bytes < 3)
  42. break;
  43. /* from (https://www.fileformat.info/format/sunraster/egff.htm)
  44. For example, a run of 100 pixels with the value of
  45. 0Ah would encode as the values 80h 64h 0Ah. A
  46. single pixel value of 80h would encode as the
  47. values 80h 00h. The four unencoded bytes 12345678h
  48. would be stored in the RLE stream as 12h 34h 56h
  49. 78h. 100 pixels, n=100, not 100 pixels, n=99.
  50. But Wait! There's More!
  51. (https://www.fileformat.info/format/sunraster/spec/598a59c4fac64c52897585d390d86360/view.htm)
  52. If the first byte is 0x80, and the second byte is
  53. not zero, the record is three bytes long. The
  54. second byte is a count and the third byte is a
  55. value. Output (count+1) pixels of that value.
  56. 2 specs, same site, but Imagemagick and GIMP seem
  57. to agree on the second one.
  58. */
  59. n += 1;
  60. if (state->x + n > state->bytes) {
  61. extra_bytes = n; /* full value */
  62. n = state->bytes - state->x;
  63. extra_bytes -= n;
  64. extra_data = ptr[2];
  65. }
  66. memset(state->buffer + state->x, ptr[2], n);
  67. ptr += 3;
  68. bytes -= 3;
  69. }
  70. } else {
  71. /* Literal byte */
  72. n = 1;
  73. state->buffer[state->x] = ptr[0];
  74. ptr += 1;
  75. bytes -= 1;
  76. }
  77. for (;;) {
  78. state->x += n;
  79. if (state->x >= state->bytes) {
  80. /* Got a full line, unpack it */
  81. state->shuffle((UINT8*) im->image[state->y + state->yoff] +
  82. state->xoff * im->pixelsize, state->buffer,
  83. state->xsize);
  84. state->x = 0;
  85. if (++state->y >= state->ysize) {
  86. /* End of file (errcode = 0) */
  87. return -1;
  88. }
  89. }
  90. if (extra_bytes == 0) {
  91. break;
  92. }
  93. if (state->x > 0) {
  94. break; // assert
  95. }
  96. if (extra_bytes >= state->bytes) {
  97. n = state->bytes;
  98. } else {
  99. n = extra_bytes;
  100. }
  101. memset(state->buffer + state->x, extra_data, n);
  102. extra_bytes -= n;
  103. }
  104. }
  105. return ptr - buf;
  106. }