rle.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // ◄◄◄ gobmp/rle.go ►►►
  2. // Copyright © 2012 Jason Summers
  3. // Use of this code is governed by an MIT-style license that can
  4. // be found in the readme.md file.
  5. //
  6. // BMP RLE decoder
  7. //
  8. package gobmp
  9. import "io"
  10. import "bufio"
  11. type rleState struct {
  12. xpos, ypos int // Position in the target image
  13. badColorFlag bool
  14. }
  15. func (d *decoder) rlePutPixel(rle *rleState, v byte) {
  16. // Make sure the position is valid.
  17. if rle.xpos < 0 || rle.xpos >= d.width ||
  18. rle.ypos < 0 || rle.ypos >= d.height {
  19. return
  20. }
  21. // Make sure the palette index is valid.
  22. if int(v) >= d.dstPalNumEntries {
  23. rle.badColorFlag = true
  24. return
  25. }
  26. // Set the pixel, and advance the current position.
  27. var dstRow int
  28. if d.isTopDown {
  29. // Top-down RLE-compressed images are not legal in any known BMP
  30. // specification, but we'll tolerate them.
  31. dstRow = rle.ypos
  32. } else {
  33. dstRow = d.height - rle.ypos - 1
  34. }
  35. d.img_Paletted.Pix[dstRow*d.img_Paletted.Stride+rle.xpos] = v
  36. rle.xpos++
  37. }
  38. func (d *decoder) readBitsRLE() error {
  39. var err error
  40. var b1, b2 byte
  41. var uncPixelsLeft int
  42. var deltaFlag bool
  43. var k int
  44. bufferedR := bufio.NewReader(d.r)
  45. rle := new(rleState)
  46. rle.xpos = 0
  47. rle.ypos = 0
  48. for {
  49. if rle.badColorFlag {
  50. return FormatError("palette index out of range")
  51. }
  52. if rle.ypos >= d.height || (rle.ypos == (d.height-1) && rle.xpos >= d.width) {
  53. break // Reached the end of the target image; may as well stop
  54. }
  55. // Read the next two bytes
  56. b1, err = bufferedR.ReadByte()
  57. if err == nil {
  58. b2, err = bufferedR.ReadByte()
  59. }
  60. if err != nil {
  61. if err == io.EOF {
  62. break
  63. }
  64. return err
  65. }
  66. if uncPixelsLeft > 0 {
  67. if d.biCompression == bI_RLE4 {
  68. // The two bytes we're processing store up to 4 uncompressed pixels.
  69. d.rlePutPixel(rle, b1>>4)
  70. uncPixelsLeft--
  71. if uncPixelsLeft > 0 {
  72. d.rlePutPixel(rle, b1&0x0f)
  73. uncPixelsLeft--
  74. }
  75. if uncPixelsLeft > 0 {
  76. d.rlePutPixel(rle, b2>>4)
  77. uncPixelsLeft--
  78. }
  79. if uncPixelsLeft > 0 {
  80. d.rlePutPixel(rle, b2&0x0f)
  81. uncPixelsLeft--
  82. }
  83. } else { // RLE8
  84. // The two bytes we're processing store up to 2 uncompressed pixels.
  85. d.rlePutPixel(rle, b1)
  86. uncPixelsLeft--
  87. if uncPixelsLeft > 0 {
  88. d.rlePutPixel(rle, b2)
  89. uncPixelsLeft--
  90. }
  91. }
  92. } else if deltaFlag {
  93. rle.xpos += int(b1)
  94. rle.ypos += int(b2)
  95. deltaFlag = false
  96. } else if b1 == 0 {
  97. // An uncompressed run, or a special code.
  98. //
  99. // Any pixels skipped by special codes will be left at whatever
  100. // image.NewPaletted() initialized them to, which we assume is 0,
  101. // meaning palette entry 0.
  102. if b2 == 0 { // End of row
  103. rle.ypos++
  104. rle.xpos = 0
  105. } else if b2 == 1 { // End of bitmap
  106. break
  107. } else if b2 == 2 { // Delta
  108. deltaFlag = true
  109. } else {
  110. // An upcoming uncompressed run of b2 pixels
  111. uncPixelsLeft = int(b2)
  112. }
  113. } else { // A compressed run of pixels
  114. if d.biCompression == bI_RLE4 {
  115. // b1 pixels, alternating between two colors
  116. for k = 0; k < int(b1); k++ {
  117. if k%2 == 0 {
  118. d.rlePutPixel(rle, b2>>4)
  119. } else {
  120. d.rlePutPixel(rle, b2&0x0f)
  121. }
  122. }
  123. } else { // RLE8
  124. // b1 pixels of color b2
  125. for k = 0; k < int(b1); k++ {
  126. d.rlePutPixel(rle, b2)
  127. }
  128. }
  129. }
  130. }
  131. return nil
  132. }