scaledbarcode.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package barcode
  2. import (
  3. "errors"
  4. "fmt"
  5. "image"
  6. "image/color"
  7. "math"
  8. )
  9. type wrapFunc func(x, y int) color.Color
  10. type scaledBarcode struct {
  11. wrapped Barcode
  12. wrapperFunc wrapFunc
  13. rect image.Rectangle
  14. }
  15. func (bc *scaledBarcode) Content() string {
  16. return bc.wrapped.Content()
  17. }
  18. func (bc *scaledBarcode) Metadata() Metadata {
  19. return bc.wrapped.Metadata()
  20. }
  21. func (bc *scaledBarcode) ColorModel() color.Model {
  22. return bc.wrapped.ColorModel()
  23. }
  24. func (bc *scaledBarcode) Bounds() image.Rectangle {
  25. return bc.rect
  26. }
  27. func (bc *scaledBarcode) At(x, y int) color.Color {
  28. return bc.wrapperFunc(x, y)
  29. }
  30. func Scale(bc Barcode, width, height int) (Barcode, error) {
  31. switch bc.Metadata().Dimensions {
  32. case 1:
  33. return scale1DCode(bc, width, height)
  34. case 2:
  35. return scale2DCode(bc, width, height)
  36. }
  37. return nil, errors.New("unsupported barcode format")
  38. }
  39. func scale2DCode(bc Barcode, width, height int) (Barcode, error) {
  40. orgBounds := bc.Bounds()
  41. orgWidth := orgBounds.Max.X - orgBounds.Min.X
  42. orgHeight := orgBounds.Max.Y - orgBounds.Min.Y
  43. factor := int(math.Min(float64(width)/float64(orgWidth), float64(height)/float64(orgHeight)))
  44. if factor <= 0 {
  45. return nil, fmt.Errorf("can no scale barcode to an image smaller then %dx%d", orgWidth, orgHeight)
  46. }
  47. offsetX := (width - (orgWidth * factor)) / 2
  48. offsetY := (height - (orgHeight * factor)) / 2
  49. wrap := func(x, y int) color.Color {
  50. if x < offsetX || y < offsetY {
  51. return color.White
  52. }
  53. x = (x - offsetX) / factor
  54. y = (y - offsetY) / factor
  55. if x >= orgWidth || y >= orgHeight {
  56. return color.White
  57. }
  58. return bc.At(x, y)
  59. }
  60. return &scaledBarcode{
  61. bc,
  62. wrap,
  63. image.Rect(0, 0, width, height),
  64. }, nil
  65. }
  66. func scale1DCode(bc Barcode, width, height int) (Barcode, error) {
  67. orgBounds := bc.Bounds()
  68. orgWidth := orgBounds.Max.X - orgBounds.Min.X
  69. factor := int(float64(width) / float64(orgWidth))
  70. if factor <= 0 {
  71. return nil, fmt.Errorf("can no scale barcode to an image smaller then %dx1", orgWidth)
  72. }
  73. offsetX := (width - (orgWidth * factor)) / 2
  74. wrap := func(x, y int) color.Color {
  75. if x < offsetX {
  76. return color.White
  77. }
  78. x = (x - offsetX) / factor
  79. if x >= orgWidth {
  80. return color.White
  81. }
  82. return bc.At(x, 0)
  83. }
  84. return &scaledBarcode{
  85. bc,
  86. wrap,
  87. image.Rect(0, 0, width, height),
  88. }, nil
  89. }