resize.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright 2021-2022 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "bytes"
  17. "fmt"
  18. "image"
  19. "image/gif"
  20. "image/jpeg"
  21. "image/png"
  22. "github.com/nfnt/resize"
  23. "github.com/lf-edge/ekuiper/pkg/api"
  24. )
  25. type imageResize struct{}
  26. func (f *imageResize) Validate(args []interface{}) error {
  27. if len(args) < 3 {
  28. return fmt.Errorf("The resize function must have at least 3 parameters, but got %d", len(args))
  29. }
  30. return nil
  31. }
  32. func (f *imageResize) IsAggregate() bool {
  33. return false
  34. }
  35. func (f *imageResize) Exec(args []interface{}, ctx api.FunctionContext) (interface{}, bool) {
  36. arg, ok := args[0].([]byte)
  37. if !ok {
  38. return fmt.Errorf("arg[0] is not a bytea, got %v", args[0]), false
  39. }
  40. width, ok := args[1].(int)
  41. if !ok || 0 > width {
  42. return fmt.Errorf("arg[1] is not a bigint, got %v", args[1]), false
  43. }
  44. height, ok := args[2].(int)
  45. if !ok || 0 > height {
  46. return fmt.Errorf("arg[2] is not a bigint, got %v", args[2]), false
  47. }
  48. isRaw := false
  49. if len(args) > 3 {
  50. isRaw, ok = args[3].(bool)
  51. if !ok {
  52. return fmt.Errorf("arg[3] is not a bool, got %v", args[3]), false
  53. }
  54. }
  55. ctx.GetLogger().Debugf("resize: %d %d, output raw %v", width, height, isRaw)
  56. img, format, err := image.Decode(bytes.NewReader(arg))
  57. if nil != err {
  58. return fmt.Errorf("image decode error:%v", err), false
  59. }
  60. img = resize.Resize(uint(width), uint(height), img, resize.Bilinear)
  61. if isRaw {
  62. bounds := img.Bounds()
  63. dx, dy := bounds.Dx(), bounds.Dy()
  64. bb := make([]byte, width*height*3)
  65. for y := 0; y < dy; y++ {
  66. for x := 0; x < dx; x++ {
  67. col := img.At(x, y)
  68. r, g, b, _ := col.RGBA()
  69. bb[(y*dx+x)*3+0] = byte(float64(r) / 255.0)
  70. bb[(y*dx+x)*3+1] = byte(float64(g) / 255.0)
  71. bb[(y*dx+x)*3+2] = byte(float64(b) / 255.0)
  72. }
  73. }
  74. return bb, true
  75. } else {
  76. var b []byte
  77. buf := bytes.NewBuffer(b)
  78. switch format {
  79. case "png":
  80. err = png.Encode(buf, img)
  81. case "jpeg":
  82. err = jpeg.Encode(buf, img, nil)
  83. case "gif":
  84. err = gif.Encode(buf, img, nil)
  85. default:
  86. return fmt.Errorf("%s image type is not currently supported", format), false
  87. }
  88. if nil != err {
  89. return fmt.Errorf("image encode error:%v", err), false
  90. }
  91. return buf.Bytes(), true
  92. }
  93. }
  94. var ResizeWithChan imageResize