ico.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package imagemeta
  2. import (
  3. "encoding/binary"
  4. "io"
  5. )
  6. type IcoMeta struct {
  7. Meta
  8. offset int
  9. size int
  10. }
  11. func (m *IcoMeta) BestImageOffset() int {
  12. return m.offset
  13. }
  14. func (m *IcoMeta) BestImageSize() int {
  15. return m.size
  16. }
  17. func icoBestSize(r io.Reader) (width, height byte, offset uint32, size uint32, err error) {
  18. var tmp [16]byte
  19. if _, err = io.ReadFull(r, tmp[:6]); err != nil {
  20. return
  21. }
  22. count := binary.LittleEndian.Uint16(tmp[4:6])
  23. for i := uint16(0); i < count; i++ {
  24. if _, err = io.ReadFull(r, tmp[:]); err != nil {
  25. return
  26. }
  27. if tmp[0] > width || tmp[1] > height || tmp[0] == 0 || tmp[1] == 0 {
  28. width = tmp[0]
  29. height = tmp[1]
  30. size = binary.LittleEndian.Uint32(tmp[8:12])
  31. offset = binary.LittleEndian.Uint32(tmp[12:16])
  32. }
  33. }
  34. return
  35. }
  36. func BestIcoPage(r io.Reader) (int, int, error) {
  37. _, _, offset, size, err := icoBestSize(r)
  38. return int(offset), int(size), err
  39. }
  40. func DecodeIcoMeta(r io.Reader) (*IcoMeta, error) {
  41. bwidth, bheight, offset, size, err := icoBestSize(r)
  42. if err != nil {
  43. return nil, err
  44. }
  45. width := int(bwidth)
  46. height := int(bheight)
  47. if width == 0 {
  48. width = 256
  49. }
  50. if height == 0 {
  51. height = 256
  52. }
  53. return &IcoMeta{
  54. Meta: &meta{
  55. format: "ico",
  56. width: width,
  57. height: height,
  58. },
  59. offset: int(offset),
  60. size: int(size),
  61. }, nil
  62. }
  63. func init() {
  64. RegisterFormat(
  65. "\x00\x00\x01\x00",
  66. func(r io.Reader) (Meta, error) { return DecodeIcoMeta(r) },
  67. )
  68. }