resize.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. "github.com/lf-edge/ekuiper/pkg/api"
  19. "github.com/nfnt/resize"
  20. "image"
  21. "image/gif"
  22. "image/jpeg"
  23. "image/png"
  24. )
  25. type imageResize struct {
  26. }
  27. func (f *imageResize) Validate(args []interface{}) error {
  28. if len(args) < 3 {
  29. return fmt.Errorf("The resize function must have at least 3 parameters, but got %d", len(args))
  30. }
  31. return nil
  32. }
  33. func (f *imageResize) IsAggregate() bool {
  34. return false
  35. }
  36. func (f *imageResize) Exec(args []interface{}, ctx api.FunctionContext) (interface{}, bool) {
  37. arg, ok := args[0].([]byte)
  38. if !ok {
  39. return fmt.Errorf("arg[0] is not a bytea, got %v", args[0]), false
  40. }
  41. width, ok := args[1].(int)
  42. if !ok || 0 > width {
  43. return fmt.Errorf("arg[1] is not a bigint, got %v", args[1]), false
  44. }
  45. height, ok := args[2].(int)
  46. if !ok || 0 > height {
  47. return fmt.Errorf("arg[2] is not a bigint, got %v", args[2]), false
  48. }
  49. isRaw := false
  50. if len(args) > 3 {
  51. isRaw, ok = args[3].(bool)
  52. if !ok {
  53. return fmt.Errorf("arg[3] is not a bool, got %v", args[3]), false
  54. }
  55. }
  56. ctx.GetLogger().Debugf("resize: %d %d, output raw %v", width, height, isRaw)
  57. img, format, err := image.Decode(bytes.NewReader(arg))
  58. if nil != err {
  59. return fmt.Errorf("image decode error:%v", err), false
  60. }
  61. img = resize.Resize(uint(width), uint(height), img, resize.Bilinear)
  62. if isRaw {
  63. bounds := img.Bounds()
  64. dx, dy := bounds.Dx(), bounds.Dy()
  65. bb := make([]byte, width*height*3)
  66. for y := 0; y < dy; y++ {
  67. for x := 0; x < dx; x++ {
  68. col := img.At(x, y)
  69. r, g, b, _ := col.RGBA()
  70. bb[(y*dx+x)*3+0] = byte(float64(r) / 255.0)
  71. bb[(y*dx+x)*3+1] = byte(float64(g) / 255.0)
  72. bb[(y*dx+x)*3+2] = byte(float64(b) / 255.0)
  73. }
  74. }
  75. return bb, true
  76. } else {
  77. var b []byte
  78. buf := bytes.NewBuffer(b)
  79. switch format {
  80. case "png":
  81. err = png.Encode(buf, img)
  82. case "jpeg":
  83. err = jpeg.Encode(buf, img, nil)
  84. case "gif":
  85. err = gif.Encode(buf, img, nil)
  86. default:
  87. return fmt.Errorf("%s image type is not currently supported", format), false
  88. }
  89. if nil != err {
  90. return fmt.Errorf("image encode error:%v", err), false
  91. }
  92. return buf.Bytes(), true
  93. }
  94. }
  95. var ResizeWithChan imageResize