image.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package bimg
  2. // Image provides a simple method DSL to transform a given image as byte buffer.
  3. type Image struct {
  4. buffer []byte
  5. }
  6. // NewImage creates a new Image struct with method DSL.
  7. func NewImage(buf []byte) *Image {
  8. return &Image{buf}
  9. }
  10. // Resize resizes the image to fixed width and height.
  11. func (i *Image) Resize(width, height int) ([]byte, error) {
  12. options := Options{
  13. Width: width,
  14. Height: height,
  15. Embed: true,
  16. }
  17. return i.Process(options)
  18. }
  19. // ForceResize resizes with custom size (aspect ratio won't be maintained).
  20. func (i *Image) ForceResize(width, height int) ([]byte, error) {
  21. options := Options{
  22. Width: width,
  23. Height: height,
  24. Force: true,
  25. }
  26. return i.Process(options)
  27. }
  28. // ResizeAndCrop resizes the image to fixed width and height with additional crop transformation.
  29. func (i *Image) ResizeAndCrop(width, height int) ([]byte, error) {
  30. options := Options{
  31. Width: width,
  32. Height: height,
  33. Embed: true,
  34. Crop: true,
  35. }
  36. return i.Process(options)
  37. }
  38. // SmartCrop produces a thumbnail aiming at focus on the interesting part.
  39. func (i *Image) SmartCrop(width, height int) ([]byte, error) {
  40. options := Options{
  41. Width: width,
  42. Height: height,
  43. Crop: true,
  44. Gravity: GravitySmart,
  45. }
  46. return i.Process(options)
  47. }
  48. // Extract area from the by X/Y axis in the current image.
  49. func (i *Image) Extract(top, left, width, height int) ([]byte, error) {
  50. options := Options{
  51. Top: top,
  52. Left: left,
  53. AreaWidth: width,
  54. AreaHeight: height,
  55. }
  56. if top == 0 && left == 0 {
  57. options.Top = -1
  58. }
  59. return i.Process(options)
  60. }
  61. // Enlarge enlarges the image by width and height. Aspect ratio is maintained.
  62. func (i *Image) Enlarge(width, height int) ([]byte, error) {
  63. options := Options{
  64. Width: width,
  65. Height: height,
  66. Enlarge: true,
  67. }
  68. return i.Process(options)
  69. }
  70. // EnlargeAndCrop enlarges the image by width and height with additional crop transformation.
  71. func (i *Image) EnlargeAndCrop(width, height int) ([]byte, error) {
  72. options := Options{
  73. Width: width,
  74. Height: height,
  75. Enlarge: true,
  76. Crop: true,
  77. }
  78. return i.Process(options)
  79. }
  80. // Crop crops the image to the exact size specified.
  81. func (i *Image) Crop(width, height int, gravity Gravity) ([]byte, error) {
  82. options := Options{
  83. Width: width,
  84. Height: height,
  85. Gravity: gravity,
  86. Crop: true,
  87. }
  88. return i.Process(options)
  89. }
  90. // CropByWidth crops an image by width only param (auto height).
  91. func (i *Image) CropByWidth(width int) ([]byte, error) {
  92. options := Options{
  93. Width: width,
  94. Crop: true,
  95. }
  96. return i.Process(options)
  97. }
  98. // CropByHeight crops an image by height (auto width).
  99. func (i *Image) CropByHeight(height int) ([]byte, error) {
  100. options := Options{
  101. Height: height,
  102. Crop: true,
  103. }
  104. return i.Process(options)
  105. }
  106. // Thumbnail creates a thumbnail of the image by the a given width by aspect ratio 4:4.
  107. func (i *Image) Thumbnail(pixels int) ([]byte, error) {
  108. options := Options{
  109. Width: pixels,
  110. Height: pixels,
  111. Crop: true,
  112. Quality: 95,
  113. }
  114. return i.Process(options)
  115. }
  116. // Watermark adds text as watermark on the given image.
  117. func (i *Image) Watermark(w Watermark) ([]byte, error) {
  118. options := Options{Watermark: w}
  119. return i.Process(options)
  120. }
  121. // WatermarkImage adds image as watermark on the given image.
  122. func (i *Image) WatermarkImage(w WatermarkImage) ([]byte, error) {
  123. options := Options{WatermarkImage: w}
  124. return i.Process(options)
  125. }
  126. // Zoom zooms the image by the given factor.
  127. // You should probably call Extract() before.
  128. func (i *Image) Zoom(factor int) ([]byte, error) {
  129. options := Options{Zoom: factor}
  130. return i.Process(options)
  131. }
  132. // Rotate rotates the image by given angle degrees (0, 90, 180 or 270).
  133. func (i *Image) Rotate(a Angle) ([]byte, error) {
  134. options := Options{Rotate: a}
  135. return i.Process(options)
  136. }
  137. // Flip flips the image about the vertical Y axis.
  138. func (i *Image) Flip() ([]byte, error) {
  139. options := Options{Flip: true}
  140. return i.Process(options)
  141. }
  142. // Flop flops the image about the horizontal X axis.
  143. func (i *Image) Flop() ([]byte, error) {
  144. options := Options{Flop: true}
  145. return i.Process(options)
  146. }
  147. // Convert converts image to another format.
  148. func (i *Image) Convert(t ImageType) ([]byte, error) {
  149. options := Options{Type: t}
  150. return i.Process(options)
  151. }
  152. // Colourspace performs a color space conversion bsaed on the given interpretation.
  153. func (i *Image) Colourspace(c Interpretation) ([]byte, error) {
  154. options := Options{Interpretation: c}
  155. return i.Process(options)
  156. }
  157. // Process processes the image based on the given transformation options,
  158. // talking with libvips bindings accordingly and returning the resultant
  159. // image buffer.
  160. func (i *Image) Process(o Options) ([]byte, error) {
  161. image, err := Resize(i.buffer, o)
  162. if err != nil {
  163. return nil, err
  164. }
  165. i.buffer = image
  166. return image, nil
  167. }
  168. // Metadata returns the image metadata (size, alpha channel, profile, EXIF rotation).
  169. func (i *Image) Metadata() (ImageMetadata, error) {
  170. return Metadata(i.buffer)
  171. }
  172. // Interpretation gets the image interpretation type.
  173. // See: http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/VipsImage.html#VipsInterpretation
  174. func (i *Image) Interpretation() (Interpretation, error) {
  175. return ImageInterpretation(i.buffer)
  176. }
  177. // ColourspaceIsSupported checks if the current image
  178. // color space is supported.
  179. func (i *Image) ColourspaceIsSupported() (bool, error) {
  180. return ColourspaceIsSupported(i.buffer)
  181. }
  182. // Type returns the image type format (jpeg, png, webp, tiff).
  183. func (i *Image) Type() string {
  184. return DetermineImageTypeName(i.buffer)
  185. }
  186. // Size returns the image size as form of width and height pixels.
  187. func (i *Image) Size() (ImageSize, error) {
  188. return Size(i.buffer)
  189. }
  190. // Image returns the current resultant image buffer.
  191. func (i *Image) Image() []byte {
  192. return i.buffer
  193. }
  194. // Length returns the size in bytes of the image buffer.
  195. func (i *Image) Length() int {
  196. return len(i.buffer)
  197. }