feat(storage): added support for images/heic (#3694)

This commit is contained in:
David Barroso
2025-11-19 08:21:43 +01:00
committed by GitHub
parent f7ea20db61
commit ee2d9763f7
140 changed files with 27031 additions and 160639 deletions

View File

@@ -792,7 +792,7 @@ Maximum height to resize image to while maintaining aspect ratio. Only applies t
optional q: number;
```
Image quality (1-100). Only applies to JPEG, WebP and PNG files
Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
#### w?
@@ -842,7 +842,7 @@ Maximum height to resize image to while maintaining aspect ratio. Only applies t
optional q: number;
```
Image quality (1-100). Only applies to JPEG, WebP and PNG files
Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
#### w?
@@ -1068,7 +1068,7 @@ buildVersion: string
## OutputImageFormat
```ts
type OutputImageFormat = 'auto' | 'same' | 'jpeg' | 'webp' | 'png' | 'avif'
type OutputImageFormat = 'auto' | 'same' | 'jpeg' | 'webp' | 'png' | 'avif' | 'heic'
```
Output format for image files. Use 'auto' for content negotiation based on Accept header

View File

@@ -148,7 +148,7 @@ paths:
schema:
$ref: '#/components/schemas/RFC2822Date'
- name: q
description: "Image quality (1-100). Only applies to JPEG, WebP and PNG files"
description: "Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files"
in: query
schema:
type: integer
@@ -332,7 +332,7 @@ paths:
schema:
$ref: '#/components/schemas/RFC2822Date'
- name: q
description: "Image quality (1-100). Only applies to JPEG, WebP and PNG files"
description: "Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files"
in: query
schema:
type: integer
@@ -614,7 +614,7 @@ paths:
schema:
$ref: '#/components/schemas/RFC2822Date'
- name: q
description: "Image quality (1-100). Only applies to JPEG, WebP and PNG files"
description: "Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files"
in: query
schema:
type: integer
@@ -1178,4 +1178,5 @@ components:
- webp
- png
- avif
- heic
example: same

13
go.mod
View File

@@ -13,7 +13,7 @@ require (
github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf
github.com/charmbracelet/lipgloss v1.1.0
github.com/creack/pty v1.1.24
github.com/davidbyttow/govips/v2 v2.16.0
github.com/cshum/vipsgen v1.2.1
github.com/gabriel-vasile/mimetype v1.4.8
github.com/getkin/kin-openapi v0.133.0
github.com/gin-gonic/gin v1.11.0
@@ -43,10 +43,10 @@ require (
github.com/vektah/gqlparser/v2 v2.5.30
github.com/wI2L/jsondiff v0.7.0
go.uber.org/mock v0.5.0
golang.org/x/crypto v0.42.0
golang.org/x/crypto v0.43.0
golang.org/x/mod v0.28.0
golang.org/x/oauth2 v0.30.0
golang.org/x/term v0.35.0
golang.org/x/term v0.36.0
gopkg.in/evanphx/json-patch.v5 v5.9.11
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
@@ -179,11 +179,10 @@ require (
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
golang.org/x/arch v0.20.0 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/net v0.44.0 // indirect
golang.org/x/net v0.45.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/text v0.29.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.37.0 // indirect
google.golang.org/protobuf v1.36.9 // indirect

66
go.sum
View File

@@ -121,14 +121,14 @@ github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6N
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/cshum/vipsgen v1.2.1 h1:Es305Zf7C9T+8QbsiWn3BtQ+2/uHz6sp/SFnvwnO/kU=
github.com/cshum/vipsgen v1.2.1/go.mod h1:1GboZQcNmo4NwuNnGogM24m3O+1i6UpnvurqMcsFItE=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davidbyttow/govips/v2 v2.16.0 h1:1nH/Rbx8qZP1hd+oYL9fYQjAnm1+KorX9s07ZGseQmo=
github.com/davidbyttow/govips/v2 v2.16.0/go.mod h1:clH5/IDVmG5eVyc23qYpyi7kmOT0B/1QNTKtci4RkyM=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo=
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
@@ -223,7 +223,6 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc=
@@ -415,7 +414,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -465,7 +463,6 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
@@ -483,23 +480,14 @@ golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -508,17 +496,12 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
@@ -526,11 +509,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -544,50 +522,31 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -600,7 +559,6 @@ google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXn
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v5 v5.9.11 h1:OMPeiLomOQwe8+Ku4nwXsdOmrRw2vGUpP3XgLj3ojNw=

View File

@@ -275,7 +275,8 @@ export type OutputImageFormat =
| "jpeg"
| "webp"
| "png"
| "avif";
| "avif"
| "heic";
/**
*
@@ -378,7 +379,7 @@ export interface ListOrphanedFilesResponse200 {
/**
* Parameters for the getFile method.
@property q? (number) - Image quality (1-100). Only applies to JPEG, WebP and PNG files
@property q? (number) - Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
@property h? (number) - Maximum height to resize image to while maintaining aspect ratio. Only applies to image files
@@ -391,7 +392,7 @@ export interface ListOrphanedFilesResponse200 {
* Output format for image files. Use 'auto' for content negotiation based on Accept header*/
export interface GetFileParams {
/**
* Image quality (1-100). Only applies to JPEG, WebP and PNG files
* Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
*/
q?: number;
@@ -419,7 +420,7 @@ export interface GetFileParams {
}
/**
* Parameters for the getFileMetadataHeaders method.
@property q? (number) - Image quality (1-100). Only applies to JPEG, WebP and PNG files
@property q? (number) - Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
@property h? (number) - Maximum height to resize image to while maintaining aspect ratio. Only applies to image files
@@ -432,7 +433,7 @@ export interface GetFileParams {
* Output format for image files. Use 'auto' for content negotiation based on Accept header*/
export interface GetFileMetadataHeadersParams {
/**
* Image quality (1-100). Only applies to JPEG, WebP and PNG files
* Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
*/
q?: number;

View File

@@ -2066,83 +2066,84 @@ func (sh *strictHandler) GetVersion(ctx *gin.Context) {
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
"H4sIAAAAAAAC/+xde3PbtrL/KhjezjQ5FSVLjpNzNdO5102c1j1x4ontk86tc2cgciWiIQEWACUrtr/7",
"mQXAlwj5FSd1E/3TOhIei90f9oUFdB5EIssFB65VMD4PVJRARs2fe1IK+RZULrgC/IDGMdNMcJoeSpGD",
"1AxUMJ7SVEEviEFFkuX4fTC2fQnjUyEzip8RCbqQHGIyWRKdANk93O8HvSBvjHQeAHa701QxaMpS1R0y",
"ppquH1HLojPgbtWSYGciIaUaYqKFIdzQ2CNsSihf4nx6mUMwDsTkD4h0cNkLMlCKzgzL2iP/UmSUhxJo",
"TCepG4m41jgSnNEsT3GwlywFwoUmU1HwuJ5Eacn4LLi87AUS/iyYhDgY/17N+L5DzaWHvpZg3zGdHEoR",
"gVIQ47RqI+q/p6gNO1bk2CbqFVOaiCmZ4tdEJ1STBUggqoiw37RI0yWpBiETmAoJNSeIiKJCSohxAUxD",
"Zqb4TsI0GAf/NagVycBpkQHScQCaGsnUUKRS0qUfm60et0PHc5HlEhLgis2BZG6QFjLpRBSaUMMAwjhR",
"WkgnkDaUJkX0AfR+3OXh/gvkIPLEtiGR4JoyzvjMfIpDtwVcKJAqtK274u0FkQQE3a7uTnbMMlCaZjlZ",
"JMCr8cmCKuK6tecabY22w61hONw5Ho7G20/GO0//L+gFlgPBGLcIhJpl4CMENJ11adjjmukl0XRGpkKS",
"iEYJkDlNWWx42p7/NKDDySjajp/AzvTpaeCbhnm4esLZnwUQFgPXbMpAmrn8/Ix34NnTCCbhs2d0FD4Z",
"7myHk2cxDYfTZ9FwuDMZTacj77zqJE8FjcEz/7sEdAL1jCShikwAeHtvFG6AFkFWsbjpJkKkQLnVDdfB",
"2KeSnhdKi6yGL1VKRMxopQXTiZ8n5wFNUbyHUhjqcxbpQqKQI6phJuQSd92caioD367LWAbH5sNVxhzs",
"H+wRbF+ivisPltEZDP7IYebjOqeZZ9jXNGuNSBiP0iLGTQRnGrfwKrJyu7TQLa3/R+6dTrGPnumO2MfV",
"6chkqUG15hg92Xn67J+N3cK4fvqknoVxDTMwHCzy+C57NqVKE9d3zcZ9erz13+MnO+Pt0c03bgnLn5Yn",
"CuTVWgu1EVkkosLyGqnSSTQcbccwfbLz9FqjxNBuGUk7CfRqDer0SlPPNfnX2pcNJL5fYxyOiiyjiOdb",
"2YafqGLRwzcF34pq/KJK4QqsNkDaYIEPem8KnRd6H1XdS7cnkfwpLYziVXa89npsH2IxZ6RmVKV1v/rk",
"RAH5nhZafG8Nq+AauCYcZkIzC9IJRT9McLIbRZBrkgCNQSILeJHhYrA77jk7vdPBC5jkCGOO/6BzNsUV",
"1UxzjTsgOJSg2IxDfPL21R3Dvud2AyhCSV6ORk7evjILjJmESFvJ4jhmiR43Hs5yZr/0KNcECGpBs2Mh",
"EjxWpOCapQY0OJPpvaLYt59ubXm1uEz9U3SJ91BdczTROlfjwaDUIe6bfiSygRH2wGrT/8FBKSL1x7Pl",
"x2uRiuT1muzwAfPty+ejf45GL6j27Cj8FFn19uVzgq0cFlvEHxfQI8MR2S1mZLQ12iHD0Xhre7yzRX4+",
"OEbhUK1B4mj//+hA8IvjAi7eQXxxnBQXLyW7OKL64qjgj3vk9DQ+H/ZGl+TRr5RfvITJxQGVF7u5vDig",
"y4tfC37xa5Fe7BaziyPIL95E+uK1mF+8gOix6frk0vxvdDlu/Y+cni5++K7DrF5wFs5E6D5Eo4vcODF2",
"5ROCiLKbjY4iyskESottgEA5gTOmNGqlUgG38Xs3v+/EzRGt+H9a1C7gDTzAchiraZpTtHxBpzi9zuAa",
"5QwLgt84gtiMl1Fy1wxJwJZxaL5Zp5M781r9ex+yy6WYM3RtjAdmLRPKixIOizVS85neN7lLDjih7L9o",
"216yPzWRezlfj1BycrL/gixYmiJwZsBRY6w6e3a4kMXhcLTtU8X3EzrcEjquu0FOGy2xiIoMuL4NXNZD",
"pcs1/EpINmPIa2xjgFYysVBr+Fe27FtLdwOI/RskOhH7tR94VwM3tyN5XEpcjDMERIGcs8jrVLI0dtT4",
"TVA5AS+yCcjSLVoZmJhx2swZ9kf97WttS4sAb9pQQVRIppdHUQKZpXq30ImQ7GPFuQlQCbJ0iIJf3x13",
"nKDdw33yAZYGC647EKQElDZm1OSKjH9oBqspR6uKQvst/IWqQtJwN84YD48gkuCJu2wjQrER+gYStJkY",
"d+yERh+AxwPzJVMa7el81Z4zHKXysCys10xeZ7Jy9i9YBpfIMIQCkmWigMhQCBllKQqhyHMh9f/yRCjd",
"Z6Ie/zV+Qo7s94FzSSqHomp/ucpW18/BAZkckt0KFrjmjHI6M1qPx/YLZ7GU1QW5WICcFimhxos3/qcU",
"KYloTicsZQaqvSBlEThH0JG8m5sU0Cv7BRn1tzp0LxaLPjXN+kLOBm4MNXi1/3zv9dFeiH1wfzKdgm8x",
"QS+Yl5sjGPa3bHORA6c5C8bBtvnI+CaJQaZ1s/CvXCgPOKxtIYKjoiGZkFAmQQWhROUQYWgVu0CuXwpE",
"kQnVUdIwIYZ1YsUuVBoX+Q40SmpFV/fMilSzPHUT9wgwE1Y5Ldgeg6apo09IwgU3GqRCK8aiDWuJUnIb",
"6icRL0sIor5Gb8RMS6UeoKIKS6tiM7SGYZ5oN/RZw2MqZ6DLWLcRjy4SqPhZKm1UVKtqG6Pf0DJE+awe",
"jvD7++7Eu1LSZSNvXeYuWmnoKlMyYZzKpW/8dva5trK+Od9cK+Iqf2JlfVAoTTKDFmvO4lpr24URM/GN",
"c+ced8iXQW8qdcdAjzrv6A9z6mCXQFyavIy1LZdRa1Q4r/yR5nzoghgCbKhoFjTaGq7gj+Z5yiKD28Ef",
"ypqNdeC76fnFmvOKhnLTCTBZkX1/5xVNbq9Qe1OuK3/exKp4l0+4BQevWs51B30eCvdaBz0kLnDzOCJb",
"bkEw/r3jEPz+/vJ9L1Blhq7UulOnpDSdqRKmKniPo7nw+JzFl1bcKfji2EOQGcW1pUti25SZu6kUWZW7",
"I8cJU0RCJuagyEQ0PN4qvYK4Zlo18+pNmLSV7AszFzLLGBtJM9AglVn7dVm6ZiJLC0d26Wag4aqdAJOS",
"am+sXkPEq57c+86me9JlmdngLaRZCj4/0G4OK8MbQxa2ui26rHDMIB5w9YKZz0t8C1oymIPBQSwW3CAU",
"BYXLqgYs4dLwBCLBq8Pi0n/tuThbS8pVFQionhldUj6rXV1jONAOM5pWE6su5H4GfT94c1PcC+J6HfPI",
"06U752+kay0FRsZck71jOrMWEf0YXqV25zQtQFXh3zrPm01D0zn4PITFApQJQ63Npnx5e/rQM7tPIpmu",
"k+uZiK1LSqfaZd9nbA4crTVcxTPXL1SMR9Ci66od3Ewj3p5i5OMnUV3wz0O3SdiTPwuaMr0kj4bhcGvr",
"cZ+Y5Rh1Z/3JXw/3fu6RdzA5NDv38PXPldEyFP9ZgHEpHcF/tsjL6BnLiiwYD7e2egEGmPZf3Yxzl74D",
"25ckwGaJRlIkKIyQnV4RZJEgqzPKqqMliuGKJkZndJfSOGJYQ30brHejd8FiNK5fgtzFJ5D7U1pYENpp",
"CmWP5pgiis0yarf6XYia+ImqTxls2sa7lT7fqZCP0umNt1L3iMtD/Vtj1MTUHp9bBDiLalyxOstnxxjb",
"hj8qTaUOga9Vp2bgFq2Ngwc7xqPT0/iH8PQ0/scF/gf/+uHxo57348f/+M6TA+t6TltX+EAi0qBDpSXQ",
"LBifrwmiSgmVfIhbXlfQcyu1CTQjsNCs1RPf7KYLulREgdEEtkCBlDmVGOaQoq/Qz8RHlqbUpFaAhydH",
"g1hEavAOJoNfjo8PB7/YCQft2a60UMFzGiUQPrc5IM9Bkjm7Y+hWl0VAJqcBUUI5U9m1w1smhS+YyoVi",
"/sO9fR4j60FVBtuxViWiSGMyARIzlad0CTFhPGU2m0MxWCVUaxolJkt9M1JuUe9yzYh7d6mbumbMV1Tp",
"8MDZxDUHe2iqzGFot8aktKZ3taPBUSGlmFF9BSYMZKq0YdxGiCr7l1i5Zr31fP+C5bq5ynTu7QbH4Udb",
"Tz9lox86v3162w3/7W0rq8fH19iNqkSYWX+y1MqbvbvZu6t7d3ttesOEb2XEYeKGEt82Um8k9hkn+9NK",
"KOGRaSwkfvgao7gDEwWWO/dL7uHPgcAviwCc8clw5EnbSahlMaUsdTUUnlRKyXryCMWEwuihbE7quNCI",
"rNcW2OONpG4tqUbu76ocXZuzv4V75X0NXyd3KaG8mnENDbfN85VZurWZPiT0ilSfUa/VAU4JtAXTiSh0",
"lShrVm3eMP1ntLjLE6kKT42SgLXpvfKQ4ZdK4Xxati9KIPqwSfVtUn2bVN8m1bdJ9W1SfbdP9a3JjXnc",
"7mbNW2lNN9mvv1eY/gr4TCe3uCnlG7exHTeh+SY034Tm33JovonFv4FY/DnGmaVhqIvofUF5XnjLb/KU",
"RtC5RWOr9jgsKqtnvctcQlm6XGnj/Rd9cpw0qrfJVKSpWChsooAoDbkan/KhbVZf7CPTlM4Iq1wMU+GP",
"f2RUfqjHN2GZrXozd2lO+ciO1Mr+m0Izs5gqiV0W57tq81O+3ScvW7kHpqq7RI/Qme6RjGVgLjH1GoT2",
"COio//iUn/I9GiVmRdiXapGxqEcmhTaPUtgvcPeqHrJqzkSh7PptIa4N1gj6mCipiKYY24kUdztS2T/l",
"nQyFE9G9FCE5Dt1f1ds9VTkb78N7xakl43oF9hGMJmKbl7PXlxw3L/JcXezbubfmucCy5gTa0Yje32ot",
"L19d0l3LerfurVZwZZH+JbUKF8t99tAqFxt8v3XxYqkI1+Q026Wxg+o+qruxenVpY/v2arNEo67O2Ktu",
"lZZ7Ftsydcpj3O0Zc+/31Dfbp2xW2B4epeHSms0rxJ+kPD5Tnez9odh7WXodmmdUJyBXY+O/As1HIlt9",
"zOcO0L0xzhrIdsbxamwPHBfU9SAvW5b3QtZB0pa9PyRYdtJEJ6rBy0KmBHicC2YNUHmF1OayWpZ8TRro",
"t3A3+xjupjMhmU6yB0jbcwmGvTR9gMS9sOnrh0bWnn3X4AFSdlQ+avBAaYO4PmV7cDsB4ylVZOGBiB8k",
"/5xdCI/FB+DBX0nQWbg5ydycZG5OMjcnmZuTzM1J5ubSwubSwubSwuZ0dXNpYXNpYXNpYbN3N5URm+P3",
"zaWFTaHEQymUuOqcYvVIpBfAWZQWMWTl8Yh76ay/pNmV532F5KbqgbzJge8e7hO7AhLDlHGHYPNgJVNk",
"93C/R2iaigXiJ0qZoUoLUnBkmDbKPQFC55Sl9kcrXL7O3nPIRAyp/8ESN/tRDlFwq2DlLCxX2GH9+jPv",
"tWt9AOfD9jCtQsHPoGvRWLUerVbMlI9rlp93saAG9umecCLFB+Bhs6jA/9zdT6Zhq+7EsAli9JCy1hu3",
"CVXNGpkfiZYFmBITc2iJfbmoakGbdS4miWhuvGj39BKz7pd5grEuzzHTuLythavnrcZ1jy/ZpRw0KxU+",
"4Uh3/Uu9N34frHyA/gY/Z+I5f/U8yEQmbWn9NTDmzWNh36nwmmc417zKtLqmGu/1o5tdgAuZJ5Rf8Y7j",
"G9OgeuuN1u84Isbwn6ZijOtOTVaBSJ+j++V9+uuz4bekuH6p8d7gW715WWH3micP74xQ0WL71wBQtbqm",
"awCaMqW/Mf37iin9FWtfnKD46tQvCk3dVvsacHOhw6LxKyB+ZB8jlpjqXQdiU1v7uVBpdOlroRu/G/MV",
"4TKB6ENl4bjQX+6J0C+AzIa1RnPMv3dnsEUtyuuh+lW5CciXv7WTUCnSr8lLsGi9uY8wr9/yv7JuUdkn",
"+01EfbvfECAnCqZFat92F5xpIcvX3WOYFLMZ4zNvdF6+8v8Zq2E9v6vgEc6/PetdKfR2hxMPM5IvX9f3",
"yK2Z1VkqDRnCwkBPzv11pt0H/I9M285b+ueqmMQio4xf9suHjs8lzJjgl337AwGy4IP5MEAEOyrOPb/C",
"sJpocGfY7Y891Shcg+Q0bfxaAnE5itgen+fFJGURjq/qYes0RndIeymGcjqzlxYau6kuAXA6pLOSdT/h",
"UHdtfNbtX3K8sRr7ikejlrkxVpmj8wxk5LwCgrKXxcDl+8v/BAAA///wREgRYHkAAA==",
"H4sIAAAAAAAC/+xde3PbtrL/KhjezjQ5FSVLjpNzNdO513Wcxj1x4ontk86tc2cgciWiIQEWAKUotr/7",
"mQXAlwj5FSd1U/3TOhIei90f9oUFdB5EIssFB65VMD4PVJRARs2f+1IK+RZULrgC/IDGMdNMcJoeSZGD",
"1AxUMJ7SVEEviEFFkuX4fTC2fQnjUyEzip8RCbqQHGIyWRKdANk9OugHvSBvjHQeAHa701QxaMpS1R0y",
"ppquH1HLojPgbtWSYGciIaUaYqKFIdzQ2CNsSihf4nx6mUMwDsTkd4h0cNkLMlCKzgzL2iO/LDLKQwk0",
"ppPUjURcaxwJPtIsT3GwFywFwoUmU1HwuJ5Eacn4LLi87AUS/iiYhDgY/1bN+L5DzaWHvpZg3zGdHEkR",
"gVIQ47RqI+q/pqgNO1bk2CbqFVOaiCmZ4tdEJ1STBUggqoiw37RI0yWpBiETmAoJNSeIiKJCSohxAUxD",
"Zqb4TsI0GAf/NagVycBpkQHScQiaGsnUUKRS0qUfm60et0PHnshyCQlwxeZAMjdIC5l0IgpNqGEAYZwo",
"LaQTSBtKkyL6APog7vLw4DlyEHli25BIcE0ZZ3xmPsWh2wIuFEgV2tZd8faCSAKCbld3JzthGShNs5ws",
"EuDV+GRBFXHd2nONtkbb4dYwHO6cDEfj7Sfjnaf/F/QCy4FgjFsEQs0y8BECms66NOxzzfSSaDojUyFJ",
"RKMEyJymLDY8bc9/FtDhZBRtx09gZ/r0LPBNwzxcPeXsjwIIi4FrNmUgzVx+fsY78OxpBJPw2TM6Cp8M",
"d7bDybOYhsPps2g43JmMptORd151mqeCxuCZ/10COoF6RpJQRSYAvL03CjdAiyCrWNx0EyFSoNzqhutg",
"7FNJe4XSIqvhS5USETNaacF04ufJeUBTFO+RFIb6nEW6kCjkiGqYCbnEXTenmsrAt+sylsGJ+XCVMYcH",
"h/sE25eo78qDZXQGg99zmPm4zmnmGfY1zVojEsajtIhxE8FHjVt4FVm5XVroltb/PfdOp9gnz3TH7NPq",
"dGSy1KBac4ye7Dx99s/GbmFcP31Sz8K4hhkYDhZ5fJc9m1Klieu7ZuM+Pdn67/GTnfH26OYbt4TlT8tT",
"BfJqrYXaiCwSUWF5jVTpJBqOtmOYPtl5eq1RYmi3jKSdBHq1BnV6pannmvxr7csGEt+vMQ7HRZZRxPOt",
"bMNPVLHo4ZuCv4tq/KpK4QqsNkDaYIEPem8KnRf6AFXdC7cnkfwpLYziVXa89npsH2IxZ6RmVKV1v/rk",
"VAH5nhZafG8Nq+AauCYcZkIzC9IJRT9McLIbRZBrkgCNQSILeJHhYrA77jk7vdPBC5jkCGOO/6BzNg16",
"QQIswoXVvHN9Olg4kqDYjEN8+vbVHaO/PbsPFKEkL0cjp29fmXXGTEKkrYBxHLNSjzcPH3Nmv/To2AQI",
"KkOzcSESPFak4JqlBjs4k+m9ot+3n25teZW5TP1TdIn3UF1zNNE6V+PBoFQl7pt+JLKBkfnAKtX/wUEp",
"AvbHj8tP1wIWyes12eHD59sXe6N/jkbPqfZsLPwUWfX2xR7BVg6SLeJPCuiR4YjsFjMy2hrtkOFovLU9",
"3tkiPx+eoHCo1iBxtP9/dCj4xUkBF+8gvjhJiosXkl0cU31xXPDHPXJ2Fp8Pe6NL8ugXyi9ewOTikMqL",
"3VxeHNLlxS8Fv/ilSC92i9nFMeQXbyJ98VrML55D9Nh0fXJp/je6HLf+R87OFj9812FWL/gYzkToPkTb",
"i9w4NeblM2KJspsNkiLKyQRKw22AQDmBj0xpVE6lHm7j927u36mbI1pxA7WoPcEbOILlMFbhNKdouYRO",
"f3p9wjU6GhYEv3EEsRkvg+WuNZKALePQfLNONXfmtWr4PmSXSzFn6OEYR8waKJQXJRwWa6Tms8Bvcpcj",
"cEI5eN42weRgagL4cr4eoeT09OA5WbA0ReDMgKPGWPX57HAhi8PhaNuniu8ngrgldFx3g5w2WmIRFRlw",
"fRu4rIdKl2v4lZBsxpDX2MYArWRiodbwr2zZtwbvBhD7N0j0JQ5qd/CuBm5uR/J4lrgYZwiIAjlnkde3",
"ZGnsqPGboHICXmQTkKV3tDIwMeO0mTPsj/rb19qWFgHe7KGCqJBML4+jBDJL9W6hEyHZp4pzE6ASZOkX",
"Bb+8O+n4QrtHB+QDLA0WXHcgSAkobcyoSRkZN9EMVlOOVhWF9mv4kqpC0nA3zhgPjyGS4Am/bCNCsRH6",
"BhK0mRh37IRGH4DHA/MlUxrt6XzVnjMcpXK0LKzXTF4ntHL2L1gGl8gwhAKSZYKByFAIGWUpCqHIcyH1",
"//JEKN1noh7/NX5Cju33gXNJKoeian+5ylbXz8EBmRyS3QoWuOaMcjozWo/H9gtnsZTVBblYgJwWKaHG",
"mTduqBQpiWhOJyxlBqq9IGUROEfQkbybm0zQK/sFGfW3OnQvFos+Nc36Qs4Gbgw1eHWwt//6eD/EPrg/",
"mU7Bt5igF8zLzREM+1u2uciB05wF42DbfGR8k8Qg07pZ+FculAcc1rYQwVHRkExIKHOhglCicogwwopd",
"PNcvBaLIhOooaZgQwzqxYhcqjYt8BxoltaKre2ZFqlmeuol7BJiJrpwWbI9B09TRJyThghsNUqEVQ9KG",
"tUQpuQ31k4iXJQRRX6M3YqalUg9QUYWlVbGJWsMwT9Ab+qzhCZUz0GXI2whLFwlU/CyVNiqqVbWNQXBo",
"GaJ8Vg9H+O19d+JdKemykb4uUxitbHSVMJkwTuXSN347CV1bWd+cb64VcZVGsbI+LJQmmUGLNWdxrbXt",
"woiZ+MYpdI875EukN5W6Y6BHnXf0hzl8sEsgLltehtyWy6g1KpxX/khzPnRBDAE2VDQLGm0NV/BH8zxl",
"kcHt4HdlzcY68N30GGPNsUVDuekEmKzIvr9jiya3V6i9KdeVP31iVbxLK9yCg1ct57rzPg+F+63zHhIX",
"uHkckS23IBj/1nEIfnt/+b4XqDJRV2rdqVNSms5UCVMVvMfRXHh8zuJLK+4UfHHsEciM4trSJbFtygTe",
"VIqsSuGRk4QpIiETc1BkIhoeb5VlQVwzrZrp9SZM2kr2uZkLmWWMjaQZaJDKrP26ZF0zn6WFI7t0M9Bw",
"1U6AyUy1N1avIeJVT+59Z9M96bLMbPAW0iwFXx5oN4eV4Y0hC1vdFl1WOGYQD7h6wcznJb4FLRnMweAg",
"FgtuEIqCwmVVA5ZwaXgCkeDVmXHpv/ZcnK0l5aoKBFTPjC4pn9WurjEcaIcZTauJVRdyP4O+H7y5Ke4F",
"cb2OeeTp0h33N7K2lgIjY67J/gmdWYuIfgyvMrxzmhagqvBvnefNpqHpHHwZwmIByoSh1mZTvrw9feiZ",
"3SeRTNc59kzE1iWlU+2S8DM2B47WGq7imesXKsYjaNF11Q5uphFvTzHy8bOoLviXodvk7ckfBU2ZXpJH",
"w3C4tfW4T8xyjLqz/uQvR/s/98g7mBz1yNHrn832fbl/sFeZLkP3HwUYx9KR/UeLyIx+ZFmRBePh1lYv",
"wDDT/qubd+5SeWj7kgTYLNFIkASFcbLTLoIsEmR4Rll1zkQxaNHEaI7ughrnDWuob0P2bvQuWIwm9muQ",
"u/gMcn9KCwtFO02h7DkdU0SxWUbthr8LURM/UfVZg03eeDfUlzsi8lE6vfGG6p53eah/a0ybmNqzdIsA",
"Z1eNQ1bn+uwYY9vwR6Wp1CHwtUrVDNyitXH8YMd4dHYW/xCencX/uMD/4F8/PH7U8378+B/feTJhXf9p",
"6wpPSEQadKi0BJoF4/M1oVQpoZIPccv3MudwuFKbRjMCC81aPVHObrqgS0UUGE1gqxVImVmJYQ4pegz9",
"THxiaUpNggV4eHo8iEWkBu9gMnh5cnI0eGknHLRnu9JOBXs0SiDcs5kgz3GSOcFj6FyXFUEmswFRQjlT",
"2bXDWyaFz5nKhWL+I74DHiPrQVVm27FWJaJIYzIBEjOVp3QJMWE8ZTanQzFkJVRrGiUmV30zUm5R/HLN",
"iPt3KaK6ZsxXVOnw0FnGNcd7aKvMkWi34KS0qXe1psFxIaWYUX0FJgxkquRh3EaIKvuXWLlmvfV8/4Ll",
"urnKpO7tBsfhR1tPP2ejHznvfXrbDf/321ZWj4+vsRtVvTCzXmWplTd7d7N3V/fu9tokhwniyrjDRA8l",
"vm283kjvM04OppVQwmPTWEj88DXGcocmFix37tfcw18CgV8XATjjk+HIk7yTUMtiSlnqKik8CZWS9eQR",
"igmF0UPZnNbRoRFZry2wxxtJ3VpSjQzgVZm6Nmd/DffLyxu+Tu6GQnlP4xoabpvtK3N1a/N9SOgVCT+j",
"XqtjnBJoC6YTUegqXdYs4bxhEtBocZctUhWeGoUBa5N85VHDy0rhfF7OL0og+rBJ+G0SfpuE3ybht0n4",
"bRJ+d034rcmQeZzvZv1baVM3ObC/VrD+CvhMJ7e4POUbt7EdNwH6JkDfBOh/5wB9E5H/DSLyPYw2S8NQ",
"F9T7QvO88Jbi5CmNoHOjxlbwcVhUVs96l7mEsoy50sYHz/vkJGlUcpOpSFOxUNhEAVEacjU+40PbrL7r",
"R6YpnRFWuRim2h//yKj8UI9vgjNbAWfu1ZzxkR2pdQZgis7MYqpUdlmo7yrPz/h2n7xoZSCYqu4VPUJn",
"ukcyloG50NRrENojoKP+4zN+xvdplJgVYV+qRcaiHpkU2rxTYb/A3at6yKo5E4Wy67dFuTZkI+hjoqQi",
"mmKEJ1Lc7Uhl/4x38hRORPdSkOQ4dH8VcPdU8Wy8D+91p5aM6xXYdzGaiG3e115ffty81HN14W/nDpvn",
"Msuac2hHI3p/q3W9fHVJdy3x3bq3usGVRfqX1CpiLPfZQ6tibPD91oWMpSJck9lsl8kOqrup7vbq1WWO",
"7ZuszUKNukZjv7phWu5ZbMvUGY9xt2fMPelTX3afsllhe3iUhktuNq8Tf5by+EI1s/eHYu/F6XVonlGd",
"gFyNjf8MNB+LbPV9nztA98Y4ayDbGcersT1wXFDXg7xsWd4RWQdJWwL/kGDZSROdqgYvC5kS4HEumDVA",
"5XVSm8tqWfI1aaBfw93sU7ibzoRkOskeIG17Egx7afoAiXtuk9gPjax9+8bBA6TsuHzg4IHSBnF91vbg",
"dgLGU6rIwkMRP0j+ObsQnogPwIM/k6CP4eY8c3OeuTnP3Jxnbs4zN+eZmwsMmwsMmwsMmzPWzQWGzQWG",
"zQWGzd7d1Eds6iM2Fxg25RIPq1ziqtOK1YORXgAfo7SIISsPSdzbZ/0lza489SskN7UP5E0OfPfogNgV",
"kBimjDsEmycsmSK7Rwc9QtNULBA/UcoMVVqQgiPDtFHuCRA6pyy1v2bhsnb2zkMmYkj9T5i42Y9ziIJb",
"BSsfw3KFHdavP/leu9YHcEpsj9QqFPwMuhaNVevRat1M+dxm+XkXC2pgH/MJJ1J8AB42Swv8D+D9ZBq2",
"qk8MmyBGDylrvXqbUNWslPmRaFmAKTQxR5fYl4uqIrRZ7WJSieb2i3aPMTHrfplHGesiHTONy95auHpe",
"b1z3HJNdymGzXuEzDnbXv9174xfDypfpb/A7J55TWM8TTWTSltafA2PePBz2nQ2veZhzzTtNq2uq8V4/",
"w9kFuJB5QvkVLzu+MQ2q199o/bIjYgz/aerGuO5UZhWI9Dm6X97HwL4YfkuK67cb7w2+1SuYFXaveQTx",
"zggVLbZ/CwBVq2u6BqApU/pvpn9fMaW/Ye2LExTfnPpFoanbal8Dbi50WDR+HsSP7BPEElO960BsKmy/",
"FCqNLn0tdOMHZb4hXCYQfagsHBf66z0a+hWQ2bDWaI759+4ktqhFeT1Uvyk3Afnyl3YSKkX6LXkJFq03",
"9xHm9ev+V1YvKvuIv4mob/erAuRUwbRI7WvvgjMtZPneewyTYjZjfOaNzst3/79gTaznlxY8wvm3Z70r",
"5d7ucOJhRvLle/seuTWzOkulIUNYGOjJub/atPuk/7Fp23ld/1wVk1hklPHLfvn08bmEGRP8sm9/MkAW",
"fDAfBohgR8W553cZVhMN7gy7/bGnJoVrkJymjd9PIC5HEdvj87yYpCzC8VU9bJ3G6A5pr8ZQTmf26kJj",
"N9UlAE6HdFay7kcd6q6Nz7r9S443VmNf9GhUNDfGKnN0noGMnFdAUPayGLh8f/mfAAAA////QOU7eXkA",
"AA==",
}
// GetSwagger returns the content of the embedded swagger specification file

View File

@@ -18,6 +18,7 @@ const (
const (
Auto OutputImageFormat = "auto"
Avif OutputImageFormat = "avif"
Heic OutputImageFormat = "heic"
Jpeg OutputImageFormat = "jpeg"
Png OutputImageFormat = "png"
Same OutputImageFormat = "same"
@@ -158,7 +159,7 @@ type UploadFilesMultipartBody struct {
// GetFileParams defines parameters for GetFile.
type GetFileParams struct {
// Q Image quality (1-100). Only applies to JPEG, WebP and PNG files
// Q Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
Q *int `form:"q,omitempty" json:"q,omitempty"`
// H Maximum height to resize image to while maintaining aspect ratio. Only applies to image files
@@ -191,7 +192,7 @@ type GetFileParams struct {
// GetFileMetadataHeadersParams defines parameters for GetFileMetadataHeaders.
type GetFileMetadataHeadersParams struct {
// Q Image quality (1-100). Only applies to JPEG, WebP and PNG files
// Q Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
Q *int `form:"q,omitempty" json:"q,omitempty"`
// H Maximum height to resize image to while maintaining aspect ratio. Only applies to image files
@@ -257,7 +258,7 @@ type GetFileWithPresignedURLParams struct {
// XId Use presignedurl endpoint to generate this automatically
XId string `form:"x-id" json:"x-id"`
// Q Image quality (1-100). Only applies to JPEG, WebP and PNG files
// Q Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
Q *int `form:"q,omitempty" json:"q,omitempty"`
// H Maximum height to resize image to while maintaining aspect ratio. Only applies to image files

View File

@@ -28,6 +28,7 @@ const (
const (
Auto OutputImageFormat = "auto"
Avif OutputImageFormat = "avif"
Heic OutputImageFormat = "heic"
Jpeg OutputImageFormat = "jpeg"
Png OutputImageFormat = "png"
Same OutputImageFormat = "same"
@@ -168,7 +169,7 @@ type UploadFilesMultipartBody struct {
// GetFileParams defines parameters for GetFile.
type GetFileParams struct {
// Q Image quality (1-100). Only applies to JPEG, WebP and PNG files
// Q Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
Q *int `form:"q,omitempty" json:"q,omitempty"`
// H Maximum height to resize image to while maintaining aspect ratio. Only applies to image files
@@ -201,7 +202,7 @@ type GetFileParams struct {
// GetFileMetadataHeadersParams defines parameters for GetFileMetadataHeaders.
type GetFileMetadataHeadersParams struct {
// Q Image quality (1-100). Only applies to JPEG, WebP and PNG files
// Q Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
Q *int `form:"q,omitempty" json:"q,omitempty"`
// H Maximum height to resize image to while maintaining aspect ratio. Only applies to image files
@@ -267,7 +268,7 @@ type GetFileWithPresignedURLParams struct {
// XId Use presignedurl endpoint to generate this automatically
XId string `form:"x-id" json:"x-id"`
// Q Image quality (1-100). Only applies to JPEG, WebP and PNG files
// Q Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files
Q *int `form:"q,omitempty" json:"q,omitempty"`
// H Maximum height to resize image to while maintaining aspect ratio. Only applies to image files

View File

@@ -283,7 +283,7 @@ func TestGetFileMetadataHeaders(t *testing.T) { //nolint:maintidx
"Accept-Ranges": []string{"bytes"},
"Cache-Control": []string{"max-age=3600"},
"Content-Disposition": []string{`inline; filename="nhost.jpg"`},
"Content-Length": []string{"8709"},
"Content-Length": []string{"8963"},
"Content-Type": []string{"image/jpeg"},
"Date": []string{"Mon, 21 Jul 2025 13:24:53 GMT"},
"Etag": []string{`"78b676e65ebc31f0bb1f2f0d05098572"`},

View File

@@ -399,7 +399,7 @@ func TestGetFile(t *testing.T) { //nolint:maintidx
"Accept-Ranges": []string{"bytes"},
"Cache-Control": []string{"max-age=3600"},
"Content-Disposition": []string{`inline; filename="nhost.jpg"`},
"Content-Length": []string{"8709"},
"Content-Length": []string{"8963"},
"Content-Type": []string{"image/jpeg"},
"Date": []string{"Mon, 21 Jul 2025 13:24:53 GMT"},
"Etag": []string{`"78b676e65ebc31f0bb1f2f0d05098572"`},

View File

@@ -475,7 +475,7 @@ func TestGetFileWithPresignedURL(t *testing.T) { //nolint:cyclop,maintidx
"Accept-Ranges": []string{"bytes"},
"Cache-Control": []string{"max-age=30"},
"Content-Disposition": []string{`inline; filename="nhost.jpg"`},
"Content-Length": []string{"8709"},
"Content-Length": []string{"8963"},
"Content-Type": []string{"image/jpeg"},
"Date": []string{"Mon, 21 Jul 2025 13:24:53 GMT"},
"Etag": []string{`"78b676e65ebc31f0bb1f2f0d05098572"`},

View File

@@ -37,6 +37,8 @@ func mimeTypeToImageType(mimeType string) (image.ImageType, *APIError) {
return image.ImageTypeJPEG, nil
case "image/avif":
return image.ImageTypeAVIF, nil
case "image/heic", "image/heif":
return image.ImageTypeHEIC, nil
default:
return 0, BadDataError(
fmt.Errorf( //nolint: err113
@@ -73,6 +75,8 @@ func chooseImageFormat( //nolint: cyclop
return originalFormat, image.ImageTypeJPEG, nil
case api.Avif:
return originalFormat, image.ImageTypeAVIF, nil
case api.Heic:
return originalFormat, image.ImageTypeHEIC, nil
case api.Auto:
for _, acceptHeader := range acceptHeader {
acceptedTypes := strings.Split(acceptHeader, ",")
@@ -85,6 +89,8 @@ func chooseImageFormat( //nolint: cyclop
return originalFormat, image.ImageTypeJPEG, nil
case slices.Contains(acceptedTypes, "image/png"):
return originalFormat, image.ImageTypePNG, nil
case slices.Contains(acceptedTypes, "image/heic"):
return originalFormat, image.ImageTypeHEIC, nil
}
}
@@ -92,8 +98,11 @@ func chooseImageFormat( //nolint: cyclop
default:
return 0, 0, BadDataError(
//nolint: err113
fmt.Errorf("format must be one of: same, webp, png, jpeg, avif, auto. Got: %s", format),
"format must be one of: same, webp, png, jpeg, avif, auto. Got: "+string(format),
fmt.Errorf(
"format must be one of: same, webp, png, jpeg, avif, heic, auto. Got: %s",
format,
),
"format must be one of: same, webp, png, jpeg, avif, heic, auto. Got: "+string(format),
)
}
}

View File

@@ -148,7 +148,7 @@ paths:
schema:
$ref: '#/components/schemas/RFC2822Date'
- name: q
description: "Image quality (1-100). Only applies to JPEG, WebP and PNG files"
description: "Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files"
in: query
schema:
type: integer
@@ -332,7 +332,7 @@ paths:
schema:
$ref: '#/components/schemas/RFC2822Date'
- name: q
description: "Image quality (1-100). Only applies to JPEG, WebP and PNG files"
description: "Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files"
in: query
schema:
type: integer
@@ -614,7 +614,7 @@ paths:
schema:
$ref: '#/components/schemas/RFC2822Date'
- name: q
description: "Image quality (1-100). Only applies to JPEG, WebP and PNG files"
description: "Image quality (1-100). Only applies to JPEG, WebP, PNG and HEIC files"
in: query
schema:
type: integer
@@ -1178,4 +1178,5 @@ components:
- webp
- png
- avif
- heic
example: same

View File

@@ -1,14 +1,11 @@
package image
import (
"bytes"
"fmt"
"io"
"math"
"sync"
"sync/atomic"
"github.com/davidbyttow/govips/v2/vips"
"github.com/cshum/vipsgen/vips"
)
const (
@@ -24,6 +21,7 @@ const (
ImageTypePNG
ImageTypeWEBP
ImageTypeAVIF
ImageTypeHEIC
)
type Options struct {
@@ -54,6 +52,8 @@ func (o Options) FormatMimeType() string {
return "image/webp"
case ImageTypeAVIF:
return "image/avif"
case ImageTypeHEIC:
return "image/heic"
}
return ""
@@ -69,6 +69,8 @@ func (o Options) FileExtension() string {
return "webp"
case ImageTypeAVIF:
return "avif"
case ImageTypeHEIC:
return "heic"
}
return ""
@@ -76,12 +78,10 @@ func (o Options) FileExtension() string {
type Transformer struct {
workers chan struct{}
pool sync.Pool
}
func NewTransformer() *Transformer {
if atomic.CompareAndSwapInt32(&initialized, 0, 1) {
vips.LoggingSettings(nil, vips.LogLevelWarning)
vips.Startup(nil)
}
@@ -92,11 +92,6 @@ func NewTransformer() *Transformer {
return &Transformer{
workers: workers,
pool: sync.Pool{
New: func() any {
return new(bytes.Buffer)
},
},
}
}
@@ -104,35 +99,67 @@ func (t *Transformer) Shutdown() {
vips.Shutdown()
}
func export(image *vips.ImageRef, opts Options) ([]byte, error) {
var (
b []byte
err error
)
switch opts.Format {
case ImageTypeJPEG:
ep := vips.NewJpegExportParams()
ep.Quality = opts.Quality
b, _, err = image.ExportJpeg(ep)
case ImageTypePNG:
ep := vips.NewPngExportParams()
b, _, err = image.ExportPng(ep)
case ImageTypeWEBP:
ep := vips.NewWebpExportParams()
ep.Quality = opts.Quality
b, _, err = image.ExportWebp(ep)
case ImageTypeAVIF:
ep := vips.NewAvifExportParams()
ep.Quality = opts.Quality
ep.Effort = 0
b, _, err = image.ExportAvif(ep)
}
return b, err //nolint: wrapcheck
type readCloserAdapter struct {
io.Reader
}
func processImage(image *vips.ImageRef, opts Options) error {
func (r readCloserAdapter) Close() error {
if closer, ok := r.Reader.(io.Closer); ok {
return closer.Close() //nolint: wrapcheck
}
return nil
}
type writeCloserAdapter struct {
io.Writer
}
func (w writeCloserAdapter) Close() error {
if closer, ok := w.Writer.(io.Closer); ok {
return closer.Close() //nolint: wrapcheck
}
return nil
}
func exportToTarget(image *vips.Image, target *vips.Target, opts Options) error {
quality := opts.Quality
if quality == 0 {
quality = 75
}
var err error
switch opts.Format {
case ImageTypeJPEG:
jpegOpts := vips.DefaultJpegsaveTargetOptions()
jpegOpts.Q = quality
err = image.JpegsaveTarget(target, jpegOpts)
case ImageTypePNG:
pngOpts := vips.DefaultPngsaveTargetOptions()
err = image.PngsaveTarget(target, pngOpts)
case ImageTypeWEBP:
webpOpts := vips.DefaultWebpsaveTargetOptions()
webpOpts.Q = quality
err = image.WebpsaveTarget(target, webpOpts)
case ImageTypeAVIF:
heifOpts := vips.DefaultHeifsaveTargetOptions()
heifOpts.Q = quality
heifOpts.Compression = vips.HeifCompressionAv1
err = image.HeifsaveTarget(target, heifOpts)
case ImageTypeHEIC:
heifOpts := vips.DefaultHeifsaveTargetOptions()
heifOpts.Q = quality
heifOpts.Compression = vips.HeifCompressionHevc
err = image.HeifsaveTarget(target, heifOpts)
default:
return fmt.Errorf("unsupported format: %d", opts.Format) //nolint: err113
}
return err //nolint: wrapcheck
}
func imageResize(image *vips.Image, opts Options) error {
if opts.Width > 0 || opts.Height > 0 {
width := opts.Width
height := opts.Height
@@ -145,13 +172,33 @@ func processImage(image *vips.ImageRef, opts Options) error {
height = int((float64(width) / float64(image.Width())) * float64(image.Height()))
}
if err := image.Thumbnail(width, height, vips.InterestingCentre); err != nil {
thumbnailOpts := vips.DefaultThumbnailImageOptions()
thumbnailOpts.Crop = vips.InterestingCentre
thumbnailOpts.Height = height
if err := image.ThumbnailImage(width, thumbnailOpts); err != nil {
return fmt.Errorf("failed to thumbnail: %w", err)
}
}
return nil
}
func imagePipeline(image *vips.Image, opts Options) error {
if err := imageResize(image, opts); err != nil {
return err
}
// Auto-rotate when converting formats to ensure correct display
if opts.FormatChanged() {
if err := image.Autorot(nil); err != nil {
return fmt.Errorf("failed to auto-rotate: %w", err)
}
}
// Apply blur if specified
if opts.Blur > 0 {
if err := image.GaussianBlur(float64(opts.Blur)); err != nil {
if err := image.Gaussblur(float64(opts.Blur), nil); err != nil {
return fmt.Errorf("failed to blur: %w", err)
}
}
@@ -161,49 +208,37 @@ func processImage(image *vips.ImageRef, opts Options) error {
func (t *Transformer) Run(
orig io.Reader,
length uint64,
length uint64, //nolint:revive
modified io.Writer,
opts Options,
) error {
// this is to avoid processing too many images at the same time in order to save memory
// Limit concurrent processing to avoid processing too many images at the same time
<-t.workers
defer func() { t.workers <- struct{}{} }()
buf, _ := t.pool.Get().(*bytes.Buffer)
defer t.pool.Put(buf)
defer buf.Reset()
// Create streaming source from io.Reader
// This avoids loading the entire file into a buffer!
source := vips.NewSource(readCloserAdapter{orig})
defer source.Close()
if length > math.MaxUint32 {
panic("length is too big")
}
if l := int(length); buf.Len() < l {
buf.Grow(l)
}
_, err := io.Copy(buf, orig)
image, err := vips.NewImageFromSource(source, nil)
if err != nil {
panic(err)
return fmt.Errorf("failed to load image from source: %w", err)
}
image, err := vips.NewImageFromBuffer(buf.Bytes())
if err != nil {
return fmt.Errorf("failed to load image: %w", err)
}
defer image.Close()
if err := processImage(image, opts); err != nil {
// Apply additional processing (auto-rotate, blur)
if err := imagePipeline(image, opts); err != nil {
return err
}
b, err := export(image, opts)
if err != nil {
return fmt.Errorf("failed to export: %w", err)
}
// Export with streaming target
target := vips.NewTarget(writeCloserAdapter{modified})
defer target.Close()
if _, err = modified.Write(b); err != nil {
return fmt.Errorf("failed to write: %w", err)
if err := exportToTarget(image, target, opts); err != nil {
return fmt.Errorf("failed to export: %w", err)
}
return nil

View File

@@ -24,7 +24,7 @@ func TestManipulate(t *testing.T) {
{
name: "jpg",
filename: "testdata/nhost.jpg",
sum: "0a3f081bd296958cfc99297ee9fb4cc2e5a1b22bebfded81c6e00e25caf84f36",
sum: "3cffeb9c31e624970f6b6e440213a9805c4ecf56052268631d1add81f9fde37b",
size: 33399,
options: image.Options{
Height: 100,
@@ -37,45 +37,78 @@ func TestManipulate(t *testing.T) {
{
name: "jpg",
filename: "testdata/nhost.jpg",
sum: "cd9857da2c40b6c46d39abd0f18def2c9879c2a06a1702c131c17b2bfdb43268",
sum: "131c9a8f0dfb0aa345bb498a314da97711b5f3c146e572c02d62d09ace22db7b",
size: 33399,
options: image.Options{Width: 300, Height: 100, Blur: 2, Format: image.ImageTypeJPEG},
},
{
name: "png",
filename: "testdata/nhost.png",
sum: "d538212aa74ad1d17261bc2126e60964e6d2dc1c7898ea3b9f9bd3b5bc94b380",
sum: "ac7da45c3a994e50fdbc25123992b31116d32f20dac2c5436d2d6fdbfd319853",
size: 68307,
options: image.Options{Width: 300, Height: 100, Blur: 2, Format: image.ImageTypePNG},
},
{
name: "webp",
filename: "testdata/nhost.webp",
sum: "720eebe382c26b5fb8abf8552f282317074a4c9f6467aa8a60bb93a20f55e063",
sum: "e9e2342f901aa447ebd32ee4ef5a6f89f007f8d692350ec45b7f02b727cc043b",
size: 17784,
options: image.Options{Width: 300, Height: 100, Blur: 2, Format: image.ImageTypeWEBP},
},
{
name: "jpg only blur",
filename: "testdata/nhost.jpg",
sum: "0b038c3afbe8a848974874aad4fb11983d45ab84d9113eb4260c4ed34d2d03d6",
sum: "e359c19b3a708cfce10577d7b67f7372ddc57b478dcfc5c34b7d49e63bd13a86",
size: 33399,
options: image.Options{Blur: 2, Format: image.ImageTypeJPEG},
},
{
name: "webp to avif",
filename: "testdata/nhost.webp",
sum: "e0a5fb177567987b16b379ce2f263cc319c4f7f5e7145c9ae81682b02c7a9f6d",
sum: "44ae1c37353bcd8db71df35120be7c6c22435d258ccb3248662bd4fd181b7cf0",
size: 17784,
options: image.Options{Width: 300, Height: 100, Blur: 2, Format: image.ImageTypeAVIF},
},
{
name: "jpeg to avif, no image manipulation",
filename: "testdata/nhost.jpg",
sum: "cd3f0137250dcc145ee9f1e63733c30bccfc6ad1c058b2be719ea9e8148029db",
sum: "3c03519a14713701db1eaab77dae305b5484f20baacac9625294dd6952446062",
size: 17784,
options: image.Options{Format: image.ImageTypeAVIF},
},
{
name: "heic",
filename: "testdata/nhost.heic",
sum: "621a8cac7292d02342e699b11db69b1b5b6f55cb09ce06006a53f9cff7727a98",
size: 12968,
options: image.Options{
Width: 300,
Height: 100,
Blur: 2,
Format: image.ImageTypeHEIC,
Quality: 50,
},
},
{
name: "jpeg to heic",
filename: "testdata/nhost.jpg",
sum: "c564a40516e3c6f39a8b5d1ba934f3007512d9766630fd512a4c268a0c0b4cb8",
size: 33399,
options: image.Options{
Width: 300,
Height: 100,
Blur: 2,
Format: image.ImageTypeHEIC,
Quality: 50,
},
},
{
name: "webp to heic",
filename: "testdata/nhost.webp",
sum: "f1d3ebb85e83f70b4d283b30e5c2f765a9f8847b7dceae3d40907aab16b93004",
size: 17784,
options: image.Options{Width: 300, Height: 100, Blur: 2, Format: image.ImageTypeHEIC},
},
}
transformer := image.NewTransformer()

Binary file not shown.

21
vendor/github.com/cshum/vipsgen/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2025 Adrian Shum and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

100
vendor/github.com/cshum/vipsgen/pointer/pointer.go generated vendored Normal file
View File

@@ -0,0 +1,100 @@
package pointer
// #include <stdlib.h>
import "C"
import (
"sync"
"unsafe"
)
const blockSize = 1024
var (
mutex sync.RWMutex
store = map[unsafe.Pointer]interface{}{}
free []unsafe.Pointer
blocks []unsafe.Pointer
)
func allocMem() {
mem := C.malloc(blockSize)
if mem == nil {
panic("can't allocate memory block for C pointers")
}
blocks = append(blocks, mem)
for i := 0; i < blockSize; i++ {
p := unsafe.Pointer(uintptr(mem) + uintptr(blockSize-1-i))
free = append(free, p)
}
}
func getPtr() unsafe.Pointer {
// Generate real fake C pointer.
// This pointer will not store any data, but will be used for indexing
// purposes. Since Go doesn't allow to cast dangling pointer to
// unsafe.Pointer, we do really allocate memory. Why we need indexing? Because
// Go doest allow C code to store pointers to Go data.
if len(free) == 0 {
allocMem()
}
n := len(free) - 1
p := free[n]
free = free[:n]
return p
}
// Save an object in the storage and return an index pointer to it.
func Save(v interface{}) unsafe.Pointer {
if v == nil {
return nil
}
mutex.Lock()
ptr := getPtr()
store[ptr] = v
mutex.Unlock()
return ptr
}
// Restore an object from the storage by its index pointer.
func Restore(ptr unsafe.Pointer) (v interface{}) {
if ptr == nil {
return nil
}
mutex.RLock()
v = store[ptr]
mutex.RUnlock()
return
}
// Unref removes an object from the storage and returns the index pointer to the
// pool for reuse.
func Unref(ptr unsafe.Pointer) {
if ptr == nil {
return
}
mutex.Lock()
if _, ok := store[ptr]; ok {
delete(store, ptr)
free = append(free, ptr)
}
mutex.Unlock()
}
// Clear storage and free all memory
func Clear() {
mutex.Lock()
for p := range store {
delete(store, p)
}
free = nil
for _, p := range blocks {
C.free(p)
}
blocks = nil
mutex.Unlock()
}

76
vendor/github.com/cshum/vipsgen/vips/callback.go generated vendored Normal file
View File

@@ -0,0 +1,76 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
package vips
import "C"
import (
"github.com/cshum/vipsgen/pointer"
"io"
"reflect"
"unsafe"
)
//export goLoggingHandler
func goLoggingHandler(domain *C.char, level C.int, message *C.char) {
log(C.GoString(domain), LogLevel(level), C.GoString(message))
}
//export goSourceRead
func goSourceRead(
ptr unsafe.Pointer, buffer unsafe.Pointer, size C.longlong,
) C.longlong {
src, ok := pointer.Restore(ptr).(*Source)
if !ok {
return -1
}
sh := &reflect.SliceHeader{
Data: uintptr(buffer),
Len: int(size),
Cap: int(size),
}
buf := *(*[]byte)(unsafe.Pointer(sh))
n, err := src.reader.Read(buf)
if err == io.EOF {
return C.longlong(n)
} else if err != nil {
return -1
}
return C.longlong(n)
}
//export goSourceSeek
func goSourceSeek(
ptr unsafe.Pointer, offset C.longlong, whence int,
) C.longlong {
src, ok := pointer.Restore(ptr).(*Source)
if ok && src.seeker != nil {
switch whence {
case io.SeekStart, io.SeekCurrent, io.SeekEnd:
if n, err := src.seeker.Seek(int64(offset), whence); err == nil {
return C.longlong(n)
}
}
}
return -1
}
//export goTargetWrite
func goTargetWrite(
ptr unsafe.Pointer, buffer unsafe.Pointer, size C.longlong,
) C.longlong {
target, ok := pointer.Restore(ptr).(*Target)
if !ok {
return -1
}
sh := &reflect.SliceHeader{
Data: uintptr(buffer),
Len: int(size),
Cap: int(size),
}
buf := *(*[]byte)(unsafe.Pointer(sh))
n, err := target.writer.Write(buf)
if err != nil {
return -1
}
return C.longlong(n)
}

48
vendor/github.com/cshum/vipsgen/vips/connection.c generated vendored Normal file
View File

@@ -0,0 +1,48 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
#include "connection.h"
static gint64 go_read(VipsSourceCustom *source_custom, void *buffer, gint64 length, void* ptr)
{
return goSourceRead(ptr, buffer, length);
}
static gint64 go_seek(VipsSourceCustom *source_custom, gint64 offset, int whence, void* ptr)
{
return goSourceSeek(ptr, offset, whence);
}
static gint64 go_write(VipsTargetCustom *target_custom, void *buffer, gint64 length, void* ptr)
{
return goTargetWrite(ptr, buffer, length);
}
VipsSourceCustom * create_go_custom_source(void* ptr)
{
VipsSourceCustom * source_custom = vips_source_custom_new();
g_signal_connect(source_custom, "read", G_CALLBACK(go_read), ptr);
return source_custom;
}
VipsSourceCustom * create_go_custom_source_with_seek(void* ptr)
{
VipsSourceCustom * source_custom = vips_source_custom_new();
g_signal_connect(source_custom, "read", G_CALLBACK(go_read), ptr);
g_signal_connect(source_custom, "seek", G_CALLBACK(go_seek), ptr);
return source_custom;
}
VipsTargetCustom * create_go_custom_target(void* ptr)
{
VipsTargetCustom * target_custom = vips_target_custom_new();
g_signal_connect(target_custom, "write", G_CALLBACK(go_write), ptr);
return target_custom;
}
void clear_source(VipsSourceCustom **source_custom) {
if (G_IS_OBJECT(*source_custom)) g_clear_object(source_custom);
}
void clear_target(VipsTargetCustom **target_custom) {
if (G_IS_OBJECT(*target_custom)) g_clear_object(target_custom);
}

97
vendor/github.com/cshum/vipsgen/vips/connection.go generated vendored Normal file
View File

@@ -0,0 +1,97 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
package vips
// #include "connection.h"
import "C"
import (
"fmt"
"github.com/cshum/vipsgen/pointer"
"io"
"sync"
"unsafe"
)
// Source contains a libvips VipsSourceCustom and manages its lifecycle.
type Source struct {
reader io.ReadCloser
seeker io.Seeker
src *C.VipsSourceCustom
ptr unsafe.Pointer
lock sync.Mutex
}
// NewSource creates Source from reader
func NewSource(reader io.ReadCloser) *Source {
Startup(nil)
s := &Source{reader: reader}
seeker, ok := reader.(io.ReadSeeker)
if ok {
s.seeker = seeker
s.ptr = pointer.Save(s)
s.src = C.create_go_custom_source_with_seek(s.ptr)
} else {
s.ptr = pointer.Save(s)
s.src = C.create_go_custom_source(s.ptr)
}
return s
}
// Close source
func (s *Source) Close() {
if s == nil {
return
}
s.lock.Lock()
if s.ptr != nil {
C.clear_source(&s.src)
pointer.Unref(s.ptr)
s.ptr = nil
s.lock.Unlock()
if s.reader != nil {
_ = s.reader.Close()
s.reader = nil
}
log("vipsgen", LogLevelDebug, fmt.Sprintf("closing source %p", s))
} else {
s.lock.Unlock()
}
}
// Target contains a libvips VipsTargetCustom and manages its lifecycle.
type Target struct {
writer io.WriteCloser
target *C.VipsTargetCustom
ptr unsafe.Pointer
lock sync.Mutex
}
// NewTarget creates Target from writer
func NewTarget(writer io.WriteCloser) *Target {
Startup(nil)
t := &Target{writer: writer}
t.ptr = pointer.Save(t)
t.target = C.create_go_custom_target(t.ptr)
return t
}
// Close target
func (t *Target) Close() {
if t == nil {
return
}
t.lock.Lock()
if t.ptr != nil {
C.clear_target(&t.target)
pointer.Unref(t.ptr)
t.ptr = nil
t.lock.Unlock()
if t.writer != nil {
_ = t.writer.Close()
t.writer = nil
}
log("vipsgen", LogLevelDebug, fmt.Sprintf("closing target %p", t))
} else {
t.lock.Unlock()
}
}

19
vendor/github.com/cshum/vipsgen/vips/connection.h generated vendored Normal file
View File

@@ -0,0 +1,19 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
#include <stdlib.h>
#include <vips/vips.h>
extern long long goSourceRead(void*, void *, long long);
extern long long goSourceSeek(void*, long long, int);
extern long long goTargetWrite(void*, void *, long long);
static gint64 go_read(VipsSourceCustom *source_custom, void *buffer, gint64 length, void* ptr);
static gint64 go_seek(VipsSourceCustom *source_custom, gint64 offset, int whence, void* ptr);
static gint64 go_write(VipsTargetCustom *target_custom, void *buffer, gint64 length, void* ptr);
VipsSourceCustom * create_go_custom_source(void* ptr);
VipsSourceCustom * create_go_custom_source_with_seek(void* ptr);
VipsTargetCustom * create_go_custom_target(void* ptr);
void clear_source(VipsSourceCustom **source_custom);
void clear_target(VipsTargetCustom **target_custom);

10776
vendor/github.com/cshum/vipsgen/vips/image.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

818
vendor/github.com/cshum/vipsgen/vips/types.go generated vendored Normal file
View File

@@ -0,0 +1,818 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
package vips
// #include <vips/vips.h>
import "C"
import (
"strings"
"unsafe"
)
// ImageType represents an image type
type ImageType string
// ImageType enum
const (
ImageTypeUnknown ImageType = "unknown"
ImageTypeJpeg ImageType = "jpeg"
ImageTypeGif ImageType = "gif"
ImageTypePng ImageType = "png"
ImageTypeWebp ImageType = "webp"
ImageTypeHeif ImageType = "heif"
ImageTypeSvg ImageType = "svg"
ImageTypeTiff ImageType = "tiff"
ImageTypeJp2k ImageType = "jp2k"
ImageTypeAvif ImageType = "avif"
ImageTypePdf ImageType = "pdf"
ImageTypeBmp ImageType = "bmp"
ImageTypeMagick ImageType = "magick"
ImageTypeAnalyze ImageType = "analyze"
ImageTypeCsv ImageType = "csv"
ImageTypeDz ImageType = "dz"
ImageTypeFits ImageType = "fits"
ImageTypeJxl ImageType = "jxl"
ImageTypeMat ImageType = "mat"
ImageTypeMatrix ImageType = "matrix"
ImageTypeOpenexr ImageType = "openexr"
ImageTypeOpenslide ImageType = "openslide"
ImageTypePpm ImageType = "ppm"
ImageTypeRad ImageType = "rad"
ImageTypeRaw ImageType = "raw"
ImageTypeVips ImageType = "vips"
)
// Access represents VipsAccess type
type Access int
// Access enum
const (
AccessRandom Access = C.VIPS_ACCESS_RANDOM
AccessSequential Access = C.VIPS_ACCESS_SEQUENTIAL
AccessSequentialUnbuffered Access = C.VIPS_ACCESS_SEQUENTIAL_UNBUFFERED
AccessLast Access = C.VIPS_ACCESS_LAST
)
// Align represents VipsAlign type
type Align int
// Align enum
const (
AlignLow Align = C.VIPS_ALIGN_LOW
AlignCentre Align = C.VIPS_ALIGN_CENTRE
AlignHigh Align = C.VIPS_ALIGN_HIGH
AlignLast Align = C.VIPS_ALIGN_LAST
)
// Angle represents VipsAngle type
type Angle int
// Angle enum
const (
AngleD0 Angle = C.VIPS_ANGLE_D0
AngleD90 Angle = C.VIPS_ANGLE_D90
AngleD180 Angle = C.VIPS_ANGLE_D180
AngleD270 Angle = C.VIPS_ANGLE_D270
AngleLast Angle = C.VIPS_ANGLE_LAST
)
// Angle45 represents VipsAngle45 type
type Angle45 int
// Angle45 enum
const (
Angle45D0 Angle45 = C.VIPS_ANGLE45_D0
Angle45D45 Angle45 = C.VIPS_ANGLE45_D45
Angle45D90 Angle45 = C.VIPS_ANGLE45_D90
Angle45D135 Angle45 = C.VIPS_ANGLE45_D135
Angle45D180 Angle45 = C.VIPS_ANGLE45_D180
Angle45D225 Angle45 = C.VIPS_ANGLE45_D225
Angle45D270 Angle45 = C.VIPS_ANGLE45_D270
Angle45D315 Angle45 = C.VIPS_ANGLE45_D315
Angle45Last Angle45 = C.VIPS_ANGLE45_LAST
)
// BandFormat represents VipsBandFormat type
type BandFormat int
// BandFormat enum
const (
BandFormatNotset BandFormat = C.VIPS_FORMAT_NOTSET
BandFormatUchar BandFormat = C.VIPS_FORMAT_UCHAR
BandFormatChar BandFormat = C.VIPS_FORMAT_CHAR
BandFormatUshort BandFormat = C.VIPS_FORMAT_USHORT
BandFormatShort BandFormat = C.VIPS_FORMAT_SHORT
BandFormatUint BandFormat = C.VIPS_FORMAT_UINT
BandFormatInt BandFormat = C.VIPS_FORMAT_INT
BandFormatFloat BandFormat = C.VIPS_FORMAT_FLOAT
BandFormatComplex BandFormat = C.VIPS_FORMAT_COMPLEX
BandFormatDouble BandFormat = C.VIPS_FORMAT_DOUBLE
BandFormatDpcomplex BandFormat = C.VIPS_FORMAT_DPCOMPLEX
BandFormatLast BandFormat = C.VIPS_FORMAT_LAST
)
// BlendMode represents VipsBlendMode type
type BlendMode int
// BlendMode enum
const (
BlendModeClear BlendMode = C.VIPS_BLEND_MODE_CLEAR
BlendModeSource BlendMode = C.VIPS_BLEND_MODE_SOURCE
BlendModeOver BlendMode = C.VIPS_BLEND_MODE_OVER
BlendModeIn BlendMode = C.VIPS_BLEND_MODE_IN
BlendModeOut BlendMode = C.VIPS_BLEND_MODE_OUT
BlendModeAtop BlendMode = C.VIPS_BLEND_MODE_ATOP
BlendModeDest BlendMode = C.VIPS_BLEND_MODE_DEST
BlendModeDestOver BlendMode = C.VIPS_BLEND_MODE_DEST_OVER
BlendModeDestIn BlendMode = C.VIPS_BLEND_MODE_DEST_IN
BlendModeDestOut BlendMode = C.VIPS_BLEND_MODE_DEST_OUT
BlendModeDestAtop BlendMode = C.VIPS_BLEND_MODE_DEST_ATOP
BlendModeXor BlendMode = C.VIPS_BLEND_MODE_XOR
BlendModeAdd BlendMode = C.VIPS_BLEND_MODE_ADD
BlendModeSaturate BlendMode = C.VIPS_BLEND_MODE_SATURATE
BlendModeMultiply BlendMode = C.VIPS_BLEND_MODE_MULTIPLY
BlendModeScreen BlendMode = C.VIPS_BLEND_MODE_SCREEN
BlendModeOverlay BlendMode = C.VIPS_BLEND_MODE_OVERLAY
BlendModeDarken BlendMode = C.VIPS_BLEND_MODE_DARKEN
BlendModeLighten BlendMode = C.VIPS_BLEND_MODE_LIGHTEN
BlendModeColourDodge BlendMode = C.VIPS_BLEND_MODE_COLOUR_DODGE
BlendModeColourBurn BlendMode = C.VIPS_BLEND_MODE_COLOUR_BURN
BlendModeHardLight BlendMode = C.VIPS_BLEND_MODE_HARD_LIGHT
BlendModeSoftLight BlendMode = C.VIPS_BLEND_MODE_SOFT_LIGHT
BlendModeDifference BlendMode = C.VIPS_BLEND_MODE_DIFFERENCE
BlendModeExclusion BlendMode = C.VIPS_BLEND_MODE_EXCLUSION
BlendModeLast BlendMode = C.VIPS_BLEND_MODE_LAST
)
// Coding represents VipsCoding type
type Coding int
// Coding enum
const (
CodingError Coding = C.VIPS_CODING_ERROR
CodingNone Coding = C.VIPS_CODING_NONE
CodingLabq Coding = C.VIPS_CODING_LABQ
CodingRad Coding = C.VIPS_CODING_RAD
CodingLast Coding = C.VIPS_CODING_LAST
)
// Combine represents VipsCombine type
type Combine int
// Combine enum
const (
CombineMax Combine = C.VIPS_COMBINE_MAX
CombineSum Combine = C.VIPS_COMBINE_SUM
CombineMin Combine = C.VIPS_COMBINE_MIN
CombineLast Combine = C.VIPS_COMBINE_LAST
)
// CombineMode represents VipsCombineMode type
type CombineMode int
// CombineMode enum
const (
CombineModeSet CombineMode = C.VIPS_COMBINE_MODE_SET
CombineModeAdd CombineMode = C.VIPS_COMBINE_MODE_ADD
CombineModeLast CombineMode = C.VIPS_COMBINE_MODE_LAST
)
// CompassDirection represents VipsCompassDirection type
type CompassDirection int
// CompassDirection enum
const (
CompassDirectionCentre CompassDirection = C.VIPS_COMPASS_DIRECTION_CENTRE
CompassDirectionNorth CompassDirection = C.VIPS_COMPASS_DIRECTION_NORTH
CompassDirectionEast CompassDirection = C.VIPS_COMPASS_DIRECTION_EAST
CompassDirectionSouth CompassDirection = C.VIPS_COMPASS_DIRECTION_SOUTH
CompassDirectionWest CompassDirection = C.VIPS_COMPASS_DIRECTION_WEST
CompassDirectionNorthEast CompassDirection = C.VIPS_COMPASS_DIRECTION_NORTH_EAST
CompassDirectionSouthEast CompassDirection = C.VIPS_COMPASS_DIRECTION_SOUTH_EAST
CompassDirectionSouthWest CompassDirection = C.VIPS_COMPASS_DIRECTION_SOUTH_WEST
CompassDirectionNorthWest CompassDirection = C.VIPS_COMPASS_DIRECTION_NORTH_WEST
CompassDirectionLast CompassDirection = C.VIPS_COMPASS_DIRECTION_LAST
)
// Direction represents VipsDirection type
type Direction int
// Direction enum
const (
DirectionHorizontal Direction = C.VIPS_DIRECTION_HORIZONTAL
DirectionVertical Direction = C.VIPS_DIRECTION_VERTICAL
DirectionLast Direction = C.VIPS_DIRECTION_LAST
)
// Extend represents VipsExtend type
type Extend int
// Extend enum
const (
ExtendBlack Extend = C.VIPS_EXTEND_BLACK
ExtendCopy Extend = C.VIPS_EXTEND_COPY
ExtendRepeat Extend = C.VIPS_EXTEND_REPEAT
ExtendMirror Extend = C.VIPS_EXTEND_MIRROR
ExtendWhite Extend = C.VIPS_EXTEND_WHITE
ExtendBackground Extend = C.VIPS_EXTEND_BACKGROUND
ExtendLast Extend = C.VIPS_EXTEND_LAST
)
// FailOn represents VipsFailOn type
type FailOn int
// FailOn enum
const (
FailOnNone FailOn = C.VIPS_FAIL_ON_NONE
FailOnTruncated FailOn = C.VIPS_FAIL_ON_TRUNCATED
FailOnError FailOn = C.VIPS_FAIL_ON_ERROR
FailOnWarning FailOn = C.VIPS_FAIL_ON_WARNING
FailOnLast FailOn = C.VIPS_FAIL_ON_LAST
)
// DzContainer represents VipsForeignDzContainer type
type DzContainer int
// DzContainer enum
const (
DzContainerFs DzContainer = C.VIPS_FOREIGN_DZ_CONTAINER_FS
DzContainerZip DzContainer = C.VIPS_FOREIGN_DZ_CONTAINER_ZIP
DzContainerSzi DzContainer = C.VIPS_FOREIGN_DZ_CONTAINER_SZI
DzContainerLast DzContainer = C.VIPS_FOREIGN_DZ_CONTAINER_LAST
)
// DzDepth represents VipsForeignDzDepth type
type DzDepth int
// DzDepth enum
const (
DzDepthOnepixel DzDepth = C.VIPS_FOREIGN_DZ_DEPTH_ONEPIXEL
DzDepthOnetile DzDepth = C.VIPS_FOREIGN_DZ_DEPTH_ONETILE
DzDepthOne DzDepth = C.VIPS_FOREIGN_DZ_DEPTH_ONE
DzDepthLast DzDepth = C.VIPS_FOREIGN_DZ_DEPTH_LAST
)
// DzLayout represents VipsForeignDzLayout type
type DzLayout int
// DzLayout enum
const (
DzLayoutDz DzLayout = C.VIPS_FOREIGN_DZ_LAYOUT_DZ
DzLayoutZoomify DzLayout = C.VIPS_FOREIGN_DZ_LAYOUT_ZOOMIFY
DzLayoutGoogle DzLayout = C.VIPS_FOREIGN_DZ_LAYOUT_GOOGLE
DzLayoutIiif DzLayout = C.VIPS_FOREIGN_DZ_LAYOUT_IIIF
DzLayoutIiif3 DzLayout = C.VIPS_FOREIGN_DZ_LAYOUT_IIIF3
DzLayoutLast DzLayout = C.VIPS_FOREIGN_DZ_LAYOUT_LAST
)
// Flags represents VipsForeignFlags type
type Flags int
// Flags enum
const (
FlagsNone Flags = C.VIPS_FOREIGN_NONE
FlagsPartial Flags = C.VIPS_FOREIGN_PARTIAL
FlagsBigendian Flags = C.VIPS_FOREIGN_BIGENDIAN
FlagsSequential Flags = C.VIPS_FOREIGN_SEQUENTIAL
FlagsAll Flags = C.VIPS_FOREIGN_ALL
)
// HeifCompression represents VipsForeignHeifCompression type
type HeifCompression int
// HeifCompression enum
const (
HeifCompressionHevc HeifCompression = C.VIPS_FOREIGN_HEIF_COMPRESSION_HEVC
HeifCompressionAvc HeifCompression = C.VIPS_FOREIGN_HEIF_COMPRESSION_AVC
HeifCompressionJpeg HeifCompression = C.VIPS_FOREIGN_HEIF_COMPRESSION_JPEG
HeifCompressionAv1 HeifCompression = C.VIPS_FOREIGN_HEIF_COMPRESSION_AV1
HeifCompressionLast HeifCompression = C.VIPS_FOREIGN_HEIF_COMPRESSION_LAST
)
// HeifEncoder represents VipsForeignHeifEncoder type
type HeifEncoder int
// HeifEncoder enum
const (
HeifEncoderAuto HeifEncoder = C.VIPS_FOREIGN_HEIF_ENCODER_AUTO
HeifEncoderAom HeifEncoder = C.VIPS_FOREIGN_HEIF_ENCODER_AOM
HeifEncoderRav1e HeifEncoder = C.VIPS_FOREIGN_HEIF_ENCODER_RAV1E
HeifEncoderSvt HeifEncoder = C.VIPS_FOREIGN_HEIF_ENCODER_SVT
HeifEncoderX265 HeifEncoder = C.VIPS_FOREIGN_HEIF_ENCODER_X265
HeifEncoderLast HeifEncoder = C.VIPS_FOREIGN_HEIF_ENCODER_LAST
)
// Keep represents VipsForeignKeep type
type Keep int
// Keep enum
const (
KeepNone Keep = C.VIPS_FOREIGN_KEEP_NONE
KeepExif Keep = C.VIPS_FOREIGN_KEEP_EXIF
KeepXmp Keep = C.VIPS_FOREIGN_KEEP_XMP
KeepIptc Keep = C.VIPS_FOREIGN_KEEP_IPTC
KeepIcc Keep = C.VIPS_FOREIGN_KEEP_ICC
KeepOther Keep = C.VIPS_FOREIGN_KEEP_OTHER
KeepAll Keep = C.VIPS_FOREIGN_KEEP_ALL
)
// PngFilter represents VipsForeignPngFilter type
type PngFilter int
// PngFilter enum
const (
PngFilterNone PngFilter = C.VIPS_FOREIGN_PNG_FILTER_NONE
PngFilterSub PngFilter = C.VIPS_FOREIGN_PNG_FILTER_SUB
PngFilterUp PngFilter = C.VIPS_FOREIGN_PNG_FILTER_UP
PngFilterAvg PngFilter = C.VIPS_FOREIGN_PNG_FILTER_AVG
PngFilterPaeth PngFilter = C.VIPS_FOREIGN_PNG_FILTER_PAETH
PngFilterAll PngFilter = C.VIPS_FOREIGN_PNG_FILTER_ALL
)
// PpmFormat represents VipsForeignPpmFormat type
type PpmFormat int
// PpmFormat enum
const (
PpmFormatPbm PpmFormat = C.VIPS_FOREIGN_PPM_FORMAT_PBM
PpmFormatPgm PpmFormat = C.VIPS_FOREIGN_PPM_FORMAT_PGM
PpmFormatPpm PpmFormat = C.VIPS_FOREIGN_PPM_FORMAT_PPM
PpmFormatPfm PpmFormat = C.VIPS_FOREIGN_PPM_FORMAT_PFM
PpmFormatPnm PpmFormat = C.VIPS_FOREIGN_PPM_FORMAT_PNM
PpmFormatLast PpmFormat = C.VIPS_FOREIGN_PPM_FORMAT_LAST
)
// Subsample represents VipsForeignSubsample type
type Subsample int
// Subsample enum
const (
SubsampleAuto Subsample = C.VIPS_FOREIGN_SUBSAMPLE_AUTO
SubsampleOn Subsample = C.VIPS_FOREIGN_SUBSAMPLE_ON
SubsampleOff Subsample = C.VIPS_FOREIGN_SUBSAMPLE_OFF
SubsampleLast Subsample = C.VIPS_FOREIGN_SUBSAMPLE_LAST
)
// TiffCompression represents VipsForeignTiffCompression type
type TiffCompression int
// TiffCompression enum
const (
TiffCompressionNone TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_NONE
TiffCompressionJpeg TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_JPEG
TiffCompressionDeflate TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE
TiffCompressionPackbits TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS
TiffCompressionCcittfax4 TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4
TiffCompressionLzw TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_LZW
TiffCompressionWebp TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_WEBP
TiffCompressionZstd TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD
TiffCompressionJp2k TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_JP2K
TiffCompressionLast TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_LAST
)
// TiffPredictor represents VipsForeignTiffPredictor type
type TiffPredictor int
// TiffPredictor enum
const (
TiffPredictorNone TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_NONE
TiffPredictorHorizontal TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL
TiffPredictorFloat TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT
TiffPredictorLast TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_LAST
)
// TiffResunit represents VipsForeignTiffResunit type
type TiffResunit int
// TiffResunit enum
const (
TiffResunitCm TiffResunit = C.VIPS_FOREIGN_TIFF_RESUNIT_CM
TiffResunitInch TiffResunit = C.VIPS_FOREIGN_TIFF_RESUNIT_INCH
TiffResunitLast TiffResunit = C.VIPS_FOREIGN_TIFF_RESUNIT_LAST
)
// WebpPreset represents VipsForeignWebpPreset type
type WebpPreset int
// WebpPreset enum
const (
WebpPresetDefault WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_DEFAULT
WebpPresetPicture WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_PICTURE
WebpPresetPhoto WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_PHOTO
WebpPresetDrawing WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_DRAWING
WebpPresetIcon WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_ICON
WebpPresetText WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_TEXT
WebpPresetLast WebpPreset = C.VIPS_FOREIGN_WEBP_PRESET_LAST
)
// Intent represents VipsIntent type
type Intent int
// Intent enum
const (
IntentPerceptual Intent = C.VIPS_INTENT_PERCEPTUAL
IntentRelative Intent = C.VIPS_INTENT_RELATIVE
IntentSaturation Intent = C.VIPS_INTENT_SATURATION
IntentAbsolute Intent = C.VIPS_INTENT_ABSOLUTE
IntentAuto Intent = C.VIPS_INTENT_AUTO
IntentLast Intent = C.VIPS_INTENT_LAST
)
// Interesting represents VipsInteresting type
type Interesting int
// Interesting enum
const (
InterestingNone Interesting = C.VIPS_INTERESTING_NONE
InterestingCentre Interesting = C.VIPS_INTERESTING_CENTRE
InterestingEntropy Interesting = C.VIPS_INTERESTING_ENTROPY
InterestingAttention Interesting = C.VIPS_INTERESTING_ATTENTION
InterestingLow Interesting = C.VIPS_INTERESTING_LOW
InterestingHigh Interesting = C.VIPS_INTERESTING_HIGH
InterestingAll Interesting = C.VIPS_INTERESTING_ALL
InterestingLast Interesting = C.VIPS_INTERESTING_LAST
)
// Interpretation represents VipsInterpretation type
type Interpretation int
// Interpretation enum
const (
InterpretationError Interpretation = C.VIPS_INTERPRETATION_ERROR
InterpretationMultiband Interpretation = C.VIPS_INTERPRETATION_MULTIBAND
InterpretationBW Interpretation = C.VIPS_INTERPRETATION_B_W
InterpretationHistogram Interpretation = C.VIPS_INTERPRETATION_HISTOGRAM
InterpretationXyz Interpretation = C.VIPS_INTERPRETATION_XYZ
InterpretationLab Interpretation = C.VIPS_INTERPRETATION_LAB
InterpretationCmyk Interpretation = C.VIPS_INTERPRETATION_CMYK
InterpretationLabq Interpretation = C.VIPS_INTERPRETATION_LABQ
InterpretationRgb Interpretation = C.VIPS_INTERPRETATION_RGB
InterpretationCmc Interpretation = C.VIPS_INTERPRETATION_CMC
InterpretationLch Interpretation = C.VIPS_INTERPRETATION_LCH
InterpretationLabs Interpretation = C.VIPS_INTERPRETATION_LABS
InterpretationSrgb Interpretation = C.VIPS_INTERPRETATION_sRGB
InterpretationYxy Interpretation = C.VIPS_INTERPRETATION_YXY
InterpretationFourier Interpretation = C.VIPS_INTERPRETATION_FOURIER
InterpretationRgb16 Interpretation = C.VIPS_INTERPRETATION_RGB16
InterpretationGrey16 Interpretation = C.VIPS_INTERPRETATION_GREY16
InterpretationMatrix Interpretation = C.VIPS_INTERPRETATION_MATRIX
InterpretationScrgb Interpretation = C.VIPS_INTERPRETATION_scRGB
InterpretationHsv Interpretation = C.VIPS_INTERPRETATION_HSV
InterpretationLast Interpretation = C.VIPS_INTERPRETATION_LAST
)
// Kernel represents VipsKernel type
type Kernel int
// Kernel enum
const (
KernelNearest Kernel = C.VIPS_KERNEL_NEAREST
KernelLinear Kernel = C.VIPS_KERNEL_LINEAR
KernelCubic Kernel = C.VIPS_KERNEL_CUBIC
KernelMitchell Kernel = C.VIPS_KERNEL_MITCHELL
KernelLanczos2 Kernel = C.VIPS_KERNEL_LANCZOS2
KernelLanczos3 Kernel = C.VIPS_KERNEL_LANCZOS3
KernelMks2013 Kernel = C.VIPS_KERNEL_MKS2013
KernelMks2021 Kernel = C.VIPS_KERNEL_MKS2021
KernelLast Kernel = C.VIPS_KERNEL_LAST
)
// OperationBoolean represents VipsOperationBoolean type
type OperationBoolean int
// OperationBoolean enum
const (
OperationBooleanAnd OperationBoolean = C.VIPS_OPERATION_BOOLEAN_AND
OperationBooleanOr OperationBoolean = C.VIPS_OPERATION_BOOLEAN_OR
OperationBooleanEor OperationBoolean = C.VIPS_OPERATION_BOOLEAN_EOR
OperationBooleanLshift OperationBoolean = C.VIPS_OPERATION_BOOLEAN_LSHIFT
OperationBooleanRshift OperationBoolean = C.VIPS_OPERATION_BOOLEAN_RSHIFT
OperationBooleanLast OperationBoolean = C.VIPS_OPERATION_BOOLEAN_LAST
)
// OperationComplex represents VipsOperationComplex type
type OperationComplex int
// OperationComplex enum
const (
OperationComplexPolar OperationComplex = C.VIPS_OPERATION_COMPLEX_POLAR
OperationComplexRect OperationComplex = C.VIPS_OPERATION_COMPLEX_RECT
OperationComplexConj OperationComplex = C.VIPS_OPERATION_COMPLEX_CONJ
OperationComplexLast OperationComplex = C.VIPS_OPERATION_COMPLEX_LAST
)
// OperationComplex2 represents VipsOperationComplex2 type
type OperationComplex2 int
// OperationComplex2 enum
const (
OperationComplex2CrossPhase OperationComplex2 = C.VIPS_OPERATION_COMPLEX2_CROSS_PHASE
OperationComplex2Last OperationComplex2 = C.VIPS_OPERATION_COMPLEX2_LAST
)
// OperationComplexget represents VipsOperationComplexget type
type OperationComplexget int
// OperationComplexget enum
const (
OperationComplexgetReal OperationComplexget = C.VIPS_OPERATION_COMPLEXGET_REAL
OperationComplexgetImag OperationComplexget = C.VIPS_OPERATION_COMPLEXGET_IMAG
OperationComplexgetLast OperationComplexget = C.VIPS_OPERATION_COMPLEXGET_LAST
)
// OperationMath represents VipsOperationMath type
type OperationMath int
// OperationMath enum
const (
OperationMathSin OperationMath = C.VIPS_OPERATION_MATH_SIN
OperationMathCos OperationMath = C.VIPS_OPERATION_MATH_COS
OperationMathTan OperationMath = C.VIPS_OPERATION_MATH_TAN
OperationMathAsin OperationMath = C.VIPS_OPERATION_MATH_ASIN
OperationMathAcos OperationMath = C.VIPS_OPERATION_MATH_ACOS
OperationMathAtan OperationMath = C.VIPS_OPERATION_MATH_ATAN
OperationMathLog OperationMath = C.VIPS_OPERATION_MATH_LOG
OperationMathLog10 OperationMath = C.VIPS_OPERATION_MATH_LOG10
OperationMathExp OperationMath = C.VIPS_OPERATION_MATH_EXP
OperationMathExp10 OperationMath = C.VIPS_OPERATION_MATH_EXP10
OperationMathSinh OperationMath = C.VIPS_OPERATION_MATH_SINH
OperationMathCosh OperationMath = C.VIPS_OPERATION_MATH_COSH
OperationMathTanh OperationMath = C.VIPS_OPERATION_MATH_TANH
OperationMathAsinh OperationMath = C.VIPS_OPERATION_MATH_ASINH
OperationMathAcosh OperationMath = C.VIPS_OPERATION_MATH_ACOSH
OperationMathAtanh OperationMath = C.VIPS_OPERATION_MATH_ATANH
OperationMathLast OperationMath = C.VIPS_OPERATION_MATH_LAST
)
// OperationMath2 represents VipsOperationMath2 type
type OperationMath2 int
// OperationMath2 enum
const (
OperationMath2Pow OperationMath2 = C.VIPS_OPERATION_MATH2_POW
OperationMath2Wop OperationMath2 = C.VIPS_OPERATION_MATH2_WOP
OperationMath2Atan2 OperationMath2 = C.VIPS_OPERATION_MATH2_ATAN2
OperationMath2Last OperationMath2 = C.VIPS_OPERATION_MATH2_LAST
)
// OperationMorphology represents VipsOperationMorphology type
type OperationMorphology int
// OperationMorphology enum
const (
OperationMorphologyErode OperationMorphology = C.VIPS_OPERATION_MORPHOLOGY_ERODE
OperationMorphologyDilate OperationMorphology = C.VIPS_OPERATION_MORPHOLOGY_DILATE
OperationMorphologyLast OperationMorphology = C.VIPS_OPERATION_MORPHOLOGY_LAST
)
// OperationRelational represents VipsOperationRelational type
type OperationRelational int
// OperationRelational enum
const (
OperationRelationalEqual OperationRelational = C.VIPS_OPERATION_RELATIONAL_EQUAL
OperationRelationalNoteq OperationRelational = C.VIPS_OPERATION_RELATIONAL_NOTEQ
OperationRelationalLess OperationRelational = C.VIPS_OPERATION_RELATIONAL_LESS
OperationRelationalLesseq OperationRelational = C.VIPS_OPERATION_RELATIONAL_LESSEQ
OperationRelationalMore OperationRelational = C.VIPS_OPERATION_RELATIONAL_MORE
OperationRelationalMoreeq OperationRelational = C.VIPS_OPERATION_RELATIONAL_MOREEQ
OperationRelationalLast OperationRelational = C.VIPS_OPERATION_RELATIONAL_LAST
)
// OperationRound represents VipsOperationRound type
type OperationRound int
// OperationRound enum
const (
OperationRoundRint OperationRound = C.VIPS_OPERATION_ROUND_RINT
OperationRoundCeil OperationRound = C.VIPS_OPERATION_ROUND_CEIL
OperationRoundFloor OperationRound = C.VIPS_OPERATION_ROUND_FLOOR
OperationRoundLast OperationRound = C.VIPS_OPERATION_ROUND_LAST
)
// PCS represents VipsPCS type
type PCS int
// PCS enum
const (
PcsLab PCS = C.VIPS_PCS_LAB
PcsXyz PCS = C.VIPS_PCS_XYZ
PcsLast PCS = C.VIPS_PCS_LAST
)
// Precision represents VipsPrecision type
type Precision int
// Precision enum
const (
PrecisionInteger Precision = C.VIPS_PRECISION_INTEGER
PrecisionFloat Precision = C.VIPS_PRECISION_FLOAT
PrecisionApproximate Precision = C.VIPS_PRECISION_APPROXIMATE
PrecisionLast Precision = C.VIPS_PRECISION_LAST
)
// RegionShrink represents VipsRegionShrink type
type RegionShrink int
// RegionShrink enum
const (
RegionShrinkMean RegionShrink = C.VIPS_REGION_SHRINK_MEAN
RegionShrinkMedian RegionShrink = C.VIPS_REGION_SHRINK_MEDIAN
RegionShrinkMode RegionShrink = C.VIPS_REGION_SHRINK_MODE
RegionShrinkMax RegionShrink = C.VIPS_REGION_SHRINK_MAX
RegionShrinkMin RegionShrink = C.VIPS_REGION_SHRINK_MIN
RegionShrinkNearest RegionShrink = C.VIPS_REGION_SHRINK_NEAREST
RegionShrinkLast RegionShrink = C.VIPS_REGION_SHRINK_LAST
)
// SdfShape represents VipsSdfShape type
type SdfShape int
// SdfShape enum
const (
SdfShapeCircle SdfShape = C.VIPS_SDF_SHAPE_CIRCLE
SdfShapeBox SdfShape = C.VIPS_SDF_SHAPE_BOX
SdfShapeRoundedBox SdfShape = C.VIPS_SDF_SHAPE_ROUNDED_BOX
SdfShapeLine SdfShape = C.VIPS_SDF_SHAPE_LINE
SdfShapeLast SdfShape = C.VIPS_SDF_SHAPE_LAST
)
// Size represents VipsSize type
type Size int
// Size enum
const (
SizeBoth Size = C.VIPS_SIZE_BOTH
SizeUp Size = C.VIPS_SIZE_UP
SizeDown Size = C.VIPS_SIZE_DOWN
SizeForce Size = C.VIPS_SIZE_FORCE
SizeLast Size = C.VIPS_SIZE_LAST
)
// TextWrap represents VipsTextWrap type
type TextWrap int
// TextWrap enum
const (
TextWrapWord TextWrap = C.VIPS_TEXT_WRAP_WORD
TextWrapChar TextWrap = C.VIPS_TEXT_WRAP_CHAR
TextWrapWordChar TextWrap = C.VIPS_TEXT_WRAP_WORD_CHAR
TextWrapNone TextWrap = C.VIPS_TEXT_WRAP_NONE
TextWrapLast TextWrap = C.VIPS_TEXT_WRAP_LAST
)
// imageMimeTypes map the various image types to its mime type representation
var imageMimeTypes = map[ImageType]string{
ImageTypeJpeg: "image/jpeg",
ImageTypeGif: "image/gif",
ImageTypePng: "image/png",
ImageTypeWebp: "image/webp",
ImageTypeHeif: "image/heif",
ImageTypeSvg: "image/svg+xml",
ImageTypeTiff: "image/tiff",
ImageTypeJp2k: "image/jp2",
ImageTypeAvif: "image/avif",
ImageTypePdf: "application/pdf",
ImageTypeBmp: "image/bmp",
ImageTypeAnalyze: "application/x-analyze",
ImageTypeCsv: "text/csv",
ImageTypeDz: "image/x-deepzoom",
ImageTypeFits: "image/fits",
ImageTypeJxl: "image/jxl",
ImageTypeMat: "application/x-matlab-data",
ImageTypeMatrix: "application/x-matrix",
ImageTypeOpenexr: "image/openexr",
ImageTypeOpenslide: "application/x-openslide",
ImageTypePpm: "image/x-portable-pixmap",
ImageTypeRad: "image/rad",
ImageTypeRaw: "image/raw",
ImageTypeVips: "image/vnd.libvips",
}
// MimeType returns the MIME type for the image type.
func (imageType ImageType) MimeType() (mime string, ok bool) {
mime, ok = imageMimeTypes[imageType]
return
}
// vipsDetermineImageType determine the image type from loader metadata
func vipsDetermineImageType(in *C.VipsImage) ImageType {
if in != nil {
if vipsLoader, ok := vipsImageGetMetaLoader(in); ok {
if strings.HasPrefix(vipsLoader, "jpeg") {
return ImageTypeJpeg
}
if strings.HasPrefix(vipsLoader, "gif") {
return ImageTypeGif
}
if strings.HasPrefix(vipsLoader, "png") {
return ImageTypePng
}
if strings.HasPrefix(vipsLoader, "webp") {
return ImageTypeWebp
}
if strings.HasPrefix(vipsLoader, "heif") {
return ImageTypeHeif
}
if strings.HasPrefix(vipsLoader, "svg") {
return ImageTypeSvg
}
if strings.HasPrefix(vipsLoader, "tiff") {
return ImageTypeTiff
}
if strings.HasPrefix(vipsLoader, "jp2k") {
return ImageTypeJp2k
}
if strings.HasPrefix(vipsLoader, "pdf") {
return ImageTypePdf
}
if strings.HasPrefix(vipsLoader, "analyze") {
return ImageTypeAnalyze
}
if strings.HasPrefix(vipsLoader, "csv") {
return ImageTypeCsv
}
if strings.HasPrefix(vipsLoader, "fits") {
return ImageTypeFits
}
if strings.HasPrefix(vipsLoader, "jxl") {
return ImageTypeJxl
}
if strings.HasPrefix(vipsLoader, "mat") {
return ImageTypeMat
}
if strings.HasPrefix(vipsLoader, "matrix") {
return ImageTypeMatrix
}
if strings.HasPrefix(vipsLoader, "openexr") {
return ImageTypeOpenexr
}
if strings.HasPrefix(vipsLoader, "openslide") {
return ImageTypeOpenslide
}
if strings.HasPrefix(vipsLoader, "ppm") {
return ImageTypePpm
}
if strings.HasPrefix(vipsLoader, "rad") {
return ImageTypeRad
}
if strings.HasPrefix(vipsLoader, "raw") {
return ImageTypeRaw
}
if strings.HasPrefix(vipsLoader, "vips") {
return ImageTypeVips
}
if strings.HasPrefix(vipsLoader, "magick") {
return ImageTypeMagick
}
}
}
return ImageTypeUnknown
}
// Interpolate represents VipsInterpolate type
type Interpolate struct {
interp *C.VipsInterpolate
}
// InterpolateType represents the type of interpolation to use
type InterpolateType string
// InterpolateType enum - these values match the predefined interpolators in libvips
const (
InterpolateNearest InterpolateType = "nearest"
InterpolateBilinear InterpolateType = "bilinear"
InterpolateBicubic InterpolateType = "bicubic"
InterpolateLbb InterpolateType = "lbb" // Lanczos3
InterpolateNohalo InterpolateType = "nohalo"
InterpolateVsqbs InterpolateType = "vsqbs"
)
// NewInterpolate creates a new Interpolate with the given name
// Valid names include: "nearest", "bilinear", "bicubic", "lbb", "nohalo", "vsqbs"
func NewInterpolate(name InterpolateType) *Interpolate {
Startup(nil)
cName := C.CString(string(name))
defer C.free(unsafe.Pointer(cName))
interp := C.vips_interpolate_new(cName)
if interp == nil {
// Default to bilinear if requested interpolator not found
C.vips_error_clear()
cDefault := C.CString("bilinear")
defer C.free(unsafe.Pointer(cDefault))
interp = C.vips_interpolate_new(cDefault)
}
return &Interpolate{interp: interp}
}
// Close frees the interpolator resources
func (i *Interpolate) Close() {
if i != nil && i.interp != nil {
C.g_object_unref(C.gpointer(i.interp))
i.interp = nil
}
}

25
vendor/github.com/cshum/vipsgen/vips/util.c generated vendored Normal file
View File

@@ -0,0 +1,25 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
#include "util.h"
static void logging_handler(const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message, gpointer user_data) {
goLoggingHandler((char *)log_domain, (int)log_level, (char *)message);
}
static void null_logging_handler(const gchar *log_domain,
GLogLevelFlags log_level, const gchar *message,
gpointer user_data) {}
void set_logging_handler(void) {
g_log_set_default_handler(logging_handler, NULL);
}
void unset_logging_handler(void) {
g_log_set_default_handler(null_logging_handler, NULL);
}
int is_gobject(void* obj) {
return G_IS_OBJECT(obj) ? 1 : 0;
}

474
vendor/github.com/cshum/vipsgen/vips/util.go generated vendored Normal file
View File

@@ -0,0 +1,474 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
package vips
// #cgo pkg-config: vips
// #include "util.h"
import "C"
import (
"fmt"
"runtime"
"sync"
"unsafe"
)
// Version is the full libvips version string (x.y.z)
const Version = string(C.VIPS_VERSION)
// MajorVersion is the libvips major component of the version string (x in x.y.z)
const MajorVersion = int(C.VIPS_MAJOR_VERSION)
// MinorVersion is the libvips minor component of the version string (y in x.y.z)
const MinorVersion = int(C.VIPS_MINOR_VERSION)
// MicroVersion is the libvips micro component of the version string (z in x.y.z)
// Also known as patch version
const MicroVersion = int(C.VIPS_MICRO_VERSION)
var (
lock sync.Mutex
once sync.Once
isStarted bool
isShutdown bool
)
type Config struct {
ConcurrencyLevel int
MaxCacheFiles int
MaxCacheMem int
MaxCacheSize int
ReportLeaks bool
CacheTrace bool
VectorEnabled bool
}
// LogLevel log level
type LogLevel int
// LogLevel enum
const (
LogLevelError LogLevel = C.G_LOG_LEVEL_ERROR
LogLevelCritical LogLevel = C.G_LOG_LEVEL_CRITICAL
LogLevelWarning LogLevel = C.G_LOG_LEVEL_WARNING
LogLevelMessage LogLevel = C.G_LOG_LEVEL_MESSAGE
LogLevelInfo LogLevel = C.G_LOG_LEVEL_INFO
LogLevelDebug LogLevel = C.G_LOG_LEVEL_DEBUG
)
var (
currentLoggingHandlerFunction = noopLoggingHandler
currentLoggingVerbosity LogLevel
)
// LoggingHandlerFunction logging handler function
type LoggingHandlerFunction func(messageDomain string, messageLevel LogLevel, message string)
// SetLogging set logging handler and verbosity
func SetLogging(handler LoggingHandlerFunction, verbosity LogLevel) {
if handler != nil {
currentLoggingHandlerFunction = handler
}
currentLoggingVerbosity = verbosity
}
func noopLoggingHandler(_ string, _ LogLevel, _ string) {
}
func log(domain string, level LogLevel, message string) {
if level <= currentLoggingVerbosity {
currentLoggingHandlerFunction(domain, level, message)
}
}
func enableLogging() {
C.set_logging_handler()
}
func disableLogging() {
C.unset_logging_handler()
}
// Startup sets up libvips and ensures the versions are correct. Pass in nil for default config.
func Startup(config *Config) {
once.Do(func() {
startup(config)
})
}
func startup(config *Config) {
lock.Lock()
defer lock.Unlock()
if isStarted || isShutdown {
return
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if MajorVersion < 8 || (MajorVersion == 8 && MinorVersion < 10) {
panic("requires libvips version 8.10+")
}
cName := C.CString("vips")
defer freeCString(cName)
// Override default glib logging handler to intercept logging messages
enableLogging()
err := C.vips_init(cName)
if err != 0 {
panic(fmt.Sprintf("Failed to start vips code=%v", err))
}
if config != nil {
C.vips_leak_set(toGboolean(config.ReportLeaks))
}
if config != nil && config.ConcurrencyLevel >= 0 {
C.vips_concurrency_set(C.int(config.ConcurrencyLevel))
} else {
C.vips_concurrency_set(1)
}
if config != nil && config.MaxCacheFiles >= 0 {
C.vips_cache_set_max_files(C.int(config.MaxCacheFiles))
} else {
C.vips_cache_set_max_files(0)
}
if config != nil && config.MaxCacheMem >= 0 {
C.vips_cache_set_max_mem(C.size_t(config.MaxCacheMem))
} else {
C.vips_cache_set_max_mem(0)
}
if config != nil && config.MaxCacheSize >= 0 {
C.vips_cache_set_max(C.int(config.MaxCacheSize))
} else {
C.vips_cache_set_max(0)
}
if config != nil && config.VectorEnabled {
C.vips_vector_set_enabled(1)
} else {
C.vips_vector_set_enabled(0)
}
if config != nil && config.CacheTrace {
C.vips_cache_set_trace(toGboolean(true))
}
log("vipsgen", LogLevelInfo, fmt.Sprintf("vips %s started with concurrency=%d cache_max_files=%d cache_max_mem=%d cache_max=%d",
Version,
int(C.vips_concurrency_get()),
int(C.vips_cache_get_max_files()),
int(C.vips_cache_get_max_mem()),
int(C.vips_cache_get_max())))
isStarted = true
}
// Shutdown libvips
func Shutdown() {
lock.Lock()
defer lock.Unlock()
if !isStarted || isShutdown {
return
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
C.vips_shutdown()
disableLogging()
isShutdown = true
}
// MemoryStats is a data structure that houses various memory statistics from ReadVipsMemStats()
type MemoryStats struct {
Mem int64
MemHigh int64
Files int64
Allocs int64
}
// ReadVipsMemStats returns various memory statistics such as allocated memory and open files.
func ReadVipsMemStats(stats *MemoryStats) {
stats.Mem = int64(C.vips_tracked_get_mem())
stats.MemHigh = int64(C.vips_tracked_get_mem_highwater())
stats.Allocs = int64(C.vips_tracked_get_allocs())
stats.Files = int64(C.vips_tracked_get_files())
}
// HasOperation checks if a libvips operation exists
func HasOperation(name string) bool {
Startup(nil)
cName := C.CString(name)
defer freeCString(cName)
vop := C.vips_operation_new(cName)
if vop == nil {
C.vips_error_clear()
return false
}
if C.is_gobject(unsafe.Pointer(vop)) != 0 {
C.g_object_unref(C.gpointer(vop))
}
return true
}
func handleImageError(out *C.VipsImage) error {
if out != nil {
clearImage(out)
}
return handleVipsError()
}
func handleVipsError() error {
s := C.GoString(C.vips_error_buffer())
C.vips_error_clear()
return fmt.Errorf("%v", s)
}
func freeCString(s *C.char) {
C.free(unsafe.Pointer(s))
}
func gFreePointer(ref unsafe.Pointer) {
C.g_free(C.gpointer(ref))
}
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}
func boolToStr(v bool) string {
if v {
return "TRUE"
}
return "FALSE"
}
func toGboolean(b bool) C.gboolean {
if b {
return C.gboolean(1)
}
return C.gboolean(0)
}
func fromGboolean(b C.gboolean) bool {
return b != 0
}
var cStringsCache sync.Map
func cachedCString(str string) *C.char {
if cstr, ok := cStringsCache.Load(str); ok {
return cstr.(*C.char)
}
cstr := C.CString(str)
cStringsCache.Store(str, cstr)
return cstr
}
// bufferToBytes converts a C buffer to Go bytes and frees the original buffer.
// This function takes ownership of the buffer and will free it after conversion.
func bufferToBytes(buf unsafe.Pointer, length C.size_t) []byte {
if buf == nil {
return nil
}
bytes := C.GoBytes(buf, C.int(length))
C.g_free(C.gpointer(buf))
return bytes
}
// convertImagesToVipsImages converts from Image slice to VipsImage slice
func convertImagesToVipsImages(images []*Image) []*C.VipsImage {
vipsImages := make([]*C.VipsImage, len(images))
for i, img := range images {
vipsImages[i] = img.image
}
return vipsImages
}
// convertVipsImagesToImages converts a slice of *C.VipsImage to []*Image
func convertVipsImagesToImages(vipsImages []*C.VipsImage) []*Image {
images := make([]*Image, len(vipsImages))
for i, vipsImg := range vipsImages {
images[i] = newImageRef(vipsImg, ImageTypeUnknown, nil)
}
return images
}
// vipsInterpolateToC converts a Go Interpolate to a C VipsInterpolate pointer
func vipsInterpolateToC(interp *Interpolate) *C.VipsInterpolate {
if interp == nil {
return nil
}
return interp.interp
}
// vipsInterpolateFromC converts a C VipsInterpolate pointer to a Go Interpolate
func vipsInterpolateFromC(interp *C.VipsInterpolate) *Interpolate {
if interp == nil {
return nil
}
return &Interpolate{interp: interp}
}
// convertToDoubleArray converts a Go float64 slice to a C double array and returns the length
func convertToDoubleArray(values []float64) (*C.double, C.int, error) {
if len(values) == 0 {
return nil, 0, nil
}
// Allocate C memory
size := C.size_t(len(values)) * C.size_t(unsafe.Sizeof(C.double(0)))
cArray := (*C.double)(C.malloc(size))
if cArray == nil {
return nil, 0, fmt.Errorf("failed to allocate memory for double array")
}
// Copy values to C array
for i, v := range values {
ptr := unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(C.double(0)))
*(*C.double)(ptr) = C.double(v)
}
return cArray, C.int(len(values)), nil
}
// freeDoubleArray frees memory allocated for a C double array
func freeDoubleArray(array *C.double) {
if array != nil {
C.free(unsafe.Pointer(array))
}
}
func fromCArrayDouble(out *C.double, n int) []float64 {
if out == nil || n <= 0 {
return nil
}
data := make([]float64, n)
for i := 0; i < n; i++ {
data[i] = float64(*(*C.double)(unsafe.Pointer(uintptr(unsafe.Pointer(out)) + uintptr(i)*unsafe.Sizeof(C.double(0)))))
}
return data
}
func fromCArrayInt(out *C.int, n int) []int {
if out == nil || n <= 0 {
return nil
}
data := make([]int, n)
for i := 0; i < n; i++ {
data[i] = int(*(*C.int)(unsafe.Pointer(uintptr(unsafe.Pointer(out)) + uintptr(i)*unsafe.Sizeof(C.int(0)))))
}
return data
}
// convertToIntArray converts a Go int slice to a C int array and returns the length
func convertToIntArray(values []int) (*C.int, C.int, error) {
if len(values) == 0 {
return nil, 0, nil
}
// Allocate C memory
size := C.size_t(len(values)) * C.size_t(unsafe.Sizeof(C.int(0)))
cArray := (*C.int)(C.malloc(size))
if cArray == nil {
return nil, 0, fmt.Errorf("failed to allocate memory for int array")
}
// Copy values to C array
for i, v := range values {
ptr := unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(C.int(0)))
*(*C.int)(ptr) = C.int(v)
}
return cArray, C.int(len(values)), nil
}
// freeIntArray frees memory allocated for a C int array
func freeIntArray(array *C.int) {
if array != nil {
C.free(unsafe.Pointer(array))
}
}
// convertToBlendModeArray converts a Go BlendMode slice to a C int array and returns the length
func convertToBlendModeArray(values []BlendMode) (*C.int, C.int, error) {
if len(values) == 0 {
return nil, 0, nil
}
// Allocate C memory
size := C.size_t(len(values)) * C.size_t(unsafe.Sizeof(C.int(0)))
cArray := (*C.int)(C.malloc(size))
if cArray == nil {
return nil, 0, fmt.Errorf("failed to allocate memory for BlendMode array")
}
// Copy values to C array
for i, v := range values {
ptr := unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(C.int(0)))
*(*C.int)(ptr) = C.int(v)
}
return cArray, C.int(len(values)), nil
}
// convertToImageArray converts a Go []*Image slice to a C VipsImage** array and returns the length
func convertToImageArray(images []*C.VipsImage) (**C.VipsImage, C.int, error) {
if len(images) == 0 {
return nil, 0, nil
}
// Allocate C memory for array of VipsImage pointers
size := C.size_t(len(images)) * C.size_t(unsafe.Sizeof((*C.VipsImage)(nil)))
cArray := (**C.VipsImage)(C.malloc(size))
if cArray == nil {
return nil, 0, fmt.Errorf("failed to allocate memory for image array")
}
// Convert each Image to a C VipsImage pointer and store in array
for i, img := range images {
ptr := unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof((*C.VipsImage)(nil)))
*(**C.VipsImage)(ptr) = img
}
return cArray, C.int(len(images)), nil
}
// freeImageArray frees memory allocated for a C VipsImage** array
func freeImageArray(array **C.VipsImage) {
if array != nil {
C.free(unsafe.Pointer(array))
}
}
// vipsBlobToBytes converts a VipsBlob to a Go byte slice and unrefs the blob
func vipsBlobToBytes(blob *C.VipsBlob) []byte {
if blob == nil {
return nil
}
var size C.size_t
ptr := C.vips_blob_get(blob, &size)
data := C.GoBytes(ptr, C.int(size))
C.vips_area_unref((*C.VipsArea)(unsafe.Pointer(blob)))
return data
}
// getImagePointer safely extracts the C.VipsImage pointer from an Image, returning nil if the Image is nil
func getImagePointer(img *Image) *C.VipsImage {
if img == nil {
return nil
}
return img.image
}

View File

@@ -1,9 +1,11 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
// clang-format off
// include order matters
#include <stdlib.h>
#include <glib.h>
#include <vips/vips.h>
#include <vips/vector.h>
// clang-format on
#if (VIPS_MAJOR_VERSION < 8)
@@ -11,9 +13,9 @@ error_requires_version_8
#endif
extern void
govipsLoggingHandler(char *log_domain, int log_level, char *message);
goLoggingHandler(char *log_domain, int log_level, char *message);
static void govips_logging_handler(const gchar *log_domain,
static void logging_handler(const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message, gpointer user_data);
@@ -21,6 +23,11 @@ static void null_logging_handler(const gchar *log_domain,
GLogLevelFlags log_level, const gchar *message,
gpointer user_data);
void vips_set_logging_handler(void);
void vips_unset_logging_handler(void);
void vips_default_logging_handler(void);
void set_logging_handler(void);
void unset_logging_handler(void);
#ifndef G_IS_OBJECT
#define G_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_OBJECT))
#endif
int is_gobject(void* obj);

6120
vendor/github.com/cshum/vipsgen/vips/vips.c generated vendored Normal file

File diff suppressed because it is too large Load Diff

6523
vendor/github.com/cshum/vipsgen/vips/vips.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

886
vendor/github.com/cshum/vipsgen/vips/vips.h generated vendored Normal file
View File

@@ -0,0 +1,886 @@
// Code generated by github.com/cshum/vipsgen from libvips 8.17.2; DO NOT EDIT.
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/vector.h>
// Prerequisites to build, get outputs and cleanup a vips operation
int vipsgen_operation_execute(VipsOperation *operation, ...);
int vipsgen_operation_save_buffer(VipsOperation *operation, void** buf, size_t* len);
int vipsgen_set_source(VipsOperation *operation, const char *name, VipsSource *value);
int vipsgen_set_target(VipsOperation *operation, const char *name, VipsTarget *value);
int vipsgen_set_int(VipsOperation *operation, const char *name, int value);
int vipsgen_set_bool(VipsOperation *operation, const char *name, gboolean value);
int vipsgen_set_double(VipsOperation *operation, const char *name, double value);
int vipsgen_set_guint64(VipsOperation *operation, const char *name, guint64 value);
int vipsgen_set_string(VipsOperation *operation, const char *name, const char *value);
int vipsgen_set_image(VipsOperation *operation, const char *name, VipsImage *value);
int vipsgen_set_array_double(VipsOperation *operation, const char *name, VipsArrayDouble *value);
int vipsgen_set_array_int(VipsOperation *operation, const char *name, VipsArrayInt *value);
int vipsgen_set_array_image(VipsOperation *operation, const char *name, VipsArrayImage *value);
int vipsgen_set_interpolate(VipsOperation *operation, const char *name, VipsInterpolate *value);
// Generated operations
int vipsgen_CMC2LCh(VipsImage* in, VipsImage** out);
int vipsgen_CMYK2XYZ(VipsImage* in, VipsImage** out);
int vipsgen_HSV2sRGB(VipsImage* in, VipsImage** out);
int vipsgen_LCh2CMC(VipsImage* in, VipsImage** out);
int vipsgen_LCh2Lab(VipsImage* in, VipsImage** out);
int vipsgen_Lab2LCh(VipsImage* in, VipsImage** out);
int vipsgen_Lab2LabQ(VipsImage* in, VipsImage** out);
int vipsgen_Lab2LabS(VipsImage* in, VipsImage** out);
int vipsgen_Lab2XYZ(VipsImage* in, VipsImage** out);
int vipsgen_Lab2XYZ_with_options(VipsImage* in, VipsImage** out, double* temp, int temp_n);
int vipsgen_LabQ2Lab(VipsImage* in, VipsImage** out);
int vipsgen_LabQ2LabS(VipsImage* in, VipsImage** out);
int vipsgen_LabQ2sRGB(VipsImage* in, VipsImage** out);
int vipsgen_LabS2Lab(VipsImage* in, VipsImage** out);
int vipsgen_LabS2LabQ(VipsImage* in, VipsImage** out);
int vipsgen_XYZ2CMYK(VipsImage* in, VipsImage** out);
int vipsgen_XYZ2Lab(VipsImage* in, VipsImage** out);
int vipsgen_XYZ2Lab_with_options(VipsImage* in, VipsImage** out, double* temp, int temp_n);
int vipsgen_XYZ2Yxy(VipsImage* in, VipsImage** out);
int vipsgen_XYZ2scRGB(VipsImage* in, VipsImage** out);
int vipsgen_Yxy2XYZ(VipsImage* in, VipsImage** out);
int vipsgen_abs(VipsImage* in, VipsImage** out);
int vipsgen_add(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_addalpha(VipsImage* in, VipsImage** out);
int vipsgen_affine(VipsImage* in, VipsImage** out, double a, double b, double c, double d);
int vipsgen_affine_with_options(VipsImage* in, VipsImage** out, double a, double b, double c, double d, VipsInterpolate* interpolate, int* oarea, int oarea_n, double odx, double ody, double idx, double idy, double* background, int background_n, gboolean premultiplied, VipsExtend extend);
int vipsgen_analyzeload(const char* filename, VipsImage** out);
int vipsgen_analyzeload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_arrayjoin(VipsImage** in, VipsImage** out, int n);
int vipsgen_arrayjoin_with_options(VipsImage** in, VipsImage** out, int n, gint across, gint shim, double* background, int background_n, VipsAlign halign, VipsAlign valign, gint hspacing, gint vspacing);
int vipsgen_autorot(VipsImage* in, VipsImage** out);
int vipsgen_autorot_with_options(VipsImage* in, VipsImage** out, gboolean* flip);
int vipsgen_avg(VipsImage* in, double* out);
int vipsgen_bandbool(VipsImage* in, VipsImage** out, VipsOperationBoolean boolean);
int vipsgen_bandfold(VipsImage* in, VipsImage** out);
int vipsgen_bandfold_with_options(VipsImage* in, VipsImage** out, gint factor);
int vipsgen_bandjoin(VipsImage** in, VipsImage** out, int n);
int vipsgen_bandjoin_const(VipsImage* in, VipsImage** out, double* c, int n);
int vipsgen_bandmean(VipsImage* in, VipsImage** out);
int vipsgen_bandrank(VipsImage** in, VipsImage** out, int n);
int vipsgen_bandrank_with_options(VipsImage** in, VipsImage** out, int n, gint index);
int vipsgen_bandunfold(VipsImage* in, VipsImage** out);
int vipsgen_bandunfold_with_options(VipsImage* in, VipsImage** out, gint factor);
int vipsgen_black(VipsImage** out, gint width, gint height);
int vipsgen_black_with_options(VipsImage** out, gint width, gint height, gint bands);
int vipsgen_boolean(VipsImage* left, VipsImage* right, VipsImage** out, VipsOperationBoolean boolean);
int vipsgen_boolean_const(VipsImage* in, VipsImage** out, VipsOperationBoolean boolean, double* c, int n);
int vipsgen_buildlut(VipsImage* in, VipsImage** out);
int vipsgen_byteswap(VipsImage* in, VipsImage** out);
int vipsgen_canny(VipsImage* in, VipsImage** out);
int vipsgen_canny_with_options(VipsImage* in, VipsImage** out, double sigma, VipsPrecision precision);
int vipsgen_case(VipsImage* index, VipsImage** cases, VipsImage** out, int n);
int vipsgen_cast(VipsImage* in, VipsImage** out, VipsBandFormat format);
int vipsgen_cast_with_options(VipsImage* in, VipsImage** out, VipsBandFormat format, gboolean shift);
int vipsgen_clamp(VipsImage* in, VipsImage** out);
int vipsgen_clamp_with_options(VipsImage* in, VipsImage** out, double min, double max);
int vipsgen_colourspace(VipsImage* in, VipsImage** out, VipsInterpretation space);
int vipsgen_colourspace_with_options(VipsImage* in, VipsImage** out, VipsInterpretation space, VipsInterpretation source_space);
int vipsgen_compass(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_compass_with_options(VipsImage* in, VipsImage** out, VipsImage* mask, gint times, VipsAngle45 angle, VipsCombine combine, VipsPrecision precision, gint layers, gint cluster);
int vipsgen_complex(VipsImage* in, VipsImage** out, VipsOperationComplex cmplx);
int vipsgen_complex2(VipsImage* left, VipsImage* right, VipsImage** out, VipsOperationComplex2 cmplx);
int vipsgen_complexform(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_complexget(VipsImage* in, VipsImage** out, VipsOperationComplexget get);
int vipsgen_composite(VipsImage** in, VipsImage** out, int n, int* mode);
int vipsgen_composite_with_options(VipsImage** in, VipsImage** out, int n, int* mode, int* x, int x_n, int* y, int y_n, VipsInterpretation compositing_space, gboolean premultiplied);
int vipsgen_composite2(VipsImage* base, VipsImage* overlay, VipsImage** out, VipsBlendMode mode);
int vipsgen_composite2_with_options(VipsImage* base, VipsImage* overlay, VipsImage** out, VipsBlendMode mode, gint x, gint y, VipsInterpretation compositing_space, gboolean premultiplied);
int vipsgen_conv(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_conv_with_options(VipsImage* in, VipsImage** out, VipsImage* mask, VipsPrecision precision, gint layers, gint cluster);
int vipsgen_conva(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_conva_with_options(VipsImage* in, VipsImage** out, VipsImage* mask, gint layers, gint cluster);
int vipsgen_convasep(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_convasep_with_options(VipsImage* in, VipsImage** out, VipsImage* mask, gint layers);
int vipsgen_convf(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_convi(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_convsep(VipsImage* in, VipsImage** out, VipsImage* mask);
int vipsgen_convsep_with_options(VipsImage* in, VipsImage** out, VipsImage* mask, VipsPrecision precision, gint layers, gint cluster);
int vipsgen_copy(VipsImage* in, VipsImage** out);
int vipsgen_copy_with_options(VipsImage* in, VipsImage** out, gint width, gint height, gint bands, VipsBandFormat format, VipsCoding coding, VipsInterpretation interpretation, double xres, double yres, gint xoffset, gint yoffset);
int vipsgen_countlines(VipsImage* in, double* nolines, VipsDirection direction);
int vipsgen_csvload(const char* filename, VipsImage** out);
int vipsgen_csvload_with_options(const char* filename, VipsImage** out, gint skip, gint lines, const char* whitespace, const char* separator, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_csvload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_csvload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint skip, gint lines, const char* whitespace, const char* separator, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_csvsave(VipsImage* in, const char* filename);
int vipsgen_csvsave_with_options(VipsImage* in, const char* filename, const char* separator, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_csvsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_csvsave_target_with_options(VipsImage* in, VipsTargetCustom* target, const char* separator, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_dE00(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_dE76(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_dECMC(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_deviate(VipsImage* in, double* out);
int vipsgen_divide(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_draw_circle(VipsImage* image, double* ink, int n, gint cx, gint cy, gint radius);
int vipsgen_draw_circle_with_options(VipsImage* image, double* ink, int n, gint cx, gint cy, gint radius, gboolean fill);
int vipsgen_draw_flood(VipsImage* image, double* ink, int n, gint x, gint y);
int vipsgen_draw_flood_with_options(VipsImage* image, double* ink, int n, gint x, gint y, VipsImage* test, gboolean equal, gint* left, gint* top, gint* width, gint* height);
int vipsgen_draw_image(VipsImage* image, VipsImage* sub, gint x, gint y);
int vipsgen_draw_image_with_options(VipsImage* image, VipsImage* sub, gint x, gint y, VipsCombineMode mode);
int vipsgen_draw_line(VipsImage* image, double* ink, int n, gint x1, gint y1, gint x2, gint y2);
int vipsgen_draw_mask(VipsImage* image, double* ink, int n, VipsImage* mask, gint x, gint y);
int vipsgen_draw_rect(VipsImage* image, double* ink, int n, gint left, gint top, gint width, gint height);
int vipsgen_draw_rect_with_options(VipsImage* image, double* ink, int n, gint left, gint top, gint width, gint height, gboolean fill);
int vipsgen_draw_smudge(VipsImage* image, gint left, gint top, gint width, gint height);
int vipsgen_dzsave(VipsImage* in, const char* filename);
int vipsgen_dzsave_with_options(VipsImage* in, const char* filename, const char* imagename, VipsForeignDzLayout layout, const char* suffix, gint overlap, gint tile_size, gboolean centre, VipsForeignDzDepth depth, VipsAngle angle, VipsForeignDzContainer container, gint compression, VipsRegionShrink region_shrink, gint skip_blanks, const char* id, gint Q, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_dzsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_dzsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, const char* imagename, VipsForeignDzLayout layout, const char* suffix, gint overlap, gint tile_size, gboolean centre, VipsForeignDzDepth depth, VipsAngle angle, VipsForeignDzContainer container, gint compression, VipsRegionShrink region_shrink, gint skip_blanks, const char* id, gint Q, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_dzsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_dzsave_target_with_options(VipsImage* in, VipsTargetCustom* target, const char* imagename, VipsForeignDzLayout layout, const char* suffix, gint overlap, gint tile_size, gboolean centre, VipsForeignDzDepth depth, VipsAngle angle, VipsForeignDzContainer container, gint compression, VipsRegionShrink region_shrink, gint skip_blanks, const char* id, gint Q, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_embed(VipsImage* in, VipsImage** out, gint x, gint y, gint width, gint height);
int vipsgen_embed_with_options(VipsImage* in, VipsImage** out, gint x, gint y, gint width, gint height, VipsExtend extend, double* background, int background_n);
int vipsgen_extract_area(VipsImage* input, VipsImage** out, gint left, gint top, gint width, gint height);
int vipsgen_extract_band(VipsImage* in, VipsImage** out, gint band);
int vipsgen_extract_band_with_options(VipsImage* in, VipsImage** out, gint band, gint n);
int vipsgen_eye(VipsImage** out, gint width, gint height);
int vipsgen_eye_with_options(VipsImage** out, gint width, gint height, gboolean uchar, double factor);
int vipsgen_falsecolour(VipsImage* in, VipsImage** out);
int vipsgen_fastcor(VipsImage* in, VipsImage* ref, VipsImage** out);
int vipsgen_fill_nearest(VipsImage* in, VipsImage** out);
int vipsgen_find_trim(VipsImage* in, gint* left, gint* top, gint* width, gint* height);
int vipsgen_find_trim_with_options(VipsImage* in, gint* left, gint* top, gint* width, gint* height, double threshold, double* background, int background_n, gboolean line_art);
int vipsgen_fitsload(const char* filename, VipsImage** out);
int vipsgen_fitsload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_fitssave(VipsImage* in, const char* filename);
int vipsgen_fitssave_with_options(VipsImage* in, const char* filename, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_flatten(VipsImage* in, VipsImage** out);
int vipsgen_flatten_with_options(VipsImage* in, VipsImage** out, double* background, int background_n, double max_alpha);
int vipsgen_flip(VipsImage* in, VipsImage** out, VipsDirection direction);
int vipsgen_float2rad(VipsImage* in, VipsImage** out);
int vipsgen_fractsurf(VipsImage** out, gint width, gint height, double fractal_dimension);
int vipsgen_freqmult(VipsImage* in, VipsImage* mask, VipsImage** out);
int vipsgen_fwfft(VipsImage* in, VipsImage** out);
int vipsgen_gamma(VipsImage* in, VipsImage** out);
int vipsgen_gamma_with_options(VipsImage* in, VipsImage** out, double exponent);
int vipsgen_gaussblur(VipsImage* in, VipsImage** out, double sigma);
int vipsgen_gaussblur_with_options(VipsImage* in, VipsImage** out, double sigma, double min_ampl, VipsPrecision precision);
int vipsgen_gaussmat(VipsImage** out, double sigma, double min_ampl);
int vipsgen_gaussmat_with_options(VipsImage** out, double sigma, double min_ampl, gboolean separable, VipsPrecision precision);
int vipsgen_gaussnoise(VipsImage** out, gint width, gint height);
int vipsgen_gaussnoise_with_options(VipsImage** out, gint width, gint height, double sigma, double mean, gint seed);
int vipsgen_getpoint(VipsImage* in, double** out_array, int* n, gint x, gint y);
int vipsgen_getpoint_with_options(VipsImage* in, double** out_array, int* n, gint x, gint y, gboolean unpack_complex);
int vipsgen_gifload(const char* filename, VipsImage** out);
int vipsgen_gifload_with_options(const char* filename, VipsImage** out, gint n, gint page, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_gifload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_gifload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint n, gint page, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_gifload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_gifload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint n, gint page, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_gifsave(VipsImage* in, const char* filename);
int vipsgen_gifsave_with_options(VipsImage* in, const char* filename, double dither, gint effort, gint bitdepth, double interframe_maxerror, gboolean reuse, double interpalette_maxerror, gboolean interlace, gboolean keep_duplicate_frames, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_gifsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_gifsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, double dither, gint effort, gint bitdepth, double interframe_maxerror, gboolean reuse, double interpalette_maxerror, gboolean interlace, gboolean keep_duplicate_frames, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_gifsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_gifsave_target_with_options(VipsImage* in, VipsTargetCustom* target, double dither, gint effort, gint bitdepth, double interframe_maxerror, gboolean reuse, double interpalette_maxerror, gboolean interlace, gboolean keep_duplicate_frames, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_globalbalance(VipsImage* in, VipsImage** out);
int vipsgen_globalbalance_with_options(VipsImage* in, VipsImage** out, double gamma, gboolean int_output);
int vipsgen_gravity(VipsImage* in, VipsImage** out, VipsCompassDirection direction, gint width, gint height);
int vipsgen_gravity_with_options(VipsImage* in, VipsImage** out, VipsCompassDirection direction, gint width, gint height, VipsExtend extend, double* background, int background_n);
int vipsgen_grey(VipsImage** out, gint width, gint height);
int vipsgen_grey_with_options(VipsImage** out, gint width, gint height, gboolean uchar);
int vipsgen_grid(VipsImage* in, VipsImage** out, gint tile_height, gint across, gint down);
int vipsgen_heifload(const char* filename, VipsImage** out);
int vipsgen_heifload_with_options(const char* filename, VipsImage** out, gint page, gint n, gboolean thumbnail, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_heifload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_heifload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint page, gint n, gboolean thumbnail, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_heifload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_heifload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint page, gint n, gboolean thumbnail, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_heifsave(VipsImage* in, const char* filename);
int vipsgen_heifsave_with_options(VipsImage* in, const char* filename, gint Q, gint bitdepth, gboolean lossless, VipsForeignHeifCompression compression, gint effort, VipsForeignSubsample subsample_mode, VipsForeignHeifEncoder encoder, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_heifsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_heifsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, gint Q, gint bitdepth, gboolean lossless, VipsForeignHeifCompression compression, gint effort, VipsForeignSubsample subsample_mode, VipsForeignHeifEncoder encoder, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_heifsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_heifsave_target_with_options(VipsImage* in, VipsTargetCustom* target, gint Q, gint bitdepth, gboolean lossless, VipsForeignHeifCompression compression, gint effort, VipsForeignSubsample subsample_mode, VipsForeignHeifEncoder encoder, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_hist_cum(VipsImage* in, VipsImage** out);
int vipsgen_hist_entropy(VipsImage* in, double* out);
int vipsgen_hist_equal(VipsImage* in, VipsImage** out);
int vipsgen_hist_equal_with_options(VipsImage* in, VipsImage** out, gint band);
int vipsgen_hist_find(VipsImage* in, VipsImage** out);
int vipsgen_hist_find_with_options(VipsImage* in, VipsImage** out, gint band);
int vipsgen_hist_find_indexed(VipsImage* in, VipsImage* index, VipsImage** out);
int vipsgen_hist_find_indexed_with_options(VipsImage* in, VipsImage* index, VipsImage** out, VipsCombine combine);
int vipsgen_hist_find_ndim(VipsImage* in, VipsImage** out);
int vipsgen_hist_find_ndim_with_options(VipsImage* in, VipsImage** out, gint bins);
int vipsgen_hist_ismonotonic(VipsImage* in, gboolean* monotonic);
int vipsgen_hist_local(VipsImage* in, VipsImage** out, gint width, gint height);
int vipsgen_hist_local_with_options(VipsImage* in, VipsImage** out, gint width, gint height, gint max_slope);
int vipsgen_hist_match(VipsImage* in, VipsImage* ref, VipsImage** out);
int vipsgen_hist_norm(VipsImage* in, VipsImage** out);
int vipsgen_hist_plot(VipsImage* in, VipsImage** out);
int vipsgen_hough_circle(VipsImage* in, VipsImage** out);
int vipsgen_hough_circle_with_options(VipsImage* in, VipsImage** out, gint scale, gint min_radius, gint max_radius);
int vipsgen_hough_line(VipsImage* in, VipsImage** out);
int vipsgen_hough_line_with_options(VipsImage* in, VipsImage** out, gint width, gint height);
int vipsgen_icc_export(VipsImage* in, VipsImage** out);
int vipsgen_icc_export_with_options(VipsImage* in, VipsImage** out, VipsPCS pcs, VipsIntent intent, gboolean black_point_compensation, const char* output_profile, gint depth);
int vipsgen_icc_import(VipsImage* in, VipsImage** out);
int vipsgen_icc_import_with_options(VipsImage* in, VipsImage** out, VipsPCS pcs, VipsIntent intent, gboolean black_point_compensation, gboolean embedded, const char* input_profile);
int vipsgen_icc_transform(VipsImage* in, VipsImage** out, const char* output_profile);
int vipsgen_icc_transform_with_options(VipsImage* in, VipsImage** out, const char* output_profile, VipsPCS pcs, VipsIntent intent, gboolean black_point_compensation, gboolean embedded, const char* input_profile, gint depth);
int vipsgen_identity(VipsImage** out);
int vipsgen_identity_with_options(VipsImage** out, gint bands, gboolean ushort, gint size);
int vipsgen_ifthenelse(VipsImage* cond, VipsImage* in1, VipsImage* in2, VipsImage** out);
int vipsgen_ifthenelse_with_options(VipsImage* cond, VipsImage* in1, VipsImage* in2, VipsImage** out, gboolean blend);
int vipsgen_insert(VipsImage* main, VipsImage* sub, VipsImage** out, gint x, gint y);
int vipsgen_insert_with_options(VipsImage* main, VipsImage* sub, VipsImage** out, gint x, gint y, gboolean expand, double* background, int background_n);
int vipsgen_invert(VipsImage* in, VipsImage** out);
int vipsgen_invertlut(VipsImage* in, VipsImage** out);
int vipsgen_invertlut_with_options(VipsImage* in, VipsImage** out, gint size);
int vipsgen_invfft(VipsImage* in, VipsImage** out);
int vipsgen_invfft_with_options(VipsImage* in, VipsImage** out, gboolean real);
int vipsgen_join(VipsImage* in1, VipsImage* in2, VipsImage** out, VipsDirection direction);
int vipsgen_join_with_options(VipsImage* in1, VipsImage* in2, VipsImage** out, VipsDirection direction, gboolean expand, gint shim, double* background, int background_n, VipsAlign align);
int vipsgen_jp2kload(const char* filename, VipsImage** out);
int vipsgen_jp2kload_with_options(const char* filename, VipsImage** out, gint page, gboolean oneshot, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jp2kload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_jp2kload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint page, gboolean oneshot, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jp2kload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_jp2kload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint page, gboolean oneshot, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jp2ksave(VipsImage* in, const char* filename);
int vipsgen_jp2ksave_with_options(VipsImage* in, const char* filename, gint tile_width, gint tile_height, gboolean lossless, gint Q, VipsForeignSubsample subsample_mode, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jp2ksave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_jp2ksave_buffer_with_options(VipsImage* in, void** buf, size_t* len, gint tile_width, gint tile_height, gboolean lossless, gint Q, VipsForeignSubsample subsample_mode, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jp2ksave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_jp2ksave_target_with_options(VipsImage* in, VipsTargetCustom* target, gint tile_width, gint tile_height, gboolean lossless, gint Q, VipsForeignSubsample subsample_mode, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jpegload(const char* filename, VipsImage** out);
int vipsgen_jpegload_with_options(const char* filename, VipsImage** out, gint shrink, gboolean autorotate, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jpegload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_jpegload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint shrink, gboolean autorotate, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jpegload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_jpegload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint shrink, gboolean autorotate, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jpegsave(VipsImage* in, const char* filename);
int vipsgen_jpegsave_with_options(VipsImage* in, const char* filename, gint Q, gboolean optimize_coding, gboolean interlace, gboolean trellis_quant, gboolean overshoot_deringing, gboolean optimize_scans, gint quant_table, VipsForeignSubsample subsample_mode, gint restart_interval, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jpegsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_jpegsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, gint Q, gboolean optimize_coding, gboolean interlace, gboolean trellis_quant, gboolean overshoot_deringing, gboolean optimize_scans, gint quant_table, VipsForeignSubsample subsample_mode, gint restart_interval, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jpegsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_jpegsave_target_with_options(VipsImage* in, VipsTargetCustom* target, gint Q, gboolean optimize_coding, gboolean interlace, gboolean trellis_quant, gboolean overshoot_deringing, gboolean optimize_scans, gint quant_table, VipsForeignSubsample subsample_mode, gint restart_interval, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jxlload(const char* filename, VipsImage** out);
int vipsgen_jxlload_with_options(const char* filename, VipsImage** out, gint page, gint n, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jxlload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_jxlload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint page, gint n, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jxlload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_jxlload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint page, gint n, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_jxlsave(VipsImage* in, const char* filename);
int vipsgen_jxlsave_with_options(VipsImage* in, const char* filename, gint tier, double distance, gint effort, gboolean lossless, gint Q, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jxlsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_jxlsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, gint tier, double distance, gint effort, gboolean lossless, gint Q, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_jxlsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_jxlsave_target_with_options(VipsImage* in, VipsTargetCustom* target, gint tier, double distance, gint effort, gboolean lossless, gint Q, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_labelregions(VipsImage* in, VipsImage** mask);
int vipsgen_labelregions_with_options(VipsImage* in, VipsImage** mask, gint* segments);
int vipsgen_linear(VipsImage* in, VipsImage** out, double* a, double* b, int n);
int vipsgen_linear_with_options(VipsImage* in, VipsImage** out, double* a, double* b, int n, gboolean uchar);
int vipsgen_linecache(VipsImage* in, VipsImage** out);
int vipsgen_linecache_with_options(VipsImage* in, VipsImage** out, gint tile_height, VipsAccess access, gboolean threaded, gboolean persistent);
int vipsgen_logmat(VipsImage** out, double sigma, double min_ampl);
int vipsgen_logmat_with_options(VipsImage** out, double sigma, double min_ampl, gboolean separable, VipsPrecision precision);
int vipsgen_magickload(const char* filename, VipsImage** out);
int vipsgen_magickload_with_options(const char* filename, VipsImage** out, const char* density, gint page, gint n, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_magickload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_magickload_buffer_with_options(void* buf, size_t len, VipsImage** out, const char* density, gint page, gint n, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_magicksave(VipsImage* in, const char* filename);
int vipsgen_magicksave_with_options(VipsImage* in, const char* filename, const char* format, gint quality, gboolean optimize_gif_frames, gboolean optimize_gif_transparency, gint bitdepth, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_magicksave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_magicksave_buffer_with_options(VipsImage* in, void** buf, size_t* len, const char* format, gint quality, gboolean optimize_gif_frames, gboolean optimize_gif_transparency, gint bitdepth, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_mapim(VipsImage* in, VipsImage** out, VipsImage* index);
int vipsgen_mapim_with_options(VipsImage* in, VipsImage** out, VipsImage* index, VipsInterpolate* interpolate, double* background, int background_n, gboolean premultiplied, VipsExtend extend);
int vipsgen_maplut(VipsImage* in, VipsImage** out, VipsImage* lut);
int vipsgen_maplut_with_options(VipsImage* in, VipsImage** out, VipsImage* lut, gint band);
int vipsgen_mask_butterworth(VipsImage** out, gint width, gint height, double order, double frequency_cutoff, double amplitude_cutoff);
int vipsgen_mask_butterworth_with_options(VipsImage** out, gint width, gint height, double order, double frequency_cutoff, double amplitude_cutoff, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_butterworth_band(VipsImage** out, gint width, gint height, double order, double frequency_cutoff_x, double frequency_cutoff_y, double radius, double amplitude_cutoff);
int vipsgen_mask_butterworth_band_with_options(VipsImage** out, gint width, gint height, double order, double frequency_cutoff_x, double frequency_cutoff_y, double radius, double amplitude_cutoff, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_butterworth_ring(VipsImage** out, gint width, gint height, double order, double frequency_cutoff, double amplitude_cutoff, double ringwidth);
int vipsgen_mask_butterworth_ring_with_options(VipsImage** out, gint width, gint height, double order, double frequency_cutoff, double amplitude_cutoff, double ringwidth, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_fractal(VipsImage** out, gint width, gint height, double fractal_dimension);
int vipsgen_mask_fractal_with_options(VipsImage** out, gint width, gint height, double fractal_dimension, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_gaussian(VipsImage** out, gint width, gint height, double frequency_cutoff, double amplitude_cutoff);
int vipsgen_mask_gaussian_with_options(VipsImage** out, gint width, gint height, double frequency_cutoff, double amplitude_cutoff, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_gaussian_band(VipsImage** out, gint width, gint height, double frequency_cutoff_x, double frequency_cutoff_y, double radius, double amplitude_cutoff);
int vipsgen_mask_gaussian_band_with_options(VipsImage** out, gint width, gint height, double frequency_cutoff_x, double frequency_cutoff_y, double radius, double amplitude_cutoff, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_gaussian_ring(VipsImage** out, gint width, gint height, double frequency_cutoff, double amplitude_cutoff, double ringwidth);
int vipsgen_mask_gaussian_ring_with_options(VipsImage** out, gint width, gint height, double frequency_cutoff, double amplitude_cutoff, double ringwidth, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_ideal(VipsImage** out, gint width, gint height, double frequency_cutoff);
int vipsgen_mask_ideal_with_options(VipsImage** out, gint width, gint height, double frequency_cutoff, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_ideal_band(VipsImage** out, gint width, gint height, double frequency_cutoff_x, double frequency_cutoff_y, double radius);
int vipsgen_mask_ideal_band_with_options(VipsImage** out, gint width, gint height, double frequency_cutoff_x, double frequency_cutoff_y, double radius, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_mask_ideal_ring(VipsImage** out, gint width, gint height, double frequency_cutoff, double ringwidth);
int vipsgen_mask_ideal_ring_with_options(VipsImage** out, gint width, gint height, double frequency_cutoff, double ringwidth, gboolean uchar, gboolean nodc, gboolean reject, gboolean optical);
int vipsgen_match(VipsImage* ref, VipsImage* sec, VipsImage** out, gint xr1, gint yr1, gint xs1, gint ys1, gint xr2, gint yr2, gint xs2, gint ys2);
int vipsgen_match_with_options(VipsImage* ref, VipsImage* sec, VipsImage** out, gint xr1, gint yr1, gint xs1, gint ys1, gint xr2, gint yr2, gint xs2, gint ys2, gint hwindow, gint harea, gboolean search, VipsInterpolate* interpolate);
int vipsgen_math(VipsImage* in, VipsImage** out, VipsOperationMath math);
int vipsgen_math2(VipsImage* left, VipsImage* right, VipsImage** out, VipsOperationMath2 math2);
int vipsgen_math2_const(VipsImage* in, VipsImage** out, VipsOperationMath2 math2, double* c, int n);
int vipsgen_matload(const char* filename, VipsImage** out);
int vipsgen_matload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_matrixinvert(VipsImage* in, VipsImage** out);
int vipsgen_matrixload(const char* filename, VipsImage** out);
int vipsgen_matrixload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_matrixload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_matrixload_source_with_options(VipsSourceCustom* source, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_matrixmultiply(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_matrixprint(VipsImage* in);
int vipsgen_matrixprint_with_options(VipsImage* in, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_matrixsave(VipsImage* in, const char* filename);
int vipsgen_matrixsave_with_options(VipsImage* in, const char* filename, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_matrixsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_matrixsave_target_with_options(VipsImage* in, VipsTargetCustom* target, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_max(VipsImage* in, double* out);
int vipsgen_max_with_options(VipsImage* in, double* out, gint size, gint* x, gint* y);
int vipsgen_maxpair(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_measure(VipsImage* in, VipsImage** out, gint h, gint v);
int vipsgen_measure_with_options(VipsImage* in, VipsImage** out, gint h, gint v, gint left, gint top, gint width, gint height);
int vipsgen_merge(VipsImage* ref, VipsImage* sec, VipsImage** out, VipsDirection direction, gint dx, gint dy);
int vipsgen_merge_with_options(VipsImage* ref, VipsImage* sec, VipsImage** out, VipsDirection direction, gint dx, gint dy, gint mblend);
int vipsgen_min(VipsImage* in, double* out);
int vipsgen_min_with_options(VipsImage* in, double* out, gint size, gint* x, gint* y);
int vipsgen_minpair(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_morph(VipsImage* in, VipsImage** out, VipsImage* mask, VipsOperationMorphology morph);
int vipsgen_mosaic(VipsImage* ref, VipsImage* sec, VipsImage** out, VipsDirection direction, gint xref, gint yref, gint xsec, gint ysec);
int vipsgen_mosaic_with_options(VipsImage* ref, VipsImage* sec, VipsImage** out, VipsDirection direction, gint xref, gint yref, gint xsec, gint ysec, gint hwindow, gint harea, gint mblend, gint bandno, gint* dx0, gint* dy0, double* scale1, double* angle1, double* dy1, double* dx1);
int vipsgen_mosaic1(VipsImage* ref, VipsImage* sec, VipsImage** out, VipsDirection direction, gint xr1, gint yr1, gint xs1, gint ys1, gint xr2, gint yr2, gint xs2, gint ys2);
int vipsgen_mosaic1_with_options(VipsImage* ref, VipsImage* sec, VipsImage** out, VipsDirection direction, gint xr1, gint yr1, gint xs1, gint ys1, gint xr2, gint yr2, gint xs2, gint ys2, gint hwindow, gint harea, gboolean search, VipsInterpolate* interpolate, gint mblend);
int vipsgen_msb(VipsImage* in, VipsImage** out);
int vipsgen_msb_with_options(VipsImage* in, VipsImage** out, gint band);
int vipsgen_multiply(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_niftiload(const char* filename, VipsImage** out);
int vipsgen_niftiload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_niftiload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_niftiload_source_with_options(VipsSourceCustom* source, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_niftisave(VipsImage* in, const char* filename);
int vipsgen_niftisave_with_options(VipsImage* in, const char* filename, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_openexrload(const char* filename, VipsImage** out);
int vipsgen_openexrload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_openslideload(const char* filename, VipsImage** out);
int vipsgen_openslideload_with_options(const char* filename, VipsImage** out, gint level, gboolean autocrop, const char* associated, gboolean attach_associated, gboolean rgb, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_openslideload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_openslideload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint level, gboolean autocrop, const char* associated, gboolean attach_associated, gboolean rgb, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_pdfload(const char* filename, VipsImage** out);
int vipsgen_pdfload_with_options(const char* filename, VipsImage** out, gint page, gint n, double dpi, double scale, double* background, int background_n, const char* password, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_pdfload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_pdfload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint page, gint n, double dpi, double scale, double* background, int background_n, const char* password, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_pdfload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_pdfload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint page, gint n, double dpi, double scale, double* background, int background_n, const char* password, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_percent(VipsImage* in, double percent, gint* threshold);
int vipsgen_perlin(VipsImage** out, gint width, gint height);
int vipsgen_perlin_with_options(VipsImage** out, gint width, gint height, gint cell_size, gboolean uchar, gint seed);
int vipsgen_phasecor(VipsImage* in, VipsImage* in2, VipsImage** out);
int vipsgen_pngload(const char* filename, VipsImage** out);
int vipsgen_pngload_with_options(const char* filename, VipsImage** out, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_pngload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_pngload_buffer_with_options(void* buf, size_t len, VipsImage** out, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_pngload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_pngload_source_with_options(VipsSourceCustom* source, VipsImage** out, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_pngsave(VipsImage* in, const char* filename);
int vipsgen_pngsave_with_options(VipsImage* in, const char* filename, gint compression, gboolean interlace, VipsForeignPngFilter filter, gboolean palette, gint Q, double dither, gint bitdepth, gint effort, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_pngsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_pngsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, gint compression, gboolean interlace, VipsForeignPngFilter filter, gboolean palette, gint Q, double dither, gint bitdepth, gint effort, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_pngsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_pngsave_target_with_options(VipsImage* in, VipsTargetCustom* target, gint compression, gboolean interlace, VipsForeignPngFilter filter, gboolean palette, gint Q, double dither, gint bitdepth, gint effort, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_ppmload(const char* filename, VipsImage** out);
int vipsgen_ppmload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_ppmload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_ppmload_buffer_with_options(void* buf, size_t len, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_ppmload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_ppmload_source_with_options(VipsSourceCustom* source, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_ppmsave(VipsImage* in, const char* filename);
int vipsgen_ppmsave_with_options(VipsImage* in, const char* filename, VipsForeignPpmFormat format, gboolean ascii, gint bitdepth, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_ppmsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_ppmsave_target_with_options(VipsImage* in, VipsTargetCustom* target, VipsForeignPpmFormat format, gboolean ascii, gint bitdepth, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_premultiply(VipsImage* in, VipsImage** out);
int vipsgen_premultiply_with_options(VipsImage* in, VipsImage** out, double max_alpha);
int vipsgen_prewitt(VipsImage* in, VipsImage** out);
int vipsgen_profile(VipsImage* in, VipsImage** columns, VipsImage** rows);
int vipsgen_profile_load(const char* name, VipsBlob** profile);
int vipsgen_project(VipsImage* in, VipsImage** columns, VipsImage** rows);
int vipsgen_quadratic(VipsImage* in, VipsImage** out, VipsImage* coeff);
int vipsgen_quadratic_with_options(VipsImage* in, VipsImage** out, VipsImage* coeff, VipsInterpolate* interpolate);
int vipsgen_rad2float(VipsImage* in, VipsImage** out);
int vipsgen_radload(const char* filename, VipsImage** out);
int vipsgen_radload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_radload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_radload_buffer_with_options(void* buf, size_t len, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_radload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_radload_source_with_options(VipsSourceCustom* source, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_radsave(VipsImage* in, const char* filename);
int vipsgen_radsave_with_options(VipsImage* in, const char* filename, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_radsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_radsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_radsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_radsave_target_with_options(VipsImage* in, VipsTargetCustom* target, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_rank(VipsImage* in, VipsImage** out, gint width, gint height, gint index);
int vipsgen_rawload(const char* filename, VipsImage** out, gint width, gint height, gint bands);
int vipsgen_rawload_with_options(const char* filename, VipsImage** out, gint width, gint height, gint bands, guint64 offset, VipsBandFormat format, VipsInterpretation interpretation, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_rawsave(VipsImage* in, const char* filename);
int vipsgen_rawsave_with_options(VipsImage* in, const char* filename, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_rawsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_rawsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_rawsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_rawsave_target_with_options(VipsImage* in, VipsTargetCustom* target, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_recomb(VipsImage* in, VipsImage** out, VipsImage* m);
int vipsgen_reduce(VipsImage* in, VipsImage** out, double hshrink, double vshrink);
int vipsgen_reduce_with_options(VipsImage* in, VipsImage** out, double hshrink, double vshrink, VipsKernel kernel, double gap);
int vipsgen_reduceh(VipsImage* in, VipsImage** out, double hshrink);
int vipsgen_reduceh_with_options(VipsImage* in, VipsImage** out, double hshrink, VipsKernel kernel, double gap);
int vipsgen_reducev(VipsImage* in, VipsImage** out, double vshrink);
int vipsgen_reducev_with_options(VipsImage* in, VipsImage** out, double vshrink, VipsKernel kernel, double gap);
int vipsgen_relational(VipsImage* left, VipsImage* right, VipsImage** out, VipsOperationRelational relational);
int vipsgen_relational_const(VipsImage* in, VipsImage** out, VipsOperationRelational relational, double* c, int n);
int vipsgen_remainder(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_remainder_const(VipsImage* in, VipsImage** out, double* c, int n);
int vipsgen_remosaic(VipsImage* in, VipsImage** out, const char* old_str, const char* new_str);
int vipsgen_replicate(VipsImage* in, VipsImage** out, gint across, gint down);
int vipsgen_resize(VipsImage* in, VipsImage** out, double scale);
int vipsgen_resize_with_options(VipsImage* in, VipsImage** out, double scale, VipsKernel kernel, double gap, double vscale);
int vipsgen_rot(VipsImage* in, VipsImage** out, VipsAngle angle);
int vipsgen_rot45(VipsImage* in, VipsImage** out);
int vipsgen_rot45_with_options(VipsImage* in, VipsImage** out, VipsAngle45 angle);
int vipsgen_rotate(VipsImage* in, VipsImage** out, double angle);
int vipsgen_rotate_with_options(VipsImage* in, VipsImage** out, double angle, VipsInterpolate* interpolate, double* background, int background_n, double odx, double ody, double idx, double idy);
int vipsgen_round(VipsImage* in, VipsImage** out, VipsOperationRound round);
int vipsgen_sRGB2HSV(VipsImage* in, VipsImage** out);
int vipsgen_sRGB2scRGB(VipsImage* in, VipsImage** out);
int vipsgen_scRGB2BW(VipsImage* in, VipsImage** out);
int vipsgen_scRGB2BW_with_options(VipsImage* in, VipsImage** out, gint depth);
int vipsgen_scRGB2XYZ(VipsImage* in, VipsImage** out);
int vipsgen_scRGB2sRGB(VipsImage* in, VipsImage** out);
int vipsgen_scRGB2sRGB_with_options(VipsImage* in, VipsImage** out, gint depth);
int vipsgen_scale(VipsImage* in, VipsImage** out);
int vipsgen_scale_with_options(VipsImage* in, VipsImage** out, double exp, gboolean log);
int vipsgen_scharr(VipsImage* in, VipsImage** out);
int vipsgen_sdf(VipsImage** out, gint width, gint height, VipsSdfShape shape);
int vipsgen_sdf_with_options(VipsImage** out, gint width, gint height, VipsSdfShape shape, double r, double* a, int a_n, double* b, int b_n, double* corners, int corners_n);
int vipsgen_sequential(VipsImage* in, VipsImage** out);
int vipsgen_sequential_with_options(VipsImage* in, VipsImage** out, gint tile_height);
int vipsgen_sharpen(VipsImage* in, VipsImage** out);
int vipsgen_sharpen_with_options(VipsImage* in, VipsImage** out, double sigma, double x1, double y2, double y3, double m1, double m2);
int vipsgen_shrink(VipsImage* in, VipsImage** out, double hshrink, double vshrink);
int vipsgen_shrink_with_options(VipsImage* in, VipsImage** out, double hshrink, double vshrink, gboolean ceil);
int vipsgen_shrinkh(VipsImage* in, VipsImage** out, gint hshrink);
int vipsgen_shrinkh_with_options(VipsImage* in, VipsImage** out, gint hshrink, gboolean ceil);
int vipsgen_shrinkv(VipsImage* in, VipsImage** out, gint vshrink);
int vipsgen_shrinkv_with_options(VipsImage* in, VipsImage** out, gint vshrink, gboolean ceil);
int vipsgen_sign(VipsImage* in, VipsImage** out);
int vipsgen_similarity(VipsImage* in, VipsImage** out);
int vipsgen_similarity_with_options(VipsImage* in, VipsImage** out, double scale, double angle, VipsInterpolate* interpolate, double* background, int background_n, double odx, double ody, double idx, double idy);
int vipsgen_sines(VipsImage** out, gint width, gint height);
int vipsgen_sines_with_options(VipsImage** out, gint width, gint height, gboolean uchar, double hfreq, double vfreq);
int vipsgen_smartcrop(VipsImage* input, VipsImage** out, gint width, gint height);
int vipsgen_smartcrop_with_options(VipsImage* input, VipsImage** out, gint width, gint height, VipsInteresting interesting, gboolean premultiplied, gint* attention_x, gint* attention_y);
int vipsgen_sobel(VipsImage* in, VipsImage** out);
int vipsgen_spcor(VipsImage* in, VipsImage* ref, VipsImage** out);
int vipsgen_spectrum(VipsImage* in, VipsImage** out);
int vipsgen_stats(VipsImage* in, VipsImage** out);
int vipsgen_stdif(VipsImage* in, VipsImage** out, gint width, gint height);
int vipsgen_stdif_with_options(VipsImage* in, VipsImage** out, gint width, gint height, double s0, double b, double m0, double a);
int vipsgen_subsample(VipsImage* input, VipsImage** out, gint xfac, gint yfac);
int vipsgen_subsample_with_options(VipsImage* input, VipsImage** out, gint xfac, gint yfac, gboolean point);
int vipsgen_subtract(VipsImage* left, VipsImage* right, VipsImage** out);
int vipsgen_sum(VipsImage** in, VipsImage** out, int n);
int vipsgen_svgload(const char* filename, VipsImage** out);
int vipsgen_svgload_with_options(const char* filename, VipsImage** out, double dpi, double scale, gboolean unlimited, const char* stylesheet, gboolean high_bitdepth, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_svgload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_svgload_buffer_with_options(void* buf, size_t len, VipsImage** out, double dpi, double scale, gboolean unlimited, const char* stylesheet, gboolean high_bitdepth, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_svgload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_svgload_source_with_options(VipsSourceCustom* source, VipsImage** out, double dpi, double scale, gboolean unlimited, const char* stylesheet, gboolean high_bitdepth, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_switch(VipsImage** tests, VipsImage** out, int n);
int vipsgen_system(const char* cmd_format);
int vipsgen_system_with_options(const char* cmd_format, VipsImage** in, int in_n, const char* out_format, const char* in_format);
int vipsgen_text(VipsImage** out, const char* text);
int vipsgen_text_with_options(VipsImage** out, const char* text, const char* font, gint width, gint height, VipsAlign align, gboolean justify, gint dpi, gint spacing, const char* fontfile, gboolean rgba, VipsTextWrap wrap, gint* autofit_dpi);
int vipsgen_thumbnail(const char* filename, VipsImage** out, gint width);
int vipsgen_thumbnail_with_options(const char* filename, VipsImage** out, gint width, gint height, VipsSize size, gboolean no_rotate, VipsInteresting crop, gboolean linear, const char* input_profile, const char* output_profile, VipsIntent intent, VipsFailOn fail_on);
int vipsgen_thumbnail_buffer(void* buf, size_t len, VipsImage** out, gint width);
int vipsgen_thumbnail_buffer_with_options(void* buf, size_t len, VipsImage** out, gint width, const char* option_string, gint height, VipsSize size, gboolean no_rotate, VipsInteresting crop, gboolean linear, const char* input_profile, const char* output_profile, VipsIntent intent, VipsFailOn fail_on);
int vipsgen_thumbnail_image(VipsImage* in, VipsImage** out, gint width);
int vipsgen_thumbnail_image_with_options(VipsImage* in, VipsImage** out, gint width, gint height, VipsSize size, gboolean no_rotate, VipsInteresting crop, gboolean linear, const char* input_profile, const char* output_profile, VipsIntent intent, VipsFailOn fail_on);
int vipsgen_thumbnail_source(VipsSourceCustom* source, VipsImage** out, gint width);
int vipsgen_thumbnail_source_with_options(VipsSourceCustom* source, VipsImage** out, gint width, const char* option_string, gint height, VipsSize size, gboolean no_rotate, VipsInteresting crop, gboolean linear, const char* input_profile, const char* output_profile, VipsIntent intent, VipsFailOn fail_on);
int vipsgen_tiffload(const char* filename, VipsImage** out);
int vipsgen_tiffload_with_options(const char* filename, VipsImage** out, gint page, gint n, gboolean autorotate, gint subifd, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_tiffload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_tiffload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint page, gint n, gboolean autorotate, gint subifd, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_tiffload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_tiffload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint page, gint n, gboolean autorotate, gint subifd, gboolean unlimited, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_tiffsave(VipsImage* in, const char* filename);
int vipsgen_tiffsave_with_options(VipsImage* in, const char* filename, VipsForeignTiffCompression compression, gint Q, VipsForeignTiffPredictor predictor, gboolean tile, gint tile_width, gint tile_height, gboolean pyramid, gboolean miniswhite, gint bitdepth, VipsForeignTiffResunit resunit, double xres, double yres, gboolean bigtiff, gboolean properties, VipsRegionShrink region_shrink, gint level, gboolean lossless, VipsForeignDzDepth depth, gboolean subifd, gboolean premultiply, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_tiffsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_tiffsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, VipsForeignTiffCompression compression, gint Q, VipsForeignTiffPredictor predictor, gboolean tile, gint tile_width, gint tile_height, gboolean pyramid, gboolean miniswhite, gint bitdepth, VipsForeignTiffResunit resunit, double xres, double yres, gboolean bigtiff, gboolean properties, VipsRegionShrink region_shrink, gint level, gboolean lossless, VipsForeignDzDepth depth, gboolean subifd, gboolean premultiply, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_tiffsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_tiffsave_target_with_options(VipsImage* in, VipsTargetCustom* target, VipsForeignTiffCompression compression, gint Q, VipsForeignTiffPredictor predictor, gboolean tile, gint tile_width, gint tile_height, gboolean pyramid, gboolean miniswhite, gint bitdepth, VipsForeignTiffResunit resunit, double xres, double yres, gboolean bigtiff, gboolean properties, VipsRegionShrink region_shrink, gint level, gboolean lossless, VipsForeignDzDepth depth, gboolean subifd, gboolean premultiply, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_tilecache(VipsImage* in, VipsImage** out);
int vipsgen_tilecache_with_options(VipsImage* in, VipsImage** out, gint tile_width, gint tile_height, gint max_tiles, VipsAccess access, gboolean threaded, gboolean persistent);
int vipsgen_tonelut(VipsImage** out);
int vipsgen_tonelut_with_options(VipsImage** out, gint in_max, gint out_max, double Lb, double Lw, double Ps, double Pm, double Ph, double S, double M, double H);
int vipsgen_transpose3d(VipsImage* in, VipsImage** out);
int vipsgen_transpose3d_with_options(VipsImage* in, VipsImage** out, gint page_height);
int vipsgen_unpremultiply(VipsImage* in, VipsImage** out);
int vipsgen_unpremultiply_with_options(VipsImage* in, VipsImage** out, double max_alpha, gint alpha_band);
int vipsgen_vipsload(const char* filename, VipsImage** out);
int vipsgen_vipsload_with_options(const char* filename, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_vipsload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_vipsload_source_with_options(VipsSourceCustom* source, VipsImage** out, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_vipssave(VipsImage* in, const char* filename);
int vipsgen_vipssave_with_options(VipsImage* in, const char* filename, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_vipssave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_vipssave_target_with_options(VipsImage* in, VipsTargetCustom* target, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_webpload(const char* filename, VipsImage** out);
int vipsgen_webpload_with_options(const char* filename, VipsImage** out, gint page, gint n, double scale, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_webpload_buffer(void* buf, size_t len, VipsImage** out);
int vipsgen_webpload_buffer_with_options(void* buf, size_t len, VipsImage** out, gint page, gint n, double scale, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_webpload_source(VipsSourceCustom* source, VipsImage** out);
int vipsgen_webpload_source_with_options(VipsSourceCustom* source, VipsImage** out, gint page, gint n, double scale, gboolean memory, VipsAccess access, VipsFailOn fail_on, gboolean revalidate);
int vipsgen_webpsave(VipsImage* in, const char* filename);
int vipsgen_webpsave_with_options(VipsImage* in, const char* filename, gint Q, gboolean lossless, VipsForeignWebpPreset preset, gboolean smart_subsample, gboolean near_lossless, gint alpha_q, gboolean min_size, gint kmin, gint kmax, gint effort, gint target_size, gboolean mixed, gboolean smart_deblock, gint passes, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_webpsave_buffer(VipsImage* in, void** buf, size_t* len);
int vipsgen_webpsave_buffer_with_options(VipsImage* in, void** buf, size_t* len, gint Q, gboolean lossless, VipsForeignWebpPreset preset, gboolean smart_subsample, gboolean near_lossless, gint alpha_q, gboolean min_size, gint kmin, gint kmax, gint effort, gint target_size, gboolean mixed, gboolean smart_deblock, gint passes, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_webpsave_target(VipsImage* in, VipsTargetCustom* target);
int vipsgen_webpsave_target_with_options(VipsImage* in, VipsTargetCustom* target, gint Q, gboolean lossless, VipsForeignWebpPreset preset, gboolean smart_subsample, gboolean near_lossless, gint alpha_q, gboolean min_size, gint kmin, gint kmax, gint effort, gint target_size, gboolean mixed, gboolean smart_deblock, gint passes, VipsForeignKeep keep, double* background, int background_n, gint page_height, const char* profile);
int vipsgen_worley(VipsImage** out, gint width, gint height);
int vipsgen_worley_with_options(VipsImage** out, gint width, gint height, gint cell_size, gint seed);
int vipsgen_wrap(VipsImage* in, VipsImage** out);
int vipsgen_wrap_with_options(VipsImage* in, VipsImage** out, gint x, gint y);
int vipsgen_xyz(VipsImage** out, gint width, gint height);
int vipsgen_xyz_with_options(VipsImage** out, gint width, gint height, gint csize, gint dsize, gint esize);
int vipsgen_zone(VipsImage** out, gint width, gint height);
int vipsgen_zone_with_options(VipsImage** out, gint width, gint height, gboolean uchar);
int vipsgen_zoom(VipsImage* input, VipsImage** out, gint xfac, gint yfac);
// Custom operations
int vipsgen_image_new_from_source(VipsSourceCustom *source, VipsImage **out);
int vipsgen_image_new_from_source_with_option(VipsSourceCustom *source, VipsImage **out, const char *option_string);
int vipsgen_image_new_from_file(const char *name, VipsImage **out);
int vipsgen_image_new_from_buffer(const void *buf, size_t len, VipsImage **out);
int vipsgen_image_new_from_buffer_with_option(const void *buf, size_t len, VipsImage **out, const char *option_string);
int vipsgen_image_new_from_memory(const void *buf, size_t len, int width, int height, int bands, VipsImage **out);
void vipsgen_clear_image(VipsImage **image);
int vipsgen_remove_exif(VipsImage *in, VipsImage **out);
int vipsgen_embed_multi_page(VipsImage *in, VipsImage **out, int left, int top, int width, int height, int extend);
int vipsgen_embed_multi_page_background(VipsImage *in, VipsImage **out, int left, int top, int width, int height, double r, double g, double b, double a);
int vipsgen_extract_area_multi_page(VipsImage *in, VipsImage **out, int left, int top, int width, int height);
int vipsgen_rot_multi_page(VipsImage *in, VipsImage **out, VipsAngle angle);
int vipsgen_label(VipsImage *in, VipsImage **out, const char *text, const char *font, int x, int y, int size, VipsAlign align, double r, double g, double b, float opacity);

View File

@@ -1,24 +0,0 @@
The MIT License
Copyright (c) Simple Things LLC and contributors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,71 +0,0 @@
#include "arithmetic.h"
int add(VipsImage *left, VipsImage *right, VipsImage **out) {
return vips_add(left, right, out, NULL);
}
int multiply(VipsImage *left, VipsImage *right, VipsImage **out) {
return vips_multiply(left, right, out, NULL);
}
int divide(VipsImage *left, VipsImage *right, VipsImage **out) {
return vips_divide(left, right, out, NULL);
}
int linear(VipsImage *in, VipsImage **out, double *a, double *b, int n) {
return vips_linear(in, out, a, b, n, NULL);
}
int linear1(VipsImage *in, VipsImage **out, double a, double b) {
return vips_linear1(in, out, a, b, NULL);
}
int invert_image(VipsImage *in, VipsImage **out) {
return vips_invert(in, out, NULL);
}
int average(VipsImage *in, double *out) {
return vips_avg(in, out, NULL);
}
int find_trim(VipsImage *in, int *left, int *top, int *width, int *height,
double threshold, double r, double g, double b) {
if (in->Type == VIPS_INTERPRETATION_RGB16 || in->Type == VIPS_INTERPRETATION_GREY16) {
r = 65535 * r / 255;
g = 65535 * g / 255;
b = 65535 * b / 255;
}
double background[3] = {r, g, b};
VipsArrayDouble *vipsBackground = vips_array_double_new(background, 3);
int code = vips_find_trim(in, left, top, width, height, "threshold", threshold, "background", vipsBackground, NULL);
vips_area_unref(VIPS_AREA(vipsBackground));
return code;
}
int getpoint(VipsImage *in, double **vector, int n, int x, int y) {
return vips_getpoint(in, vector, &n, x, y, NULL);
}
int stats(VipsImage *in, VipsImage **out) {
return vips_stats(in, out, NULL);
}
int hist_find(VipsImage *in, VipsImage **out) {
return vips_hist_find(in, out, NULL);
}
int hist_cum(VipsImage *in, VipsImage **out) {
return vips_hist_cum(in, out, NULL);
}
int hist_norm(VipsImage *in, VipsImage **out) {
return vips_hist_norm(in, out, NULL);
}
int hist_entropy(VipsImage *in, double *out) {
return vips_hist_entropy(in, out, NULL);
}

View File

@@ -1,176 +0,0 @@
package vips
// #include "arithmetic.h"
import "C"
import "unsafe"
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-add
func vipsAdd(left *C.VipsImage, right *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("add")
var out *C.VipsImage
if err := C.add(left, right, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-multiply
func vipsMultiply(left *C.VipsImage, right *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("multiply")
var out *C.VipsImage
if err := C.multiply(left, right, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-divide
func vipsDivide(left *C.VipsImage, right *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("divide")
var out *C.VipsImage
if err := C.divide(left, right, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-linear
func vipsLinear(in *C.VipsImage, a, b []float64, n int) (*C.VipsImage, error) {
incOpCounter("linear")
var out *C.VipsImage
if err := C.linear(in, &out, (*C.double)(&a[0]), (*C.double)(&b[0]), C.int(n)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-linear1
func vipsLinear1(in *C.VipsImage, a, b float64) (*C.VipsImage, error) {
incOpCounter("linear1")
var out *C.VipsImage
if err := C.linear1(in, &out, C.double(a), C.double(b)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-invert
func vipsInvert(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("invert")
var out *C.VipsImage
if err := C.invert_image(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-avg
func vipsAverage(in *C.VipsImage) (float64, error) {
incOpCounter("average")
var out C.double
if err := C.average(in, &out); err != 0 {
return 0, handleVipsError()
}
return float64(out), nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-find-trim
func vipsFindTrim(in *C.VipsImage, threshold float64, backgroundColor *Color) (int, int, int, int, error) {
incOpCounter("findTrim")
var left, top, width, height C.int
if err := C.find_trim(in, &left, &top, &width, &height, C.double(threshold), C.double(backgroundColor.R),
C.double(backgroundColor.G), C.double(backgroundColor.B)); err != 0 {
return -1, -1, -1, -1, handleVipsError()
}
return int(left), int(top), int(width), int(height), nil
}
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html#vips-getpoint
func vipsGetPoint(in *C.VipsImage, n int, x int, y int) ([]float64, error) {
incOpCounter("getpoint")
var out *C.double
defer gFreePointer(unsafe.Pointer(out))
if err := C.getpoint(in, &out, C.int(n), C.int(x), C.int(y)); err != 0 {
return nil, handleVipsError()
}
// maximum n is 4
return (*[4]float64)(unsafe.Pointer(out))[:n:n], nil
}
// https://www.libvips.org/API/current/libvips-arithmetic.html#vips-stats
func vipsStats(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("stats")
var out *C.VipsImage
if err := C.stats(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-arithmetic.html#vips-hist-find
func vipsHistFind(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("histFind")
var out *C.VipsImage
if err := C.hist_find(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-histogram.html#vips-hist-norm
func vipsHistNorm(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("histNorm")
var out *C.VipsImage
if err := C.hist_norm(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-histogram.html#vips-hist-cum
func vipsHistCum(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("histCum")
var out *C.VipsImage
if err := C.hist_cum(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-histogram.html#vips-hist-entropy
func vipsHistEntropy(in *C.VipsImage) (float64, error) {
incOpCounter("histEntropy")
var out C.double
if err := C.hist_entropy(in, &out); err != 0 {
return 0, handleVipsError()
}
return float64(out), nil
}

View File

@@ -1,20 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-arithmetic.html
#include <stdlib.h>
#include <vips/vips.h>
int add(VipsImage *left, VipsImage *right, VipsImage **out);
int multiply(VipsImage *left, VipsImage *right, VipsImage **out);
int divide(VipsImage *left, VipsImage *right, VipsImage **out);
int linear(VipsImage *in, VipsImage **out, double *a, double *b, int n);
int linear1(VipsImage *in, VipsImage **out, double a, double b);
int invert_image(VipsImage *in, VipsImage **out);
int average(VipsImage *in, double *out);
int find_trim(VipsImage *in, int *left, int *top, int *width, int *height,
double threshold, double r, double g, double b);
int getpoint(VipsImage *in, double **vector, int n, int x, int y);
int stats(VipsImage *in, VipsImage **out);
int hist_find(VipsImage *in, VipsImage **out);
int hist_cum(VipsImage *in, VipsImage **out);
int hist_norm(VipsImage *in, VipsImage **out);
int hist_entropy(VipsImage *in, double *out);

View File

@@ -1,22 +0,0 @@
#include "color.h"
#include <unistd.h>
int is_colorspace_supported(VipsImage *in) {
return vips_colourspace_issupported(in) ? 1 : 0;
}
int to_colorspace(VipsImage *in, VipsImage **out, VipsInterpretation space) {
return vips_colourspace(in, out, space, NULL);
}
// https://libvips.github.io/libvips/API/8.6/libvips-colour.html#vips-icc-transform
int icc_transform(VipsImage *in, VipsImage **out, const char *output_profile, const char *input_profile, VipsIntent intent,
int depth, gboolean embedded) {
return vips_icc_transform(
in, out, output_profile,
"input_profile", input_profile ? input_profile : "none",
"intent", intent,
"depth", depth ? depth : 8,
"embedded", embedded,
NULL);
}

View File

@@ -1,96 +0,0 @@
package vips
// #include "color.h"
import "C"
// Color represents an RGB
type Color struct {
R, G, B uint8
}
// ColorRGBA represents an RGB with alpha channel (A)
type ColorRGBA struct {
R, G, B, A uint8
}
// Interpretation represents VIPS_INTERPRETATION type
type Interpretation int
// Interpretation enum
const (
InterpretationError Interpretation = C.VIPS_INTERPRETATION_ERROR
InterpretationMultiband Interpretation = C.VIPS_INTERPRETATION_MULTIBAND
InterpretationBW Interpretation = C.VIPS_INTERPRETATION_B_W
InterpretationHistogram Interpretation = C.VIPS_INTERPRETATION_HISTOGRAM
InterpretationXYZ Interpretation = C.VIPS_INTERPRETATION_XYZ
InterpretationLAB Interpretation = C.VIPS_INTERPRETATION_LAB
InterpretationCMYK Interpretation = C.VIPS_INTERPRETATION_CMYK
InterpretationLABQ Interpretation = C.VIPS_INTERPRETATION_LABQ
InterpretationRGB Interpretation = C.VIPS_INTERPRETATION_RGB
InterpretationRGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16
InterpretationCMC Interpretation = C.VIPS_INTERPRETATION_CMC
InterpretationLCH Interpretation = C.VIPS_INTERPRETATION_LCH
InterpretationLABS Interpretation = C.VIPS_INTERPRETATION_LABS
InterpretationSRGB Interpretation = C.VIPS_INTERPRETATION_sRGB
InterpretationYXY Interpretation = C.VIPS_INTERPRETATION_YXY
InterpretationFourier Interpretation = C.VIPS_INTERPRETATION_FOURIER
InterpretationGrey16 Interpretation = C.VIPS_INTERPRETATION_GREY16
InterpretationMatrix Interpretation = C.VIPS_INTERPRETATION_MATRIX
InterpretationScRGB Interpretation = C.VIPS_INTERPRETATION_scRGB
InterpretationHSV Interpretation = C.VIPS_INTERPRETATION_HSV
)
// Intent represents VIPS_INTENT type
type Intent int
// Intent enum
const (
IntentPerceptual Intent = C.VIPS_INTENT_PERCEPTUAL
IntentRelative Intent = C.VIPS_INTENT_RELATIVE
IntentSaturation Intent = C.VIPS_INTENT_SATURATION
IntentAbsolute Intent = C.VIPS_INTENT_ABSOLUTE
IntentLast Intent = C.VIPS_INTENT_LAST
)
func vipsIsColorSpaceSupported(in *C.VipsImage) bool {
return C.is_colorspace_supported(in) == 1
}
// https://libvips.github.io/libvips/API/current/libvips-colour.html#vips-colourspace
func vipsToColorSpace(in *C.VipsImage, interpretation Interpretation) (*C.VipsImage, error) {
incOpCounter("to_colorspace")
var out *C.VipsImage
inter := C.VipsInterpretation(interpretation)
if err := C.to_colorspace(in, &out, inter); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsICCTransform(in *C.VipsImage, outputProfile string, inputProfile string, intent Intent, depth int,
embedded bool) (*C.VipsImage, error) {
var out *C.VipsImage
var cInputProfile *C.char
var cEmbedded C.gboolean
cOutputProfile := C.CString(outputProfile)
defer freeCString(cOutputProfile)
if inputProfile != "" {
cInputProfile = C.CString(inputProfile)
defer freeCString(cInputProfile)
}
if embedded {
cEmbedded = C.TRUE
}
if res := C.icc_transform(in, &out, cOutputProfile, cInputProfile, C.VipsIntent(intent), C.int(depth), cEmbedded); res != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,10 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-colour.html
#include <stdlib.h>
#include <vips/vips.h>
int is_colorspace_supported(VipsImage *in);
int to_colorspace(VipsImage *in, VipsImage **out, VipsInterpretation space);
int icc_transform(VipsImage *in, VipsImage **out, const char *output_profile, const char *input_profile, VipsIntent intent,
int depth, gboolean embedded);

View File

@@ -1,27 +0,0 @@
package vips
// #include <vips/vips.h>
import "C"
// ImageComposite image to composite param
type ImageComposite struct {
Image *ImageRef
BlendMode BlendMode
X, Y int
}
func toVipsCompositeStructs(r *ImageRef, datas []*ImageComposite) ([]*C.VipsImage, []C.int, []C.int, []C.int) {
ins := []*C.VipsImage{r.image}
modes := []C.int{}
xs := []C.int{}
ys := []C.int{}
for _, image := range datas {
ins = append(ins, image.Image.image)
modes = append(modes, C.int(image.BlendMode))
xs = append(xs, C.int(image.X))
ys = append(ys, C.int(image.Y))
}
return ins, modes, xs, ys
}

View File

@@ -1,380 +0,0 @@
#include "conversion.h"
int copy_image_changing_interpretation(VipsImage *in, VipsImage **out,
VipsInterpretation interpretation) {
return vips_copy(in, out, "interpretation", interpretation, NULL);
}
int copy_image_changing_resolution(VipsImage *in, VipsImage **out, double xres,
double yres) {
return vips_copy(in, out, "xres", xres, "yres", yres, NULL);
}
int copy_image(VipsImage *in, VipsImage **out) {
return vips_copy(in, out, NULL);
}
int embed_image(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, int extend) {
return vips_embed(in, out, left, top, width, height, "extend", extend, NULL);
}
int embed_image_background(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, double r, double g, double b, double a) {
double background[3] = {r, g, b};
double backgroundRGBA[4] = {r, g, b, a};
VipsArrayDouble *vipsBackground;
if (in->Bands <= 3) {
vipsBackground = vips_array_double_new(background, 3);
} else {
vipsBackground = vips_array_double_new(backgroundRGBA, 4);
}
int code = vips_embed(in, out, left, top, width, height,
"extend", VIPS_EXTEND_BACKGROUND, "background", vipsBackground, NULL);
vips_area_unref(VIPS_AREA(vipsBackground));
return code;
}
int embed_multi_page_image(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, int extend) {
VipsObject *base = VIPS_OBJECT(vips_image_new());
int page_height = vips_image_get_page_height(in);
int in_width = in->Xsize;
int n_pages = in->Ysize / page_height;
VipsImage **page = (VipsImage **) vips_object_local_array(base, n_pages);
VipsImage **copy = (VipsImage **) vips_object_local_array(base, 1);
// split image into cropped frames
for (int i = 0; i < n_pages; i++) {
if (
vips_extract_area(in, &page[i], 0, page_height * i, in_width, page_height, NULL) ||
vips_embed(page[i], &page[i], left, top, width, height, "extend", extend, NULL)
) {
g_object_unref(base);
return -1;
}
}
// reassemble frames and set page height
// copy before modifying metadata
if(
vips_arrayjoin(page, &copy[0], n_pages, "across", 1, NULL) ||
vips_copy(copy[0], out, NULL)
) {
g_object_unref(base);
return -1;
}
vips_image_set_int(*out, VIPS_META_PAGE_HEIGHT, height);
g_object_unref(base);
return 0;
}
int embed_multi_page_image_background(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, double r, double g, double b, double a) {
double background[3] = {r, g, b};
double backgroundRGBA[4] = {r, g, b, a};
VipsArrayDouble *vipsBackground;
if (in->Bands <= 3) {
vipsBackground = vips_array_double_new(background, 3);
} else {
vipsBackground = vips_array_double_new(backgroundRGBA, 4);
}
VipsObject *base = VIPS_OBJECT(vips_image_new());
int page_height = vips_image_get_page_height(in);
int in_width = in->Xsize;
int n_pages = in->Ysize / page_height;
VipsImage **page = (VipsImage **) vips_object_local_array(base, n_pages);
VipsImage **copy = (VipsImage **) vips_object_local_array(base, 1);
// split image into cropped frames
for (int i = 0; i < n_pages; i++) {
if (
vips_extract_area(in, &page[i], 0, page_height * i, in_width, page_height, NULL) ||
vips_embed(page[i], &page[i], left, top, width, height,
"extend", VIPS_EXTEND_BACKGROUND, "background", vipsBackground, NULL)
) {
vips_area_unref(VIPS_AREA(vipsBackground));
g_object_unref(base);
return -1;
}
}
// reassemble frames and set page height
// copy before modifying metadata
if(
vips_arrayjoin(page, &copy[0], n_pages, "across", 1, NULL) ||
vips_copy(copy[0], out, NULL)
) {
vips_area_unref(VIPS_AREA(vipsBackground));
g_object_unref(base);
return -1;
}
vips_image_set_int(*out, VIPS_META_PAGE_HEIGHT, height);
vips_area_unref(VIPS_AREA(vipsBackground));
g_object_unref(base);
return 0;
}
int flip_image(VipsImage *in, VipsImage **out, int direction) {
return vips_flip(in, out, direction, NULL);
}
int recomb_image(VipsImage *in, VipsImage **out, VipsImage *m) {
return vips_recomb(in, out, m, NULL);
}
int extract_image_area(VipsImage *in, VipsImage **out, int left, int top,
int width, int height) {
return vips_extract_area(in, out, left, top, width, height, NULL);
}
int extract_area_multi_page(VipsImage *in, VipsImage **out, int left, int top, int width, int height) {
VipsObject *base = VIPS_OBJECT(vips_image_new());
int page_height = vips_image_get_page_height(in);
int n_pages = in->Ysize / page_height;
VipsImage **page = (VipsImage **) vips_object_local_array(base, n_pages);
VipsImage **copy = (VipsImage **) vips_object_local_array(base, 1);
// split image into cropped frames
for (int i = 0; i < n_pages; i++) {
if(vips_extract_area(in, &page[i], left, page_height * i + top, width, height, NULL)) {
g_object_unref(base);
return -1;
}
}
// reassemble frames and set page height
// copy before modifying metadata
if(
vips_arrayjoin(page, &copy[0], n_pages, "across", 1, NULL) ||
vips_copy(copy[0], out, NULL)
) {
g_object_unref(base);
return -1;
}
vips_image_set_int(*out, VIPS_META_PAGE_HEIGHT, height);
g_object_unref(base);
return 0;
}
int extract_band(VipsImage *in, VipsImage **out, int band, int num) {
if (num > 0) {
return vips_extract_band(in, out, band, "n", num, NULL);
}
return vips_extract_band(in, out, band, NULL);
}
int rot_image(VipsImage *in, VipsImage **out, VipsAngle angle) {
return vips_rot(in, out, angle, NULL);
}
int autorot_image(VipsImage *in, VipsImage **out) {
return vips_autorot(in, out, NULL);
}
int zoom_image(VipsImage *in, VipsImage **out, int xfac, int yfac) {
return vips_zoom(in, out, xfac, yfac, NULL);
}
int bandjoin(VipsImage **in, VipsImage **out, int n) {
return vips_bandjoin(in, out, n, NULL);
}
int bandjoin_const(VipsImage *in, VipsImage **out, double constants[], int n) {
return vips_bandjoin_const(in, out, constants, n, NULL);
}
int similarity(VipsImage *in, VipsImage **out, double scale, double angle,
double r, double g, double b, double a, double idx, double idy,
double odx, double ody) {
if (is_16bit(in->Type)) {
r = 65535 * r / 255;
g = 65535 * g / 255;
b = 65535 * b / 255;
a = 65535 * a / 255;
}
double background[3] = {r, g, b};
double backgroundRGBA[4] = {r, g, b, a};
VipsArrayDouble *vipsBackground;
// Ignore the alpha channel if the image doesn't have one
if (in->Bands <= 3) {
vipsBackground = vips_array_double_new(background, 3);
} else {
vipsBackground = vips_array_double_new(backgroundRGBA, 4);
}
int code = vips_similarity(in, out, "scale", scale, "angle", angle,
"background", vipsBackground, "idx", idx, "idy",
idy, "odx", odx, "ody", ody, NULL);
vips_area_unref(VIPS_AREA(vipsBackground));
return code;
}
int smartcrop(VipsImage *in, VipsImage **out, int width, int height,
int interesting) {
return vips_smartcrop(in, out, width, height, "interesting", interesting,
NULL);
}
int crop(VipsImage *in, VipsImage **out, int left, int top,
int width, int height) {
// resolve image pages
int page_height = vips_image_get_page_height(in);
int n_pages = in->Ysize / page_height;
if (n_pages <= 1) {
return vips_crop(in, out, left, top, width, height, NULL);
}
int in_width = in->Xsize;
VipsObject *base = VIPS_OBJECT(vips_image_new());
VipsImage **page = (VipsImage **) vips_object_local_array(base, n_pages);
VipsImage **copy = (VipsImage **) vips_object_local_array(base, 1);
// split image into cropped frames
for (int i = 0; i < n_pages; i++) {
if (
vips_extract_area(in, &page[i], 0, page_height * i, in_width, page_height, NULL) ||
vips_crop(page[i], &page[i], left, top, width, height, NULL)
) {
g_object_unref(base);
return -1;
}
}
// reassemble frames and set page height
// copy before modifying metadata
if(
vips_arrayjoin(page, &copy[0], n_pages, "across", 1, NULL) ||
vips_copy(copy[0], out, NULL)
) {
g_object_unref(base);
return -1;
}
vips_image_set_int(*out, VIPS_META_PAGE_HEIGHT, height);
g_object_unref(base);
return 0;
}
int flatten_image(VipsImage *in, VipsImage **out, double r, double g,
double b) {
if (is_16bit(in->Type)) {
r = 65535 * r / 255;
g = 65535 * g / 255;
b = 65535 * b / 255;
}
double background[3] = {r, g, b};
VipsArrayDouble *vipsBackground = vips_array_double_new(background, 3);
int code = vips_flatten(in, out, "background", vipsBackground, "max_alpha",
is_16bit(in->Type) ? 65535.0 : 255.0, NULL);
vips_area_unref(VIPS_AREA(vipsBackground));
return code;
}
int is_16bit(VipsInterpretation interpretation) {
return interpretation == VIPS_INTERPRETATION_RGB16 ||
interpretation == VIPS_INTERPRETATION_GREY16;
}
int add_alpha(VipsImage *in, VipsImage **out) {
return vips_addalpha(in, out, NULL);
}
int premultiply_alpha(VipsImage *in, VipsImage **out) {
return vips_premultiply(in, out, "max_alpha", max_alpha(in), NULL);
}
int unpremultiply_alpha(VipsImage *in, VipsImage **out) {
return vips_unpremultiply(in, out, NULL);
}
int cast(VipsImage *in, VipsImage **out, int bandFormat) {
return vips_cast(in, out, bandFormat, NULL);
}
double max_alpha(VipsImage *in) {
switch (in->BandFmt) {
case VIPS_FORMAT_USHORT:
return 65535;
case VIPS_FORMAT_FLOAT:
case VIPS_FORMAT_DOUBLE:
return 1.0;
default:
return 255;
}
}
int composite_image(VipsImage **in, VipsImage **out, int n, int *mode, int *x,
int *y) {
VipsArrayInt *xs = vips_array_int_new(x, n - 1);
VipsArrayInt *ys = vips_array_int_new(y, n - 1);
int code = vips_composite(in, out, n, mode, "x", xs, "y", ys, NULL);
vips_area_unref(VIPS_AREA(xs));
vips_area_unref(VIPS_AREA(ys));
return code;
}
int composite2_image(VipsImage *base, VipsImage *overlay, VipsImage **out,
int mode, gint x, gint y) {
return vips_composite2(base, overlay, out, mode, "x", x, "y", y, NULL);
}
int insert_image(VipsImage *main, VipsImage *sub, VipsImage **out, int x, int y, int expand, double r, double g, double b, double a) {
if (is_16bit(main->Type)) {
r = 65535 * r / 255;
g = 65535 * g / 255;
b = 65535 * b / 255;
a = 65535 * a / 255;
}
double background[3] = {r, g, b};
double backgroundRGBA[4] = {r, g, b, a};
VipsArrayDouble *vipsBackground;
// Ignore the alpha channel if the image doesn't have one
if (main->Bands <= 3) {
vipsBackground = vips_array_double_new(background, 3);
} else {
vipsBackground = vips_array_double_new(backgroundRGBA, 4);
}
int code = vips_insert(main, sub, out, x, y, "expand", expand, "background", vipsBackground, NULL);
vips_area_unref(VIPS_AREA(vipsBackground));
return code;
}
int join(VipsImage *in1, VipsImage *in2, VipsImage **out, int direction) {
return vips_join(in1, in2, out, direction, NULL);
}
int arrayjoin(VipsImage **in, VipsImage **out, int n, int across) {
return vips_arrayjoin(in, out, n, "across", across, NULL);
}
int replicate(VipsImage *in, VipsImage **out, int across, int down) {
return vips_replicate(in, out, across, down, NULL);
}
int grid(VipsImage *in, VipsImage **out, int tileHeight, int across, int down){
return vips_grid(in, out, tileHeight, across, down, NULL);
}
int adjust_gamma(VipsImage *in, VipsImage **out, double g) {
return vips_gamma(in, out, "exponent", g, NULL);
}

View File

@@ -1,520 +0,0 @@
package vips
// #cgo CFLAGS: -std=c99
// #include "conversion.h"
import "C"
// BandFormat represents VIPS_FORMAT type
type BandFormat int
// BandFormat enum
const (
BandFormatNotSet BandFormat = C.VIPS_FORMAT_NOTSET
BandFormatUchar BandFormat = C.VIPS_FORMAT_UCHAR
BandFormatChar BandFormat = C.VIPS_FORMAT_CHAR
BandFormatUshort BandFormat = C.VIPS_FORMAT_USHORT
BandFormatShort BandFormat = C.VIPS_FORMAT_SHORT
BandFormatUint BandFormat = C.VIPS_FORMAT_UINT
BandFormatInt BandFormat = C.VIPS_FORMAT_INT
BandFormatFloat BandFormat = C.VIPS_FORMAT_FLOAT
BandFormatComplex BandFormat = C.VIPS_FORMAT_COMPLEX
BandFormatDouble BandFormat = C.VIPS_FORMAT_DOUBLE
BandFormatDpComplex BandFormat = C.VIPS_FORMAT_DPCOMPLEX
)
// BlendMode gives the various Porter-Duff and PDF blend modes.
// See https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsBlendMode
type BlendMode int
// Constants define the various Porter-Duff and PDF blend modes.
// See https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsBlendMode
const (
BlendModeClear BlendMode = C.VIPS_BLEND_MODE_CLEAR
BlendModeSource BlendMode = C.VIPS_BLEND_MODE_SOURCE
BlendModeOver BlendMode = C.VIPS_BLEND_MODE_OVER
BlendModeIn BlendMode = C.VIPS_BLEND_MODE_IN
BlendModeOut BlendMode = C.VIPS_BLEND_MODE_OUT
BlendModeAtop BlendMode = C.VIPS_BLEND_MODE_ATOP
BlendModeDest BlendMode = C.VIPS_BLEND_MODE_DEST
BlendModeDestOver BlendMode = C.VIPS_BLEND_MODE_DEST_OVER
BlendModeDestIn BlendMode = C.VIPS_BLEND_MODE_DEST_IN
BlendModeDestOut BlendMode = C.VIPS_BLEND_MODE_DEST_OUT
BlendModeDestAtop BlendMode = C.VIPS_BLEND_MODE_DEST_ATOP
BlendModeXOR BlendMode = C.VIPS_BLEND_MODE_XOR
BlendModeAdd BlendMode = C.VIPS_BLEND_MODE_ADD
BlendModeSaturate BlendMode = C.VIPS_BLEND_MODE_SATURATE
BlendModeMultiply BlendMode = C.VIPS_BLEND_MODE_MULTIPLY
BlendModeScreen BlendMode = C.VIPS_BLEND_MODE_SCREEN
BlendModeOverlay BlendMode = C.VIPS_BLEND_MODE_OVERLAY
BlendModeDarken BlendMode = C.VIPS_BLEND_MODE_DARKEN
BlendModeLighten BlendMode = C.VIPS_BLEND_MODE_LIGHTEN
BlendModeColorDodge BlendMode = C.VIPS_BLEND_MODE_COLOUR_DODGE
BlendModeColorBurn BlendMode = C.VIPS_BLEND_MODE_COLOUR_BURN
BlendModeHardLight BlendMode = C.VIPS_BLEND_MODE_HARD_LIGHT
BlendModeSoftLight BlendMode = C.VIPS_BLEND_MODE_SOFT_LIGHT
BlendModeDifference BlendMode = C.VIPS_BLEND_MODE_DIFFERENCE
BlendModeExclusion BlendMode = C.VIPS_BLEND_MODE_EXCLUSION
)
// Direction represents VIPS_DIRECTION type
type Direction int
// Direction enum
const (
DirectionHorizontal Direction = C.VIPS_DIRECTION_HORIZONTAL
DirectionVertical Direction = C.VIPS_DIRECTION_VERTICAL
)
// Angle represents VIPS_ANGLE type
type Angle int
// Angle enum
const (
Angle0 Angle = C.VIPS_ANGLE_D0
Angle90 Angle = C.VIPS_ANGLE_D90
Angle180 Angle = C.VIPS_ANGLE_D180
Angle270 Angle = C.VIPS_ANGLE_D270
)
// Angle45 represents VIPS_ANGLE45 type
type Angle45 int
// Angle45 enum
const (
Angle45_0 Angle45 = C.VIPS_ANGLE45_D0
Angle45_45 Angle45 = C.VIPS_ANGLE45_D45
Angle45_90 Angle45 = C.VIPS_ANGLE45_D90
Angle45_135 Angle45 = C.VIPS_ANGLE45_D135
Angle45_180 Angle45 = C.VIPS_ANGLE45_D180
Angle45_225 Angle45 = C.VIPS_ANGLE45_D225
Angle45_270 Angle45 = C.VIPS_ANGLE45_D270
Angle45_315 Angle45 = C.VIPS_ANGLE45_D315
)
// ExtendStrategy represents VIPS_EXTEND type
type ExtendStrategy int
// ExtendStrategy enum
const (
ExtendBlack ExtendStrategy = C.VIPS_EXTEND_BLACK
ExtendCopy ExtendStrategy = C.VIPS_EXTEND_COPY
ExtendRepeat ExtendStrategy = C.VIPS_EXTEND_REPEAT
ExtendMirror ExtendStrategy = C.VIPS_EXTEND_MIRROR
ExtendWhite ExtendStrategy = C.VIPS_EXTEND_WHITE
ExtendBackground ExtendStrategy = C.VIPS_EXTEND_BACKGROUND
)
// Interesting represents VIPS_INTERESTING type
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#VipsInteresting
type Interesting int
// Interesting constants represent areas of interest which smart cropping will crop based on.
const (
InterestingNone Interesting = C.VIPS_INTERESTING_NONE
InterestingCentre Interesting = C.VIPS_INTERESTING_CENTRE
InterestingEntropy Interesting = C.VIPS_INTERESTING_ENTROPY
InterestingAttention Interesting = C.VIPS_INTERESTING_ATTENTION
InterestingLow Interesting = C.VIPS_INTERESTING_LOW
InterestingHigh Interesting = C.VIPS_INTERESTING_HIGH
InterestingAll Interesting = C.VIPS_INTERESTING_ALL
InterestingLast Interesting = C.VIPS_INTERESTING_LAST
)
func vipsCopyImageChangingInterpretation(in *C.VipsImage, interpretation Interpretation) (*C.VipsImage, error) {
var out *C.VipsImage
if err := C.copy_image_changing_interpretation(in, &out, C.VipsInterpretation(interpretation)); int(err) != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsCopyImageChangingResolution(in *C.VipsImage, xres float64, yres float64) (*C.VipsImage, error) {
var out *C.VipsImage
if err := C.copy_image_changing_resolution(in, &out, C.double(xres), C.double(yres)); int(err) != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-copy
func vipsCopyImage(in *C.VipsImage) (*C.VipsImage, error) {
var out *C.VipsImage
if err := C.copy_image(in, &out); int(err) != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-embed
func vipsEmbed(in *C.VipsImage, left, top, width, height int, extend ExtendStrategy) (*C.VipsImage, error) {
incOpCounter("embed")
var out *C.VipsImage
if err := C.embed_image(in, &out, C.int(left), C.int(top), C.int(width), C.int(height), C.int(extend)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-embed
func vipsEmbedBackground(in *C.VipsImage, left, top, width, height int, backgroundColor *ColorRGBA) (*C.VipsImage, error) {
incOpCounter("embed")
var out *C.VipsImage
if err := C.embed_image_background(in, &out, C.int(left), C.int(top), C.int(width),
C.int(height), C.double(backgroundColor.R),
C.double(backgroundColor.G), C.double(backgroundColor.B), C.double(backgroundColor.A)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsEmbedMultiPage(in *C.VipsImage, left, top, width, height int, extend ExtendStrategy) (*C.VipsImage, error) {
incOpCounter("embedMultiPage")
var out *C.VipsImage
if err := C.embed_multi_page_image(in, &out, C.int(left), C.int(top), C.int(width), C.int(height), C.int(extend)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsEmbedMultiPageBackground(in *C.VipsImage, left, top, width, height int, backgroundColor *ColorRGBA) (*C.VipsImage, error) {
incOpCounter("embedMultiPageBackground")
var out *C.VipsImage
if err := C.embed_multi_page_image_background(in, &out, C.int(left), C.int(top), C.int(width),
C.int(height), C.double(backgroundColor.R),
C.double(backgroundColor.G), C.double(backgroundColor.B), C.double(backgroundColor.A)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-flip
func vipsFlip(in *C.VipsImage, direction Direction) (*C.VipsImage, error) {
incOpCounter("flip")
var out *C.VipsImage
if err := C.flip_image(in, &out, C.int(direction)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-recomb
func vipsRecomb(in *C.VipsImage, m *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("recomb")
var out *C.VipsImage
if err := C.recomb_image(in, &out, m); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-extract-area
func vipsExtractArea(in *C.VipsImage, left, top, width, height int) (*C.VipsImage, error) {
incOpCounter("extractArea")
var out *C.VipsImage
if err := C.extract_image_area(in, &out, C.int(left), C.int(top), C.int(width), C.int(height)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsExtractAreaMultiPage(in *C.VipsImage, left, top, width, height int) (*C.VipsImage, error) {
incOpCounter("extractAreaMultiPage")
var out *C.VipsImage
if err := C.extract_area_multi_page(in, &out, C.int(left), C.int(top), C.int(width), C.int(height)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-extract-band
func vipsExtractBand(in *C.VipsImage, band, num int) (*C.VipsImage, error) {
incOpCounter("extractBand")
var out *C.VipsImage
if err := C.extract_band(in, &out, C.int(band), C.int(num)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// http://libvips.github.io/libvips/API/current/libvips-resample.html#vips-similarity
func vipsSimilarity(in *C.VipsImage, scale float64, angle float64, color *ColorRGBA,
idx float64, idy float64, odx float64, ody float64) (*C.VipsImage, error) {
incOpCounter("similarity")
var out *C.VipsImage
if err := C.similarity(in, &out, C.double(scale), C.double(angle),
C.double(color.R), C.double(color.G), C.double(color.B), C.double(color.A),
C.double(idx), C.double(idy), C.double(odx), C.double(ody)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// http://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-smartcrop
func vipsSmartCrop(in *C.VipsImage, width int, height int, interesting Interesting) (*C.VipsImage, error) {
incOpCounter("smartcrop")
var out *C.VipsImage
if err := C.smartcrop(in, &out, C.int(width), C.int(height), C.int(interesting)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// http://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-crop
func vipsCrop(in *C.VipsImage, left int, top int, width int, height int) (*C.VipsImage, error) {
incOpCounter("crop")
var out *C.VipsImage
if err := C.crop(in, &out, C.int(left), C.int(top), C.int(width), C.int(height)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-rot
func vipsRotate(in *C.VipsImage, angle Angle) (*C.VipsImage, error) {
incOpCounter("rot")
var out *C.VipsImage
if err := C.rot_image(in, &out, C.VipsAngle(angle)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-autorot
func vipsAutoRotate(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("autorot")
var out *C.VipsImage
if err := C.autorot_image(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-zoom
func vipsZoom(in *C.VipsImage, xFactor, yFactor int) (*C.VipsImage, error) {
incOpCounter("zoom")
var out *C.VipsImage
if err := C.zoom_image(in, &out, C.int(xFactor), C.int(yFactor)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-bandjoin
func vipsBandJoin(ins []*C.VipsImage) (*C.VipsImage, error) {
incOpCounter("bandjoin")
var out *C.VipsImage
if err := C.bandjoin(&ins[0], &out, C.int(len(ins))); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// http://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-bandjoin-const
func vipsBandJoinConst(in *C.VipsImage, constants []float64) (*C.VipsImage, error) {
incOpCounter("bandjoin_const")
var out *C.VipsImage
if err := C.bandjoin_const(in, &out, (*C.double)(&constants[0]), C.int(len(constants))); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-flatten
func vipsFlatten(in *C.VipsImage, color *Color) (*C.VipsImage, error) {
incOpCounter("flatten")
var out *C.VipsImage
err := C.flatten_image(in, &out, C.double(color.R), C.double(color.G), C.double(color.B))
if int(err) != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsAddAlpha(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("addAlpha")
var out *C.VipsImage
if err := C.add_alpha(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-premultiply
func vipsPremultiplyAlpha(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("premultiplyAlpha")
var out *C.VipsImage
if err := C.premultiply_alpha(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-unpremultiply
func vipsUnpremultiplyAlpha(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("unpremultiplyAlpha")
var out *C.VipsImage
if err := C.unpremultiply_alpha(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsCast(in *C.VipsImage, bandFormat BandFormat) (*C.VipsImage, error) {
incOpCounter("cast")
var out *C.VipsImage
if err := C.cast(in, &out, C.int(bandFormat)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-composite
func vipsComposite(ins []*C.VipsImage, modes []C.int, xs, ys []C.int) (*C.VipsImage, error) {
incOpCounter("composite_multi")
var out *C.VipsImage
if err := C.composite_image(&ins[0], &out, C.int(len(ins)), &modes[0], &xs[0], &ys[0]); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-composite2
func vipsComposite2(base *C.VipsImage, overlay *C.VipsImage, mode BlendMode, x, y int) (*C.VipsImage, error) {
incOpCounter("composite")
var out *C.VipsImage
if err := C.composite2_image(base, overlay, &out, C.int(mode), C.gint(x), C.gint(y)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsInsert(main *C.VipsImage, sub *C.VipsImage, x, y int, expand bool, background *ColorRGBA) (*C.VipsImage, error) {
incOpCounter("insert")
var out *C.VipsImage
if background == nil {
background = &ColorRGBA{R: 0.0, G: 0.0, B: 0.0, A: 255.0}
}
expandInt := 0
if expand {
expandInt = 1
}
if err := C.insert_image(main, sub, &out, C.int(x), C.int(y), C.int(expandInt), C.double(background.R), C.double(background.G), C.double(background.B), C.double(background.A)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-join
func vipsJoin(input1 *C.VipsImage, input2 *C.VipsImage, dir Direction) (*C.VipsImage, error) {
incOpCounter("join")
var out *C.VipsImage
defer C.g_object_unref(C.gpointer(input1))
defer C.g_object_unref(C.gpointer(input2))
if err := C.join(input1, input2, &out, C.int(dir)); err != 0 {
return nil, handleVipsError()
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-conversion.html#vips-arrayjoin
func vipsArrayJoin(inputs []*C.VipsImage, across int) (*C.VipsImage, error) {
incOpCounter("arrayjoin")
var out *C.VipsImage
if err := C.arrayjoin(&inputs[0], &out, C.int(len(inputs)), C.int(across)); err != 0 {
return nil, handleVipsError()
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-conversion.html#vips-replicate
func vipsReplicate(in *C.VipsImage, across int, down int) (*C.VipsImage, error) {
incOpCounter("replicate")
var out *C.VipsImage
if err := C.replicate(in, &out, C.int(across), C.int(down)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-conversion.html#vips-grid
func vipsGrid(in *C.VipsImage, tileHeight, across, down int) (*C.VipsImage, error) {
incOpCounter("grid")
var out *C.VipsImage
if err := C.grid(in, &out, C.int(tileHeight), C.int(across), C.int(down)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsGamma(image *C.VipsImage, gamma float64) (*C.VipsImage, error) {
incOpCounter("gamma")
var out *C.VipsImage
if err := C.adjust_gamma(image, &out, C.double(gamma)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,70 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-conversion.html
#include <stdlib.h>
#include <vips/vips.h>
int copy_image_changing_interpretation(VipsImage *in, VipsImage **out,
VipsInterpretation interpretation);
int copy_image_changing_resolution(VipsImage *in, VipsImage **out, double xres,
double yres);
int copy_image(VipsImage *in, VipsImage **out);
int embed_image(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, int extend);
int embed_image_background(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, double r, double g, double b, double a);
int embed_multi_page_image(VipsImage *in, VipsImage **out, int left, int top, int width,
int height, int extend);
int embed_multi_page_image_background(VipsImage *in, VipsImage **out, int left, int top,
int width, int height, double r, double g, double b, double a);
int flip_image(VipsImage *in, VipsImage **out, int direction);
int recomb_image(VipsImage *in, VipsImage **out, VipsImage *m);
int extract_image_area(VipsImage *in, VipsImage **out, int left, int top,
int width, int height);
int extract_area_multi_page(VipsImage *in, VipsImage **out, int left, int top,
int width, int height);
int extract_band(VipsImage *in, VipsImage **out, int band, int num);
int rot_image(VipsImage *in, VipsImage **out, VipsAngle angle);
int autorot_image(VipsImage *in, VipsImage **out);
int zoom_image(VipsImage *in, VipsImage **out, int xfac, int yfac);
int smartcrop(VipsImage *in, VipsImage **out, int width, int height,
int interesting);
int crop(VipsImage *in, VipsImage **out, int left, int top,
int width, int height);
int bandjoin(VipsImage **in, VipsImage **out, int n);
int bandjoin_const(VipsImage *in, VipsImage **out, double constants[], int n);
int similarity(VipsImage *in, VipsImage **out, double scale, double angle,
double r, double g, double b, double a, double idx, double idy,
double odx, double ody);
int flatten_image(VipsImage *in, VipsImage **out, double r, double g, double b);
int add_alpha(VipsImage *in, VipsImage **out);
int premultiply_alpha(VipsImage *in, VipsImage **out);
int unpremultiply_alpha(VipsImage *in, VipsImage **out);
int cast(VipsImage *in, VipsImage **out, int bandFormat);
double max_alpha(VipsImage *in);
int composite_image(VipsImage **in, VipsImage **out, int n, int *mode, int *x,
int *y);
int composite2_image(VipsImage *base, VipsImage *overlay, VipsImage **out,
int mode, gint x, gint y);
int insert_image(VipsImage *main, VipsImage *sub, VipsImage **out, int x, int y,
int expand, double r, double g, double b, double a);
int join(VipsImage *in1, VipsImage *in2, VipsImage **out, int direction);
int arrayjoin(VipsImage **in, VipsImage **out, int n, int across);
int is_16bit(VipsInterpretation interpretation);
int replicate(VipsImage *in, VipsImage **out, int across, int down);
int grid(VipsImage *in, VipsImage **out, int tileHeight, int across, int down);
int adjust_gamma(VipsImage *in, VipsImage **out, double g);

View File

@@ -1,14 +0,0 @@
#include "convolution.h"
int gaussian_blur_image(VipsImage *in, VipsImage **out, double sigma, double min_ampl) {
return vips_gaussblur(in, out, sigma, "min_ampl", min_ampl, NULL);
}
int sharpen_image(VipsImage *in, VipsImage **out, double sigma, double x1,
double m2) {
return vips_sharpen(in, out, "sigma", sigma, "x1", x1, "m2", m2, NULL);
}
int sobel_image(VipsImage *in, VipsImage **out) {
return vips_sobel(in, out, NULL);
}

View File

@@ -1,40 +0,0 @@
package vips
// #include "convolution.h"
import "C"
// https://libvips.github.io/libvips/API/current/libvips-convolution.html#vips-gaussblur
func vipsGaussianBlur(in *C.VipsImage, sigma, minAmpl float64) (*C.VipsImage, error) {
incOpCounter("gaussblur")
var out *C.VipsImage
if err := C.gaussian_blur_image(in, &out, C.double(sigma), C.double(minAmpl)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-convolution.html#vips-sharpen
func vipsSharpen(in *C.VipsImage, sigma float64, x1 float64, m2 float64) (*C.VipsImage, error) {
incOpCounter("sharpen")
var out *C.VipsImage
if err := C.sharpen_image(in, &out, C.double(sigma), C.double(x1), C.double(m2)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-convolution.html#vips-sobel
func vipsSobel(in *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("sobel")
var out *C.VipsImage
if err := C.sobel_image(in, &out); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,9 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-convolution.html
#include <stdlib.h>
#include <vips/vips.h>
int gaussian_blur_image(VipsImage *in, VipsImage **out, double sigma, double min_ampl);
int sharpen_image(VipsImage *in, VipsImage **out, double sigma, double x1,
double m2);
int sobel_image(VipsImage *in, VipsImage **out);

View File

@@ -1,24 +0,0 @@
// clang-format off
// include order matters
#include "lang.h"
#include "create.h"
// clang-format on
// https://libvips.github.io/libvips/API/current/libvips-create.html#vips-xyz
int xyz(VipsImage **out, int width, int height) {
return vips_xyz(out, width, height, NULL);
}
// http://libvips.github.io/libvips/API/current/libvips-create.html#vips-black
int black(VipsImage **out, int width, int height) {
return vips_black(out, width, height, NULL);
}
// https://libvips.github.io/libvips/API/current/libvips-create.html#vips-identity
int identity(VipsImage **out, int ushort) {
if (ushort > 0) {
return vips_identity(out, "ushort", TRUE, NULL);
} else {
return vips_identity(out, NULL);
}
}

View File

@@ -1,37 +0,0 @@
package vips
// #include "create.h"
import "C"
// https://libvips.github.io/libvips/API/current/libvips-create.html#vips-xyz
func vipsXYZ(width int, height int) (*C.VipsImage, error) {
var out *C.VipsImage
if err := C.xyz(&out, C.int(width), C.int(height)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// http://libvips.github.io/libvips/API/current/libvips-create.html#vips-black
func vipsBlack(width int, height int) (*C.VipsImage, error) {
var out *C.VipsImage
if err := C.black(&out, C.int(width), C.int(height)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-create.html#vips-identity
func vipsIdentity(ushort bool) (*C.VipsImage, error) {
var out *C.VipsImage
ushortInt := C.int(boolToInt(ushort))
if err := C.identity(&out, ushortInt); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,12 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-create.html
// clang-format off
// include order matters
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/foreign.h>
// clang-format on
int xyz(VipsImage **out, int width, int height);
int black(VipsImage **out, int width, int height);
int identity(VipsImage **out, int ushort);

View File

@@ -1,24 +0,0 @@
#include "draw.h"
#include "conversion.h"
int draw_rect(VipsImage *in, double r, double g, double b, double a, int left,
int top, int width, int height, int fill) {
if (is_16bit(in->Type)) {
r = 65535 * r / 255;
g = 65535 * g / 255;
b = 65535 * b / 255;
a = 65535 * a / 255;
}
double background[3] = {r, g, b};
double backgroundRGBA[4] = {r, g, b, a};
if (in->Bands <= 3) {
return vips_draw_rect(in, background, 3, left, top, width, height, "fill",
fill, NULL);
} else {
return vips_draw_rect(in, backgroundRGBA, 4, left, top, width, height,
"fill", fill, NULL);
}
}

View File

@@ -1,21 +0,0 @@
package vips
// #include "draw.h"
import "C"
// https://libvips.github.io/libvips/API/current/libvips-draw.html#vips-draw-rect
func vipsDrawRect(in *C.VipsImage, color ColorRGBA, left int, top int, width int, height int, fill bool) error {
incOpCounter("draw_rect")
fillBit := 0
if fill {
fillBit = 1
}
if err := C.draw_rect(in, C.double(color.R), C.double(color.G), C.double(color.B), C.double(color.A),
C.int(left), C.int(top), C.int(width), C.int(height), C.int(fillBit)); err != 0 {
return handleImageError(in)
}
return nil
}

View File

@@ -1,7 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-draw.html
#include <stdlib.h>
#include <vips/vips.h>
int draw_rect(VipsImage *in, double r, double g, double b, double a, int left,
int top, int width, int height, int fill);

View File

@@ -1,39 +0,0 @@
package vips
// #include <vips/vips.h>
import "C"
import (
"errors"
"fmt"
dbg "runtime/debug"
"unsafe"
)
var (
// ErrUnsupportedImageFormat when image type is unsupported
ErrUnsupportedImageFormat = errors.New("unsupported image format")
)
func handleImageError(out *C.VipsImage) error {
if out != nil {
clearImage(out)
}
return handleVipsError()
}
func handleSaveBufferError(out unsafe.Pointer) error {
if out != nil {
gFreePointer(out)
}
return handleVipsError()
}
func handleVipsError() error {
s := C.GoString(C.vips_error_buffer())
C.vips_error_clear()
return fmt.Errorf("%v\nStack:\n%s", s, dbg.Stack())
}

View File

@@ -1,578 +0,0 @@
#include "foreign.h"
#include "lang.h"
void set_bool_param(Param *p, gboolean b) {
p->type = PARAM_TYPE_BOOL;
p->value.b = b;
p->is_set = TRUE;
}
void set_int_param(Param *p, gint i) {
p->type = PARAM_TYPE_INT;
p->value.i = i;
p->is_set = TRUE;
}
void set_double_param(Param *p, gdouble d) {
p->type = PARAM_TYPE_DOUBLE;
p->value.d = d;
p->is_set = TRUE;
}
int load_image_buffer(LoadParams *params, void *buf, size_t len,
VipsImage **out) {
int code = 1;
ImageType imageType = params->inputFormat;
if (imageType == JPEG) {
// shrink: int, fail: bool, autorotate: bool
code = vips_jpegload_buffer(buf, len, out, "fail", params->fail,
"autorotate", params->autorotate, "shrink",
params->jpegShrink, NULL);
} else if (imageType == PNG) {
code = vips_pngload_buffer(buf, len, out, NULL);
} else if (imageType == WEBP) {
// page: int, n: int, scale: double
code = vips_webpload_buffer(buf, len, out, "page", params->page, "n",
params->n, NULL);
} else if (imageType == TIFF) {
// page: int, n: int, autorotate: bool, subifd: int
code =
vips_tiffload_buffer(buf, len, out, "page", params->page, "n",
params->n, "autorotate", params->autorotate, NULL);
} else if (imageType == GIF) {
// page: int, n: int, scale: double
code = vips_gifload_buffer(buf, len, out, "page", params->page, "n",
params->n, NULL);
} else if (imageType == PDF) {
// page: int, n: int, dpi: double, scale: double, background: color
code = vips_pdfload_buffer(buf, len, out, "page", params->page, "n",
params->n, "dpi", params->dpi, NULL);
} else if (imageType == SVG) {
// dpi: double, scale: double, unlimited: bool
code = vips_svgload_buffer(buf, len, out, "dpi", params->dpi, "unlimited",
params->svgUnlimited, NULL);
} else if (imageType == HEIF) {
// added autorotate on load as currently it addresses orientation issues
// https://github.com/libvips/libvips/pull/1680
// page: int, n: int, thumbnail: bool
code = vips_heifload_buffer(buf, len, out, "page", params->page, "n",
params->n, "thumbnail", params->heifThumbnail,
"autorotate", TRUE, NULL);
} else if (imageType == MAGICK) {
// page: int, n: int, density: string
code = vips_magickload_buffer(buf, len, out, "page", params->page, "n",
params->n, NULL);
} else if (imageType == AVIF) {
code = vips_heifload_buffer(buf, len, out, "page", params->page, "n",
params->n, "thumbnail", params->heifThumbnail,
"autorotate", params->autorotate, NULL);
}
#if (VIPS_MAJOR_VERSION >= 8) && (VIPS_MINOR_VERSION >= 11)
else if (imageType == JP2K) {
code = vips_jp2kload_buffer(buf, len, out, "page", params->page, NULL);
}
#endif
return code;
}
#define MAYBE_SET_BOOL(OP, PARAM, NAME) \
if (PARAM.is_set) { \
vips_object_set(VIPS_OBJECT(OP), NAME, PARAM.value.b, NULL); \
}
#define MAYBE_SET_INT(OP, PARAM, NAME) \
if (PARAM.is_set) { \
vips_object_set(VIPS_OBJECT(OP), NAME, PARAM.value.i, NULL); \
}
#define MAYBE_SET_DOUBLE(OP, PARAM, NAME) \
if (PARAM.is_set) { \
vips_object_set(VIPS_OBJECT(OP), NAME, PARAM.value.d, NULL); \
}
typedef int (*SetLoadOptionsFn)(VipsOperation *operation, LoadParams *params);
int set_jpegload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_BOOL(operation, params->autorotate, "autorotate");
MAYBE_SET_BOOL(operation, params->fail, "fail");
MAYBE_SET_INT(operation, params->jpegShrink, "shrink");
return 0;
}
int set_pngload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_BOOL(operation, params->fail, "fail");
return 0;
}
int set_webpload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_INT(operation, params->page, "page");
MAYBE_SET_INT(operation, params->n, "n");
return 0;
}
int set_tiffload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_BOOL(operation, params->autorotate, "autorotate");
MAYBE_SET_INT(operation, params->page, "page");
MAYBE_SET_INT(operation, params->n, "n");
return 0;
}
int set_gifload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_INT(operation, params->page, "page");
MAYBE_SET_INT(operation, params->n, "n");
return 0;
}
int set_pdfload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_INT(operation, params->page, "page");
MAYBE_SET_INT(operation, params->n, "n");
MAYBE_SET_DOUBLE(operation, params->dpi, "dpi");
return 0;
}
int set_svgload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_BOOL(operation, params->svgUnlimited, "unlimited");
MAYBE_SET_DOUBLE(operation, params->dpi, "dpi");
return 0;
}
int set_heifload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_BOOL(operation, params->autorotate, "autorotate");
MAYBE_SET_BOOL(operation, params->heifThumbnail, "thumbnail");
MAYBE_SET_INT(operation, params->page, "page");
MAYBE_SET_INT(operation, params->n, "n");
return 0;
}
int set_jp2kload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_INT(operation, params->page, "page");
return 0;
}
int set_jxlload_options(VipsOperation *operation, LoadParams *params) {
// nothing need to do
return 0;
}
int set_magickload_options(VipsOperation *operation, LoadParams *params) {
MAYBE_SET_INT(operation, params->page, "page");
MAYBE_SET_INT(operation, params->n, "n");
return 0;
}
int load_buffer(const char *operationName, void *buf, size_t len,
LoadParams *params, SetLoadOptionsFn setLoadOptions) {
VipsBlob *blob = vips_blob_new(NULL, buf, len);
VipsOperation *operation = vips_operation_new(operationName);
if (!operation) {
return 1;
}
if (vips_object_set(VIPS_OBJECT(operation), "buffer", blob, NULL)) {
vips_area_unref(VIPS_AREA(blob));
return 1;
}
vips_area_unref(VIPS_AREA(blob));
if (setLoadOptions(operation, params)) {
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return 1;
}
if (vips_cache_operation_buildp(&operation)) {
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return 1;
}
g_object_get(VIPS_OBJECT(operation), "out", &params->outputImage, NULL);
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return 0;
}
typedef int (*SetSaveOptionsFn)(VipsOperation *operation, SaveParams *params);
int save_buffer(const char *operationName, SaveParams *params,
SetSaveOptionsFn setSaveOptions) {
VipsBlob *blob;
VipsOperation *operation = vips_operation_new(operationName);
if (!operation) {
return 1;
}
if (vips_object_set(VIPS_OBJECT(operation), "in", params->inputImage, NULL)) {
return 1;
}
if (setSaveOptions(operation, params)) {
g_object_unref(operation);
return 1;
}
if (vips_cache_operation_buildp(&operation)) {
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return 1;
}
g_object_get(VIPS_OBJECT(operation), "buffer", &blob, NULL);
g_object_unref(operation);
VipsArea *area = VIPS_AREA(blob);
params->outputBuffer = (char *)(area->data);
params->outputLen = area->length;
area->free_fn = NULL;
vips_area_unref(area);
return 0;
}
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-jpegsave-buffer
int set_jpegsave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(
VIPS_OBJECT(operation), "strip", params->stripMetadata, "optimize_coding",
params->jpegOptimizeCoding, "interlace", params->interlace,
"subsample_mode", params->jpegSubsample, "trellis_quant",
params->jpegTrellisQuant, "overshoot_deringing",
params->jpegOvershootDeringing, "optimize_scans",
params->jpegOptimizeScans, "quant_table", params->jpegQuantTable, NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-pngsave-buffer
int set_pngsave_options(VipsOperation *operation, SaveParams *params) {
int ret =
vips_object_set(VIPS_OBJECT(operation), "strip", params->stripMetadata,
"compression", params->pngCompression, "interlace",
params->interlace, "filter", params->pngFilter, "palette",
params->pngPalette, NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
if (!ret && params->pngDither) {
ret = vips_object_set(VIPS_OBJECT(operation), "dither", params->pngDither, NULL);
}
if (!ret && params->pngBitdepth) {
ret = vips_object_set(VIPS_OBJECT(operation), "bitdepth", params->pngBitdepth, NULL);
}
// TODO: Handle `profile` param.
return ret;
}
// https://github.com/libvips/libvips/blob/master/libvips/foreign/webpsave.c#L524
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-webpsave-buffer
int set_webpsave_options(VipsOperation *operation, SaveParams *params) {
int ret =
vips_object_set(VIPS_OBJECT(operation),
"strip", params->stripMetadata,
"lossless", params->webpLossless,
"near_lossless", params->webpNearLossless,
"reduction_effort", params->webpReductionEffort,
"profile", params->webpIccProfile ? params->webpIccProfile : "none",
"min_size", params->webpMinSize,
"kmin", params->webpKMin,
"kmax", params->webpKMax,
NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-tiffsave-buffer
int set_tiffsave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(
VIPS_OBJECT(operation), "strip", params->stripMetadata, "compression",
params->tiffCompression, "predictor", params->tiffPredictor, "pyramid",
params->tiffPyramid, "tile_height", params->tiffTileHeight, "tile_width",
params->tiffTileWidth, "tile", params->tiffTile, NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-magicksave-buffer
int set_magicksave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(VIPS_OBJECT(operation), "format", "GIF", "bitdepth", params->gifBitdepth, NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "quality", params->quality,
NULL);
}
return ret;
}
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-gifsave-buffer
int set_gifsave_options(VipsOperation *operation, SaveParams *params) {
int ret = 0;
// See for argument values: https://www.libvips.org/API/current/VipsForeignSave.html#vips-gifsave
if (params->gifDither > 0.0 && params->gifDither <= 10) {
ret = vips_object_set(VIPS_OBJECT(operation), "dither", params->gifDither, NULL);
}
if (params->gifEffort >= 1 && params->gifEffort <= 10) {
ret = vips_object_set(VIPS_OBJECT(operation), "effort", params->gifEffort, NULL);
}
if (params->gifBitdepth >= 1 && params->gifBitdepth <= 8) {
ret = vips_object_set(VIPS_OBJECT(operation), "bitdepth", params->gifBitdepth, NULL);
}
return ret;
}
// https://github.com/libvips/libvips/blob/master/libvips/foreign/heifsave.c#L653
int set_heifsave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(VIPS_OBJECT(operation), "lossless",
params->heifLossless, NULL);
#if (VIPS_MAJOR_VERSION >= 8) && (VIPS_MINOR_VERSION >= 13)
if (!ret && params->heifBitdepth && params->heifEffort) {
ret = vips_object_set(VIPS_OBJECT(operation), "bitdepth",
params->heifBitdepth, "effort", params->heifEffort,
NULL);
}
#else
if (!ret && params->heifEffort) {
ret = vips_object_set(VIPS_OBJECT(operation), "speed", params->heifEffort,
NULL);
}
#endif
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
// https://github.com/libvips/libvips/blob/master/libvips/foreign/heifsave.c#L653
int set_avifsave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(VIPS_OBJECT(operation), "strip", params->stripMetadata, "compression",
VIPS_FOREIGN_HEIF_COMPRESSION_AV1, "lossless",
params->heifLossless, NULL);
#if (VIPS_MAJOR_VERSION >= 8) && (VIPS_MINOR_VERSION >= 13)
if (!ret && params->heifBitdepth && params->heifEffort) {
ret = vips_object_set(VIPS_OBJECT(operation), "bitdepth",
params->heifBitdepth, "effort", params->heifEffort,
NULL);
}
#else
if (!ret && params->heifEffort) {
ret = vips_object_set(VIPS_OBJECT(operation), "speed", params->heifEffort,
NULL);
}
#endif
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
int set_jp2ksave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(
VIPS_OBJECT(operation), "subsample_mode", params->jpegSubsample,
"tile_height", params->jp2kTileHeight, "tile_width", params->jp2kTileWidth,
"lossless", params->jp2kLossless, NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
int set_jxlsave_options(VipsOperation *operation, SaveParams *params) {
int ret = vips_object_set(
VIPS_OBJECT(operation), "tier", params->jxlTier,
"distance", params->jxlDistance, "effort", params->jxlEffort,
"lossless", params->jxlLossless, NULL);
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
int load_from_buffer(LoadParams *params, void *buf, size_t len) {
switch (params->inputFormat) {
case JPEG:
return load_buffer("jpegload_buffer", buf, len, params,
set_jpegload_options);
case PNG:
return load_buffer("pngload_buffer", buf, len, params,
set_pngload_options);
case WEBP:
return load_buffer("webpload_buffer", buf, len, params,
set_webpload_options);
case HEIF:
return load_buffer("heifload_buffer", buf, len, params,
set_heifload_options);
case TIFF:
return load_buffer("tiffload_buffer", buf, len, params,
set_tiffload_options);
case SVG:
return load_buffer("svgload_buffer", buf, len, params,
set_svgload_options);
case GIF:
return load_buffer("gifload_buffer", buf, len, params,
set_gifload_options);
case PDF:
return load_buffer("pdfload_buffer", buf, len, params,
set_pdfload_options);
case MAGICK:
return load_buffer("magickload_buffer", buf, len, params,
set_magickload_options);
case AVIF:
return load_buffer("heifload_buffer", buf, len, params,
set_heifload_options);
case JP2K:
return load_buffer("jp2kload_buffer", buf, len, params,
set_jp2kload_options);
case JXL:
return load_buffer("jxlload_buffer", buf, len, params,
set_jxlload_options);
default:
g_warning("Unsupported input type given: %d", params->inputFormat);
}
return 1;
}
int save_to_buffer(SaveParams *params) {
switch (params->outputFormat) {
case JPEG:
return save_buffer("jpegsave_buffer", params, set_jpegsave_options);
case PNG:
return save_buffer("pngsave_buffer", params, set_pngsave_options);
case WEBP:
return save_buffer("webpsave_buffer", params, set_webpsave_options);
case HEIF:
return save_buffer("heifsave_buffer", params, set_heifsave_options);
case TIFF:
return save_buffer("tiffsave_buffer", params, set_tiffsave_options);
case GIF:
#if (VIPS_MAJOR_VERSION >= 8) && (VIPS_MINOR_VERSION >= 12)
return save_buffer("gifsave_buffer", params, set_gifsave_options);
#else
return save_buffer("magicksave_buffer", params, set_magicksave_options);
#endif
case AVIF:
return save_buffer("heifsave_buffer", params, set_avifsave_options);
case JP2K:
return save_buffer("jp2ksave_buffer", params, set_jp2ksave_options);
case JXL:
return save_buffer("jxlsave_buffer", params, set_jxlsave_options);
default:
g_warning("Unsupported output type given: %d", params->outputFormat);
}
return 1;
}
LoadParams create_load_params(ImageType inputFormat) {
Param defaultParam = {};
LoadParams p = {
.inputFormat = inputFormat,
.inputBlob = NULL,
.outputImage = NULL,
.autorotate = defaultParam,
.fail = defaultParam,
.page = defaultParam,
.n = defaultParam,
.dpi = defaultParam,
.jpegShrink = defaultParam,
.heifThumbnail = defaultParam,
.svgUnlimited = defaultParam,
};
return p;
}
// TODO: Change to same pattern as ImportParams
static SaveParams defaultSaveParams = {
.inputImage = NULL,
.outputBuffer = NULL,
.outputFormat = JPEG,
.outputLen = 0,
.interlace = FALSE,
.quality = 0,
.stripMetadata = FALSE,
.jpegOptimizeCoding = FALSE,
.jpegSubsample = VIPS_FOREIGN_SUBSAMPLE_ON,
.jpegTrellisQuant = FALSE,
.jpegOvershootDeringing = FALSE,
.jpegOptimizeScans = FALSE,
.jpegQuantTable = 0,
.pngCompression = 6,
.pngPalette = FALSE,
.pngBitdepth = 0,
.pngDither = 0,
.pngFilter = VIPS_FOREIGN_PNG_FILTER_NONE,
.gifDither = 0.0,
.gifEffort = 0,
.gifBitdepth = 0,
.webpLossless = FALSE,
.webpNearLossless = FALSE,
.webpReductionEffort = 4,
.webpIccProfile = NULL,
.webpKMax = 0,
.webpKMin = 0,
.webpMinSize = FALSE,
.heifBitdepth = 8,
.heifLossless = FALSE,
.heifEffort = 5,
.tiffCompression = VIPS_FOREIGN_TIFF_COMPRESSION_LZW,
.tiffPredictor = VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL,
.tiffPyramid = FALSE,
.tiffTile = FALSE,
.tiffTileHeight = 256,
.tiffTileWidth = 256,
.jp2kLossless = FALSE,
.jp2kTileHeight = 512,
.jp2kTileWidth = 512,
.jxlTier = 0,
.jxlDistance = 1.0,
.jxlEffort = 7,
.jxlLossless = FALSE,
};
SaveParams create_save_params(ImageType outputFormat) {
SaveParams params = defaultSaveParams;
params.outputFormat = outputFormat;
return params;
}

View File

@@ -1,512 +0,0 @@
package vips
// #include "foreign.h"
import "C"
import (
"bytes"
"encoding/xml"
"fmt"
"golang.org/x/image/bmp"
"golang.org/x/net/html/charset"
"image/png"
"math"
"runtime"
"unsafe"
)
// SubsampleMode correlates to a libvips subsample mode
type SubsampleMode int
// SubsampleMode enum correlating to libvips subsample modes
const (
VipsForeignSubsampleAuto SubsampleMode = C.VIPS_FOREIGN_SUBSAMPLE_AUTO
VipsForeignSubsampleOn SubsampleMode = C.VIPS_FOREIGN_SUBSAMPLE_ON
VipsForeignSubsampleOff SubsampleMode = C.VIPS_FOREIGN_SUBSAMPLE_OFF
VipsForeignSubsampleLast SubsampleMode = C.VIPS_FOREIGN_SUBSAMPLE_LAST
)
// ImageType represents an image type
type ImageType int
// ImageType enum
const (
ImageTypeUnknown ImageType = C.UNKNOWN
ImageTypeGIF ImageType = C.GIF
ImageTypeJPEG ImageType = C.JPEG
ImageTypeMagick ImageType = C.MAGICK
ImageTypePDF ImageType = C.PDF
ImageTypePNG ImageType = C.PNG
ImageTypeSVG ImageType = C.SVG
ImageTypeTIFF ImageType = C.TIFF
ImageTypeWEBP ImageType = C.WEBP
ImageTypeHEIF ImageType = C.HEIF
ImageTypeBMP ImageType = C.BMP
ImageTypeAVIF ImageType = C.AVIF
ImageTypeJP2K ImageType = C.JP2K
ImageTypeJXL ImageType = C.JXL
)
var imageTypeExtensionMap = map[ImageType]string{
ImageTypeGIF: ".gif",
ImageTypeJPEG: ".jpeg",
ImageTypeMagick: ".magick",
ImageTypePDF: ".pdf",
ImageTypePNG: ".png",
ImageTypeSVG: ".svg",
ImageTypeTIFF: ".tiff",
ImageTypeWEBP: ".webp",
ImageTypeHEIF: ".heic",
ImageTypeBMP: ".bmp",
ImageTypeAVIF: ".avif",
ImageTypeJP2K: ".jp2",
ImageTypeJXL: ".jxl",
}
// ImageTypes defines the various image types supported by govips
var ImageTypes = map[ImageType]string{
ImageTypeGIF: "gif",
ImageTypeJPEG: "jpeg",
ImageTypeMagick: "magick",
ImageTypePDF: "pdf",
ImageTypePNG: "png",
ImageTypeSVG: "svg",
ImageTypeTIFF: "tiff",
ImageTypeWEBP: "webp",
ImageTypeHEIF: "heif",
ImageTypeBMP: "bmp",
ImageTypeAVIF: "heif",
ImageTypeJP2K: "jp2k",
ImageTypeJXL: "jxl",
}
// TiffCompression represents method for compressing a tiff at export
type TiffCompression int
// TiffCompression enum
const (
TiffCompressionNone TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_NONE
TiffCompressionJpeg TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_JPEG
TiffCompressionDeflate TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE
TiffCompressionPackbits TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS
TiffCompressionFax4 TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4
TiffCompressionLzw TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_LZW
TiffCompressionWebp TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_WEBP
TiffCompressionZstd TiffCompression = C.VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD
)
// TiffPredictor represents method for compressing a tiff at export
type TiffPredictor int
// TiffPredictor enum
const (
TiffPredictorNone TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_NONE
TiffPredictorHorizontal TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL
TiffPredictorFloat TiffPredictor = C.VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT
)
// PngFilter represents filter algorithms that can be applied before compression.
// See https://www.w3.org/TR/PNG-Filters.html
type PngFilter int
// PngFilter enum
const (
PngFilterNone PngFilter = C.VIPS_FOREIGN_PNG_FILTER_NONE
PngFilterSub PngFilter = C.VIPS_FOREIGN_PNG_FILTER_SUB
PngFilterUo PngFilter = C.VIPS_FOREIGN_PNG_FILTER_UP
PngFilterAvg PngFilter = C.VIPS_FOREIGN_PNG_FILTER_AVG
PngFilterPaeth PngFilter = C.VIPS_FOREIGN_PNG_FILTER_PAETH
PngFilterAll PngFilter = C.VIPS_FOREIGN_PNG_FILTER_ALL
)
// FileExt returns the canonical extension for the ImageType
func (i ImageType) FileExt() string {
if ext, ok := imageTypeExtensionMap[i]; ok {
return ext
}
return ""
}
// IsTypeSupported checks whether given image type is supported by govips
func IsTypeSupported(imageType ImageType) bool {
startupIfNeeded()
return supportedImageTypes[imageType]
}
// DetermineImageType attempts to determine the image type of the given buffer
func DetermineImageType(buf []byte) ImageType {
if len(buf) < 12 {
return ImageTypeUnknown
} else if isJPEG(buf) {
return ImageTypeJPEG
} else if isPNG(buf) {
return ImageTypePNG
} else if isGIF(buf) {
return ImageTypeGIF
} else if isTIFF(buf) {
return ImageTypeTIFF
} else if isWEBP(buf) {
return ImageTypeWEBP
} else if isAVIF(buf) {
return ImageTypeAVIF
} else if isHEIF(buf) {
return ImageTypeHEIF
} else if isSVG(buf) {
return ImageTypeSVG
} else if isBMP(buf) {
return ImageTypeBMP
} else if isJP2K(buf) {
return ImageTypeJP2K
} else if isJXL(buf) {
return ImageTypeJXL
} else if isPDF(buf) {
return ImageTypePDF
} else {
return ImageTypeUnknown
}
}
var jpeg = []byte("\xFF\xD8\xFF")
func isJPEG(buf []byte) bool {
return bytes.HasPrefix(buf, jpeg)
}
var gifHeader = []byte("\x47\x49\x46")
func isGIF(buf []byte) bool {
return bytes.HasPrefix(buf, gifHeader)
}
var pngHeader = []byte("\x89\x50\x4E\x47")
func isPNG(buf []byte) bool {
return bytes.HasPrefix(buf, pngHeader)
}
var tifII = []byte("\x49\x49\x2A\x00")
var tifMM = []byte("\x4D\x4D\x00\x2A")
func isTIFF(buf []byte) bool {
return bytes.HasPrefix(buf, tifII) || bytes.HasPrefix(buf, tifMM)
}
var webpHeader = []byte("\x57\x45\x42\x50")
func isWEBP(buf []byte) bool {
return bytes.Equal(buf[8:12], webpHeader)
}
// https://github.com/strukturag/libheif/blob/master/libheif/heif.cc
var ftyp = []byte("ftyp")
var heic = []byte("heic")
var mif1 = []byte("mif1")
var msf1 = []byte("msf1")
var avif = []byte("avif")
func isHEIF(buf []byte) bool {
return bytes.Equal(buf[4:8], ftyp) && (bytes.Equal(buf[8:12], heic) ||
bytes.Equal(buf[8:12], mif1) ||
bytes.Equal(buf[8:12], msf1)) ||
isAVIF(buf)
}
func isAVIF(buf []byte) bool {
return bytes.Equal(buf[4:8], ftyp) && bytes.Equal(buf[8:12], avif)
}
var svg = []byte("<svg")
func isSVG(buf []byte) bool {
sub := buf[:int(math.Min(1024.0, float64(len(buf))))]
if bytes.Contains(sub, svg) {
data := &struct {
XMLName xml.Name `xml:"svg"`
}{}
reader := bytes.NewReader(buf)
decoder := xml.NewDecoder(reader)
decoder.Strict = false
decoder.CharsetReader = charset.NewReaderLabel
err := decoder.Decode(data)
return err == nil && data.XMLName.Local == "svg"
}
return false
}
var pdf = []byte("\x25\x50\x44\x46")
func isPDF(buf []byte) bool {
if len(buf) <= 1024 {
return bytes.Contains(buf, pdf)
}
return bytes.Contains(buf[:1024], pdf)
}
var bmpHeader = []byte("BM")
func isBMP(buf []byte) bool {
return bytes.HasPrefix(buf, bmpHeader)
}
// X'0000 000C 6A50 2020 0D0A 870A'
var jp2kHeader = []byte("\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A")
// https://datatracker.ietf.org/doc/html/rfc3745
func isJP2K(buf []byte) bool {
return bytes.HasPrefix(buf, jp2kHeader)
}
// As a 'naked' codestream
var jxlHeader = []byte("\xff\x0a")
// As an ISOBMFF-based container: 0x0000000C 4A584C20 0D0A870A
var jxlHeaderISOBMFF = []byte("\x00\x00\x00\x0C\x4A\x58\x4C\x20\x0D\x0A\x87\x0A")
func isJXL(buf []byte) bool {
return bytes.HasPrefix(buf, jxlHeader) || bytes.HasPrefix(buf, jxlHeaderISOBMFF)
}
func vipsLoadFromBuffer(buf []byte, params *ImportParams) (*C.VipsImage, ImageType, ImageType, error) {
src := buf
// Reference src here so it's not garbage collected during image initialization.
defer runtime.KeepAlive(src)
var err error
originalType := DetermineImageType(src)
currentType := originalType
if originalType == ImageTypeBMP {
src, err = bmpToPNG(src)
if err != nil {
return nil, currentType, originalType, err
}
currentType = ImageTypePNG
}
if !IsTypeSupported(currentType) {
govipsLog("govips", LogLevelInfo, fmt.Sprintf("failed to understand image format size=%d", len(src)))
return nil, currentType, originalType, ErrUnsupportedImageFormat
}
importParams := createImportParams(currentType, params)
if err := C.load_from_buffer(&importParams, unsafe.Pointer(&src[0]), C.size_t(len(src))); err != 0 {
return nil, currentType, originalType, handleImageError(importParams.outputImage)
}
return importParams.outputImage, currentType, originalType, nil
}
func bmpToPNG(src []byte) ([]byte, error) {
i, err := bmp.Decode(bytes.NewReader(src))
if err != nil {
return nil, err
}
var w bytes.Buffer
pngEnc := png.Encoder{
CompressionLevel: png.NoCompression,
}
err = pngEnc.Encode(&w, i)
if err != nil {
return nil, err
}
return w.Bytes(), nil
}
func maybeSetBoolParam(p BoolParameter, cp *C.Param) {
if p.IsSet() {
C.set_bool_param(cp, toGboolean(p.Get()))
}
}
func maybeSetIntParam(p IntParameter, cp *C.Param) {
if p.IsSet() {
C.set_int_param(cp, C.int(p.Get()))
}
}
func createImportParams(format ImageType, params *ImportParams) C.LoadParams {
p := C.create_load_params(C.ImageType(format))
maybeSetBoolParam(params.AutoRotate, &p.autorotate)
maybeSetBoolParam(params.FailOnError, &p.fail)
maybeSetIntParam(params.Page, &p.page)
maybeSetIntParam(params.NumPages, &p.n)
maybeSetIntParam(params.JpegShrinkFactor, &p.jpegShrink)
maybeSetBoolParam(params.HeifThumbnail, &p.heifThumbnail)
maybeSetBoolParam(params.SvgUnlimited, &p.svgUnlimited)
if params.Density.IsSet() {
C.set_double_param(&p.dpi, C.gdouble(params.Density.Get()))
}
return p
}
func vipsSaveJPEGToBuffer(in *C.VipsImage, params JpegExportParams) ([]byte, error) {
incOpCounter("save_jpeg_buffer")
p := C.create_save_params(C.JPEG)
p.inputImage = in
p.stripMetadata = C.int(boolToInt(params.StripMetadata))
p.quality = C.int(params.Quality)
p.interlace = C.int(boolToInt(params.Interlace))
p.jpegOptimizeCoding = C.int(boolToInt(params.OptimizeCoding))
p.jpegSubsample = C.VipsForeignSubsample(params.SubsampleMode)
p.jpegTrellisQuant = C.int(boolToInt(params.TrellisQuant))
p.jpegOvershootDeringing = C.int(boolToInt(params.OvershootDeringing))
p.jpegOptimizeScans = C.int(boolToInt(params.OptimizeScans))
p.jpegQuantTable = C.int(params.QuantTable)
return vipsSaveToBuffer(p)
}
func vipsSavePNGToBuffer(in *C.VipsImage, params PngExportParams) ([]byte, error) {
incOpCounter("save_png_buffer")
p := C.create_save_params(C.PNG)
p.inputImage = in
p.quality = C.int(params.Quality)
p.stripMetadata = C.int(boolToInt(params.StripMetadata))
p.interlace = C.int(boolToInt(params.Interlace))
p.pngCompression = C.int(params.Compression)
p.pngFilter = C.VipsForeignPngFilter(params.Filter)
p.pngPalette = C.int(boolToInt(params.Palette))
p.pngDither = C.double(params.Dither)
p.pngBitdepth = C.int(params.Bitdepth)
return vipsSaveToBuffer(p)
}
func vipsSaveWebPToBuffer(in *C.VipsImage, params WebpExportParams) ([]byte, error) {
incOpCounter("save_webp_buffer")
p := C.create_save_params(C.WEBP)
p.inputImage = in
p.stripMetadata = C.int(boolToInt(params.StripMetadata))
p.quality = C.int(params.Quality)
p.webpLossless = C.int(boolToInt(params.Lossless))
p.webpNearLossless = C.int(boolToInt(params.NearLossless))
p.webpReductionEffort = C.int(params.ReductionEffort)
p.webpMinSize = C.int(boolToInt(params.MinSize))
p.webpKMin = C.int(params.MinKeyFrames)
p.webpKMax = C.int(params.MaxKeyFrames)
if params.IccProfile != "" {
p.webpIccProfile = C.CString(params.IccProfile)
defer C.free(unsafe.Pointer(p.webpIccProfile))
}
return vipsSaveToBuffer(p)
}
func vipsSaveTIFFToBuffer(in *C.VipsImage, params TiffExportParams) ([]byte, error) {
incOpCounter("save_tiff_buffer")
p := C.create_save_params(C.TIFF)
p.inputImage = in
p.stripMetadata = C.int(boolToInt(params.StripMetadata))
p.quality = C.int(params.Quality)
p.tiffCompression = C.VipsForeignTiffCompression(params.Compression)
p.tiffPyramid = C.int(boolToInt(params.Pyramid))
p.tiffTile = C.int(boolToInt(params.Tile))
p.tiffTileHeight = C.int(params.TileHeight)
p.tiffTileWidth = C.int(params.TileWidth)
return vipsSaveToBuffer(p)
}
func vipsSaveHEIFToBuffer(in *C.VipsImage, params HeifExportParams) ([]byte, error) {
incOpCounter("save_heif_buffer")
p := C.create_save_params(C.HEIF)
p.inputImage = in
p.outputFormat = C.HEIF
p.quality = C.int(params.Quality)
p.heifLossless = C.int(boolToInt(params.Lossless))
p.heifBitdepth = C.int(params.Bitdepth)
p.heifEffort = C.int(params.Effort)
return vipsSaveToBuffer(p)
}
func vipsSaveAVIFToBuffer(in *C.VipsImage, params AvifExportParams) ([]byte, error) {
incOpCounter("save_heif_buffer")
// Speed was deprecated but we want to avoid breaking code that still uses it:
effort := params.Effort
if params.Speed != 0 {
effort = params.Speed
}
p := C.create_save_params(C.AVIF)
p.inputImage = in
p.stripMetadata = C.int(boolToInt(params.StripMetadata))
p.outputFormat = C.AVIF
p.quality = C.int(params.Quality)
p.heifLossless = C.int(boolToInt(params.Lossless))
p.heifBitdepth = C.int(params.Bitdepth)
p.heifEffort = C.int(effort)
return vipsSaveToBuffer(p)
}
func vipsSaveJP2KToBuffer(in *C.VipsImage, params Jp2kExportParams) ([]byte, error) {
incOpCounter("save_jp2k_buffer")
p := C.create_save_params(C.JP2K)
p.inputImage = in
p.outputFormat = C.JP2K
p.quality = C.int(params.Quality)
p.jp2kLossless = C.int(boolToInt(params.Lossless))
p.jp2kTileWidth = C.int(params.TileWidth)
p.jp2kTileHeight = C.int(params.TileHeight)
p.jpegSubsample = C.VipsForeignSubsample(params.SubsampleMode)
return vipsSaveToBuffer(p)
}
func vipsSaveGIFToBuffer(in *C.VipsImage, params GifExportParams) ([]byte, error) {
incOpCounter("save_gif_buffer")
p := C.create_save_params(C.GIF)
p.inputImage = in
p.quality = C.int(params.Quality)
p.gifDither = C.double(params.Dither)
p.gifEffort = C.int(params.Effort)
p.gifBitdepth = C.int(params.Bitdepth)
return vipsSaveToBuffer(p)
}
func vipsSaveJxlToBuffer(in *C.VipsImage, params JxlExportParams) ([]byte, error) {
incOpCounter("save_jxl_buffer")
p := C.create_save_params(C.JXL)
p.inputImage = in
p.outputFormat = C.JXL
p.quality = C.int(params.Quality)
p.jxlLossless = C.int(boolToInt(params.Lossless))
p.jxlTier = C.int(params.Tier)
p.jxlDistance = C.double(params.Distance)
p.jxlEffort = C.int(params.Effort)
return vipsSaveToBuffer(p)
}
func vipsSaveToBuffer(params C.struct_SaveParams) ([]byte, error) {
if err := C.save_to_buffer(&params); err != 0 {
return nil, handleSaveBufferError(params.outputBuffer)
}
buf := C.GoBytes(params.outputBuffer, C.int(params.outputLen))
defer gFreePointer(params.outputBuffer)
return buf, nil
}

View File

@@ -1,141 +0,0 @@
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html
// clang-format off
// include order matters
#include <stdlib.h>
#include <vips/vips.h>
#include <vips/foreign.h>
// clang-format n
#ifndef BOOL
#define BOOL int
#endif
typedef enum types {
UNKNOWN = 0,
JPEG,
WEBP,
PNG,
TIFF,
GIF,
PDF,
SVG,
MAGICK,
HEIF,
BMP,
AVIF,
JP2K,
JXL
} ImageType;
typedef enum ParamType {
PARAM_TYPE_NULL,
PARAM_TYPE_BOOL,
PARAM_TYPE_INT,
PARAM_TYPE_DOUBLE,
} ParamType;
typedef struct Param {
ParamType type;
union Value {
gboolean b;
gint i;
gdouble d;
} value;
gboolean is_set;
} Param;
void set_bool_param(Param *p, gboolean b);
void set_int_param(Param *p, gint i);
void set_double_param(Param *p, gdouble d);
typedef struct LoadParams {
ImageType inputFormat;
VipsBlob *inputBlob;
VipsImage *outputImage;
Param autorotate;
Param fail;
Param page;
Param n;
Param dpi;
Param jpegShrink;
Param heifThumbnail;
Param svgUnlimited;
} LoadParams;
LoadParams create_load_params(ImageType inputFormat);
int load_from_buffer(LoadParams *params, void *buf, size_t len);
typedef struct SaveParams {
VipsImage *inputImage;
void *outputBuffer;
ImageType outputFormat;
size_t outputLen;
BOOL stripMetadata;
int quality;
BOOL interlace;
// JPEG
BOOL jpegOptimizeCoding;
VipsForeignSubsample jpegSubsample;
BOOL jpegTrellisQuant;
BOOL jpegOvershootDeringing;
BOOL jpegOptimizeScans;
int jpegQuantTable;
// PNG
int pngCompression;
VipsForeignPngFilter pngFilter;
BOOL pngPalette;
double pngDither;
int pngBitdepth;
// GIF (with CGIF)
double gifDither;
int gifEffort;
int gifBitdepth;
// WEBP
BOOL webpLossless;
BOOL webpNearLossless;
int webpReductionEffort;
char *webpIccProfile;
BOOL webpMinSize;
int webpKMin;
int webpKMax;
// HEIF - https://github.com/libvips/libvips/blob/master/libvips/foreign/heifsave.c#L71
int heifBitdepth; // Bitdepth to save at for >8 bit images
BOOL heifLossless; // Lossless compression
int heifEffort; // CPU effort (0 - 9)
// TIFF
VipsForeignTiffCompression tiffCompression;
VipsForeignTiffPredictor tiffPredictor;
BOOL tiffPyramid;
BOOL tiffTile;
int tiffTileHeight;
int tiffTileWidth;
// JPEG2000
BOOL jp2kLossless;
int jp2kTileWidth;
int jp2kTileHeight;
// JXL
int jxlTier;
double jxlDistance;
int jxlEffort;
BOOL jxlLossless;
} SaveParams;
SaveParams create_save_params(ImageType outputFormat);
int save_to_buffer(SaveParams *params);

View File

@@ -1,27 +0,0 @@
#include "govips.h"
static void govips_logging_handler(const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message, gpointer user_data) {
govipsLoggingHandler((char *)log_domain, (int)log_level, (char *)message);
}
static void null_logging_handler(const gchar *log_domain,
GLogLevelFlags log_level, const gchar *message,
gpointer user_data) {}
void vips_set_logging_handler(void) {
g_log_set_default_handler(govips_logging_handler, NULL);
}
void vips_unset_logging_handler(void) {
g_log_set_default_handler(null_logging_handler, NULL);
}
/* This function skips the Govips logging handler and logs
directly to stdout. To be used only for testing and debugging.
Needed for CI because of a Go macOS bug which doesn't clean cgo callbacks on
exit. */
void vips_default_logging_handler(void) {
g_log_set_default_handler(g_log_default_handler, NULL);
}

View File

@@ -1,265 +0,0 @@
// Package vips provides go bindings for libvips, a fast image processing library.
package vips
// #cgo pkg-config: vips
// #include <vips/vips.h>
// #include "govips.h"
import "C"
import (
"fmt"
"os"
"runtime"
"strings"
"sync"
)
const (
defaultConcurrencyLevel = 1
defaultMaxCacheMem = 50 * 1024 * 1024
defaultMaxCacheSize = 100
defaultMaxCacheFiles = 0
)
var (
// Version is the full libvips version string (x.y.z)
Version = C.GoString(C.vips_version_string())
// MajorVersion is the libvips major component of the version string (x in x.y.z)
MajorVersion = int(C.vips_version(0))
// MinorVersion is the libvips minor component of the version string (y in x.y.z)
MinorVersion = int(C.vips_version(1))
// MicroVersion is the libvips micro component of the version string (z in x.y.z)
// Also known as patch version
MicroVersion = int(C.vips_version(2))
running = false
hasShutdown = false
initLock sync.Mutex
statCollectorDone chan struct{}
once sync.Once
typeLoaders = make(map[string]ImageType)
supportedImageTypes = make(map[ImageType]bool)
)
// Config allows fine-tuning of libvips library
type Config struct {
ConcurrencyLevel int
MaxCacheFiles int
MaxCacheMem int
MaxCacheSize int
ReportLeaks bool
CacheTrace bool
CollectStats bool
}
// Startup sets up the libvips support and ensures the versions are correct. Pass in nil for
// default configuration.
func Startup(config *Config) {
if hasShutdown {
panic("govips cannot be stopped and restarted")
}
initLock.Lock()
defer initLock.Unlock()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if running {
govipsLog("govips", LogLevelInfo, "warning libvips already started")
return
}
if MajorVersion < 8 {
panic("govips requires libvips version 8.10+")
}
if MajorVersion == 8 && MinorVersion < 10 {
panic("govips requires libvips version 8.10+")
}
cName := C.CString("govips")
defer freeCString(cName)
// Initialize govips logging handler and verbosity filter to historical default
if !currentLoggingOverridden {
govipsLoggingSettings(nil, LogLevelInfo)
}
// Override default glib logging handler to intercept logging messages
enableLogging()
err := C.vips_init(cName)
if err != 0 {
panic(fmt.Sprintf("Failed to start vips code=%v", err))
}
running = true
if config != nil {
if config.CollectStats {
statCollectorDone = collectStats()
}
C.vips_leak_set(toGboolean(config.ReportLeaks))
if config.ConcurrencyLevel >= 0 {
C.vips_concurrency_set(C.int(config.ConcurrencyLevel))
} else {
C.vips_concurrency_set(defaultConcurrencyLevel)
}
if config.MaxCacheFiles >= 0 {
C.vips_cache_set_max_files(C.int(config.MaxCacheFiles))
} else {
C.vips_cache_set_max_files(defaultMaxCacheFiles)
}
if config.MaxCacheMem >= 0 {
C.vips_cache_set_max_mem(C.size_t(config.MaxCacheMem))
} else {
C.vips_cache_set_max_mem(defaultMaxCacheMem)
}
if config.MaxCacheSize >= 0 {
C.vips_cache_set_max(C.int(config.MaxCacheSize))
} else {
C.vips_cache_set_max(defaultMaxCacheSize)
}
if config.CacheTrace {
C.vips_cache_set_trace(toGboolean(true))
}
} else {
C.vips_concurrency_set(defaultConcurrencyLevel)
C.vips_cache_set_max(defaultMaxCacheSize)
C.vips_cache_set_max_mem(defaultMaxCacheMem)
C.vips_cache_set_max_files(defaultMaxCacheFiles)
}
govipsLog("govips", LogLevelInfo, fmt.Sprintf("vips %s started with concurrency=%d cache_max_files=%d cache_max_mem=%d cache_max=%d",
Version,
int(C.vips_concurrency_get()),
int(C.vips_cache_get_max_files()),
int(C.vips_cache_get_max_mem()),
int(C.vips_cache_get_max())))
initTypes()
}
func enableLogging() {
C.vips_set_logging_handler()
}
func disableLogging() {
C.vips_unset_logging_handler()
}
// consoleLogging overrides the Govips logging handler and makes glib
// use its default logging handler which outputs everything to console.
// Needed for CI unit testing due to a macOS bug in Go (doesn't clean cgo callbacks on exit)
func consoleLogging() {
C.vips_default_logging_handler()
}
// Shutdown libvips
func Shutdown() {
hasShutdown = true
if statCollectorDone != nil {
statCollectorDone <- struct{}{}
}
initLock.Lock()
defer initLock.Unlock()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if !running {
govipsLog("govips", LogLevelInfo, "warning libvips not started")
return
}
if temporaryDirectory != "" {
os.RemoveAll(temporaryDirectory)
}
C.vips_shutdown()
disableLogging()
running = false
}
// ShutdownThread clears the cache for for the given thread. This needs to be
// called when a thread using vips exits.
func ShutdownThread() {
C.vips_thread_shutdown()
}
// ClearCache drops the whole operation cache, handy for leak tracking.
func ClearCache() {
C.vips_cache_drop_all()
}
// PrintCache prints the whole operation cache to stdout for debugging purposes.
func PrintCache() {
C.vips_cache_print()
}
// PrintObjectReport outputs all of the current internal objects in libvips
func PrintObjectReport(label string) {
govipsLog("govips", LogLevelInfo, fmt.Sprintf("\n=======================================\nvips live objects: %s...\n", label))
C.vips_object_print_all()
govipsLog("govips", LogLevelInfo, "=======================================\n\n")
}
// MemoryStats is a data structure that houses various memory statistics from ReadVipsMemStats()
type MemoryStats struct {
Mem int64
MemHigh int64
Files int64
Allocs int64
}
// ReadVipsMemStats returns various memory statistics such as allocated memory and open files.
func ReadVipsMemStats(stats *MemoryStats) {
stats.Mem = int64(C.vips_tracked_get_mem())
stats.MemHigh = int64(C.vips_tracked_get_mem_highwater())
stats.Allocs = int64(C.vips_tracked_get_allocs())
stats.Files = int64(C.vips_tracked_get_files())
}
func startupIfNeeded() {
if !running {
govipsLog("govips", LogLevelInfo, "libvips was forcibly started automatically, consider calling Startup/Shutdown yourself")
Startup(nil)
}
}
// InitTypes initializes caches and figures out which image types are supported
func initTypes() {
once.Do(func() {
cType := C.CString("VipsOperation")
defer freeCString(cType)
for k, v := range ImageTypes {
name := strings.ToLower("VipsForeignLoad" + v)
typeLoaders[name] = k
typeLoaders[name+"buffer"] = k
cFunc := C.CString(v + "load")
//noinspection GoDeferInLoop
defer freeCString(cFunc)
ret := C.vips_type_find(cType, cFunc)
supportedImageTypes[k] = int(ret) != 0
if supportedImageTypes[k] {
govipsLog("govips", LogLevelInfo, fmt.Sprintf("registered image type loader type=%s", v))
}
}
})
}

View File

@@ -1,122 +0,0 @@
#include "header.h"
#include <unistd.h>
unsigned long has_icc_profile(VipsImage *in) {
return vips_image_get_typeof(in, VIPS_META_ICC_NAME);
}
unsigned long get_icc_profile(VipsImage *in, const void **data,
size_t *dataLength) {
return image_get_blob(in, VIPS_META_ICC_NAME, data, dataLength);
}
gboolean remove_icc_profile(VipsImage *in) {
return vips_image_remove(in, VIPS_META_ICC_NAME);
}
unsigned long has_iptc(VipsImage *in) {
return vips_image_get_typeof(in, VIPS_META_IPTC_NAME);
}
char **image_get_fields(VipsImage *in) { return vips_image_get_fields(in); }
void image_set_string(VipsImage *in, const char *name, const char *str) {
vips_image_set_string(in, name, str);
}
unsigned long image_get_string(VipsImage *in, const char *name,
const char **out) {
return vips_image_get_string(in, name, out);
}
unsigned long image_get_as_string(VipsImage *in, const char *name, char **out) {
return vips_image_get_as_string(in, name, out);
}
void remove_field(VipsImage *in, char *field) { vips_image_remove(in, field); }
int get_meta_orientation(VipsImage *in) {
int orientation = 0;
if (vips_image_get_typeof(in, VIPS_META_ORIENTATION) != 0) {
vips_image_get_int(in, VIPS_META_ORIENTATION, &orientation);
}
return orientation;
}
void remove_meta_orientation(VipsImage *in) {
vips_image_remove(in, VIPS_META_ORIENTATION);
}
void set_meta_orientation(VipsImage *in, int orientation) {
vips_image_set_int(in, VIPS_META_ORIENTATION, orientation);
}
// https://libvips.github.io/libvips/API/current/libvips-header.html#vips-image-get-n-pages
int get_image_n_pages(VipsImage *in) {
int n_pages = 0;
n_pages = vips_image_get_n_pages(in);
return n_pages;
}
void set_image_n_pages(VipsImage *in, int n_pages) {
vips_image_set_int(in, VIPS_META_N_PAGES, n_pages);
}
// https://www.libvips.org/API/current/libvips-header.html#vips-image-get-page-height
int get_page_height(VipsImage *in) {
int page_height = 0;
page_height = vips_image_get_page_height(in);
return page_height;
}
void set_page_height(VipsImage *in, int height) {
vips_image_set_int(in, VIPS_META_PAGE_HEIGHT, height);
}
int get_meta_loader(const VipsImage *in, const char **out) {
return vips_image_get_string(in, VIPS_META_LOADER, out);
}
int get_image_delay(VipsImage *in, int **out) {
return vips_image_get_array_int(in, "delay", out, NULL);
}
void set_image_delay(VipsImage *in, const int *array, int n) {
return vips_image_set_array_int(in, "delay", array, n);
}
void image_set_double(VipsImage *in, const char *name, double i) {
vips_image_set_double(in, name, i);
}
unsigned long image_get_double(VipsImage *in, const char *name, double *out) {
return vips_image_get_double(in, name, out);
}
void image_set_int(VipsImage *in, const char *name, int i) {
vips_image_set_int(in, name, i);
}
unsigned long image_get_int(VipsImage *in, const char *name, int *out) {
return vips_image_get_int(in, name, out);
}
void image_set_blob(VipsImage *in, const char *name, const void *data,
size_t dataLength) {
vips_image_set_blob_copy(in, name, data, dataLength);
}
unsigned long image_get_blob(VipsImage *in, const char *name, const void **data,
size_t *dataLength) {
if (vips_image_get_typeof(in, name) == 0) {
return 0;
}
if (vips_image_get_blob(in, name, data, dataLength)) {
return -1;
}
return 0;
}

View File

@@ -1,289 +0,0 @@
package vips
// #include "header.h"
import "C"
import (
"strings"
"unsafe"
)
func vipsHasICCProfile(in *C.VipsImage) bool {
return int(C.has_icc_profile(in)) != 0
}
func vipsGetICCProfile(in *C.VipsImage) ([]byte, bool) {
var bufPtr unsafe.Pointer
var dataLength C.size_t
if int(C.get_icc_profile(in, &bufPtr, &dataLength)) != 0 {
return nil, false
}
buf := C.GoBytes(bufPtr, C.int(dataLength))
return buf, true
}
func vipsRemoveICCProfile(in *C.VipsImage) bool {
return fromGboolean(C.remove_icc_profile(in))
}
func vipsHasIPTC(in *C.VipsImage) bool {
return int(C.has_iptc(in)) != 0
}
func vipsImageGetFields(in *C.VipsImage) (fields []string) {
const maxFields = 256
rawFields := C.image_get_fields(in)
defer C.g_strfreev(rawFields)
cFields := (*[maxFields]*C.char)(unsafe.Pointer(rawFields))[:maxFields:maxFields]
for _, field := range cFields {
if field == nil {
break
}
fields = append(fields, C.GoString(field))
}
return
}
func vipsImageGetExifData(in *C.VipsImage) map[string]string {
fields := vipsImageGetFields(in)
exifData := map[string]string{}
for _, field := range fields {
if strings.HasPrefix(field, "exif") {
exifData[field] = vipsImageGetString(in, field)
}
}
return exifData
}
func vipsRemoveMetadata(in *C.VipsImage, keep ...string) {
fields := vipsImageGetFields(in)
retain := append(keep, technicalMetadata...)
for _, field := range fields {
if contains(retain, field) {
continue
}
cField := C.CString(field)
C.remove_field(in, cField)
C.free(unsafe.Pointer(cField))
}
}
var technicalMetadata = []string{
C.VIPS_META_ICC_NAME,
C.VIPS_META_ORIENTATION,
C.VIPS_META_N_PAGES,
C.VIPS_META_PAGE_HEIGHT,
}
func contains(a []string, x string) bool {
for _, n := range a {
if x == n {
return true
}
}
return false
}
func vipsGetMetaOrientation(in *C.VipsImage) int {
return int(C.get_meta_orientation(in))
}
func vipsRemoveMetaOrientation(in *C.VipsImage) {
C.remove_meta_orientation(in)
}
func vipsSetMetaOrientation(in *C.VipsImage, orientation int) {
C.set_meta_orientation(in, C.int(orientation))
}
func vipsGetImageNPages(in *C.VipsImage) int {
return int(C.get_image_n_pages(in))
}
func vipsSetImageNPages(in *C.VipsImage, pages int) {
C.set_image_n_pages(in, C.int(pages))
}
func vipsGetPageHeight(in *C.VipsImage) int {
return int(C.get_page_height(in))
}
func vipsSetPageHeight(in *C.VipsImage, height int) {
C.set_page_height(in, C.int(height))
}
func vipsImageGetMetaLoader(in *C.VipsImage) (string, bool) {
var out *C.char
defer freeCString(out)
code := int(C.get_meta_loader(in, &out))
return C.GoString(out), code == 0
}
func vipsImageGetDelay(in *C.VipsImage, n int) ([]int, error) {
incOpCounter("imageGetDelay")
var out *C.int
defer gFreePointer(unsafe.Pointer(out))
if err := C.get_image_delay(in, &out); err != 0 {
return nil, handleVipsError()
}
return fromCArrayInt(out, n), nil
}
func vipsImageSetDelay(in *C.VipsImage, data []C.int) error {
incOpCounter("imageSetDelay")
if n := len(data); n > 0 {
C.set_image_delay(in, &data[0], C.int(n))
}
return nil
}
// vipsDetermineImageTypeFromMetaLoader determine the image type from vips-loader metadata
func vipsDetermineImageTypeFromMetaLoader(in *C.VipsImage) ImageType {
vipsLoader, ok := vipsImageGetMetaLoader(in)
if vipsLoader == "" || !ok {
return ImageTypeUnknown
}
if strings.HasPrefix(vipsLoader, "jpeg") {
return ImageTypeJPEG
}
if strings.HasPrefix(vipsLoader, "png") {
return ImageTypePNG
}
if strings.HasPrefix(vipsLoader, "gif") {
return ImageTypeGIF
}
if strings.HasPrefix(vipsLoader, "svg") {
return ImageTypeSVG
}
if strings.HasPrefix(vipsLoader, "webp") {
return ImageTypeWEBP
}
if strings.HasPrefix(vipsLoader, "jp2k") {
return ImageTypeJP2K
}
if strings.HasPrefix(vipsLoader, "jxl") {
return ImageTypeJXL
}
if strings.HasPrefix(vipsLoader, "magick") {
return ImageTypeMagick
}
if strings.HasPrefix(vipsLoader, "tiff") {
return ImageTypeTIFF
}
if strings.HasPrefix(vipsLoader, "heif") {
return ImageTypeHEIF
}
if strings.HasPrefix(vipsLoader, "pdf") {
return ImageTypePDF
}
return ImageTypeUnknown
}
func vipsImageSetBlob(in *C.VipsImage, name string, data []byte) {
cData := unsafe.Pointer(&data)
cDataLength := C.size_t(len(data))
cField := C.CString(name)
defer freeCString(cField)
C.image_set_blob(in, cField, cData, cDataLength)
}
func vipsImageGetBlob(in *C.VipsImage, name string) []byte {
var bufPtr unsafe.Pointer
var dataLength C.size_t
cField := C.CString(name)
defer freeCString(cField)
if int(C.image_get_blob(in, cField, &bufPtr, &dataLength)) != 0 {
return nil
}
buf := C.GoBytes(bufPtr, C.int(dataLength))
return buf
}
func vipsImageSetDouble(in *C.VipsImage, name string, f float64) {
cField := C.CString(name)
defer freeCString(cField)
cDouble := C.double(f)
C.image_set_double(in, cField, cDouble)
}
func vipsImageGetDouble(in *C.VipsImage, name string) float64 {
cField := C.CString(name)
defer freeCString(cField)
var cDouble C.double
if int(C.image_get_double(in, cField, &cDouble)) == 0 {
return float64(cDouble)
}
return 0
}
func vipsImageSetInt(in *C.VipsImage, name string, i int) {
cField := C.CString(name)
defer freeCString(cField)
cInt := C.int(i)
C.image_set_int(in, cField, cInt)
}
func vipsImageGetInt(in *C.VipsImage, name string) int {
cField := C.CString(name)
defer freeCString(cField)
var cInt C.int
if int(C.image_get_int(in, cField, &cInt)) == 0 {
return int(cInt)
}
return 0
}
func vipsImageSetString(in *C.VipsImage, name string, str string) {
cField := C.CString(name)
defer freeCString(cField)
cStr := C.CString(str)
defer freeCString(cStr)
C.image_set_string(in, cField, cStr)
}
func vipsImageGetString(in *C.VipsImage, name string) string {
cField := C.CString(name)
defer freeCString(cField)
var cFieldValue *C.char
defer freeCString(cFieldValue)
if int(C.image_get_string(in, cField, &cFieldValue)) == 0 {
return C.GoString(cFieldValue)
}
return ""
}
func vipsImageGetAsString(in *C.VipsImage, name string) string {
cField := C.CString(name)
defer freeCString(cField)
var cFieldValue *C.char
defer freeCString(cFieldValue)
if int(C.image_get_as_string(in, cField, &cFieldValue)) == 0 {
return C.GoString(cFieldValue)
}
return ""
}

View File

@@ -1,41 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-header.html
#include <stdlib.h>
#include <vips/vips.h>
unsigned long has_icc_profile(VipsImage *in);
unsigned long get_icc_profile(VipsImage *in, const void **data,
size_t *dataLength);
int remove_icc_profile(VipsImage *in);
unsigned long has_iptc(VipsImage *in);
char **image_get_fields(VipsImage *in);
void image_set_string(VipsImage *in, const char *name, const char *str);
unsigned long image_get_string(VipsImage *in, const char *name,
const char **out);
unsigned long image_get_as_string(VipsImage *in, const char *name, char **out);
void remove_field(VipsImage *in, char *field);
int get_meta_orientation(VipsImage *in);
void remove_meta_orientation(VipsImage *in);
void set_meta_orientation(VipsImage *in, int orientation);
int get_image_n_pages(VipsImage *in);
void set_image_n_pages(VipsImage *in, int n_pages);
int get_page_height(VipsImage *in);
void set_page_height(VipsImage *in, int height);
int get_meta_loader(const VipsImage *in, const char **out);
int get_image_delay(VipsImage *in, int **out);
void set_image_delay(VipsImage *in, const int *array, int n);
void image_set_blob(VipsImage *in, const char *name, const void *data,
size_t dataLength);
unsigned long image_get_blob(VipsImage *in, const char *name, const void **data,
size_t *dataLength);
void image_set_double(VipsImage *in, const char *name, double i);
unsigned long image_get_double(VipsImage *in, const char *name, double *out);
void image_set_int(VipsImage *in, const char *name, int i);
unsigned long image_get_int(VipsImage *in, const char *name, int *out);

View File

@@ -1,726 +0,0 @@
package vips
import (
"os"
"path/filepath"
"sync"
)
var (
// ATTRIBUTION:
// The following micro icc profile taken from: https://github.com/saucecontrol/Compact-ICC-Profiles.
// Read more (very interesting): https://photosauce.net/blog/post/making-a-minimal-srgb-icc-profile-part-1-trim-the-fat-abuse-the-spec
sRGBV2MicroICCProfile = []byte{
0x00, 0x00, 0x01, 0xc8, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00,
0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
0x07, 0xe2, 0x00, 0x03, 0x00, 0x14, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x1d,
0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
0x73, 0x61, 0x77, 0x73, 0x63, 0x74, 0x72, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x68, 0x61, 0x6e, 0x64,
0x9d, 0x91, 0x00, 0x3d, 0x40, 0x80, 0xb0, 0x3d, 0x40, 0x74, 0x2c, 0x81,
0x9e, 0xa5, 0x22, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x5f,
0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x0c,
0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x14,
0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x14,
0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x14,
0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x00, 0x14,
0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x60,
0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x60,
0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x00, 0x60,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
0x75, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00,
0x43, 0x43, 0x30, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xc9,
0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
0x00, 0x00, 0x38, 0xf2, 0x00, 0x00, 0x03, 0x8f, 0x58, 0x59, 0x5a, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x96, 0x00, 0x00, 0xb7, 0x89,
0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x85, 0x00, 0x00, 0xb6, 0xc4,
0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a,
0x00, 0x00, 0x00, 0x7c, 0x00, 0xf8, 0x01, 0x9c, 0x02, 0x75, 0x03, 0x83,
0x04, 0xc9, 0x06, 0x4e, 0x08, 0x12, 0x0a, 0x18, 0x0c, 0x62, 0x0e, 0xf4,
0x11, 0xcf, 0x14, 0xf6, 0x18, 0x6a, 0x1c, 0x2e, 0x20, 0x43, 0x24, 0xac,
0x29, 0x6a, 0x2e, 0x7e, 0x33, 0xeb, 0x39, 0xb3, 0x3f, 0xd6, 0x46, 0x57,
0x4d, 0x36, 0x54, 0x76, 0x5c, 0x17, 0x64, 0x1d, 0x6c, 0x86, 0x75, 0x56,
0x7e, 0x8d, 0x88, 0x2c, 0x92, 0x36, 0x9c, 0xab, 0xa7, 0x8c, 0xb2, 0xdb,
0xbe, 0x99, 0xca, 0xc7, 0xd7, 0x65, 0xe4, 0x77, 0xf1, 0xf9, 0xff, 0xff,
}
// ATTRIBUTION:
// The following micro icc profile taken from: https://github.com/saucecontrol/Compact-ICC-Profiles.
// Read more (very interesting): https://photosauce.net/blog/post/making-a-minimal-srgb-icc-profile-part-1-trim-the-fat-abuse-the-spec
sGrayV2MicroICCProfile = []byte{
0x00, 0x00, 0x01, 0x50, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00,
0x6d, 0x6e, 0x74, 0x72, 0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5a, 0x20,
0x07, 0xe2, 0x00, 0x03, 0x00, 0x14, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x1d,
0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
0x73, 0x61, 0x77, 0x73, 0x63, 0x74, 0x72, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x68, 0x61, 0x6e, 0x64,
0x05, 0xd2, 0x02, 0xa7, 0xf9, 0xdd, 0x47, 0x94, 0xc7, 0x4f, 0x4c, 0x5f,
0x26, 0x82, 0x3a, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x5f,
0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x0c,
0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x14,
0x6b, 0x54, 0x52, 0x43, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x60,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
0x75, 0x47, 0x72, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00,
0x43, 0x43, 0x30, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xc9,
0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a,
0x00, 0x00, 0x00, 0x7c, 0x00, 0xf8, 0x01, 0x9c, 0x02, 0x75, 0x03, 0x83,
0x04, 0xc9, 0x06, 0x4e, 0x08, 0x12, 0x0a, 0x18, 0x0c, 0x62, 0x0e, 0xf4,
0x11, 0xcf, 0x14, 0xf6, 0x18, 0x6a, 0x1c, 0x2e, 0x20, 0x43, 0x24, 0xac,
0x29, 0x6a, 0x2e, 0x7e, 0x33, 0xeb, 0x39, 0xb3, 0x3f, 0xd6, 0x46, 0x57,
0x4d, 0x36, 0x54, 0x76, 0x5c, 0x17, 0x64, 0x1d, 0x6c, 0x86, 0x75, 0x56,
0x7e, 0x8d, 0x88, 0x2c, 0x92, 0x36, 0x9c, 0xab, 0xa7, 0x8c, 0xb2, 0xdb,
0xbe, 0x99, 0xca, 0xc7, 0xd7, 0x65, 0xe4, 0x77, 0xf1, 0xf9, 0xff, 0xff,
}
sRGBIEC6196621ICCProfile = []byte{
0x00, 0x00, 0x0b, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
0x07, 0xd9, 0x00, 0x03, 0x00, 0x1b, 0x00, 0x15, 0x00, 0x24, 0x00, 0x1f,
0x61, 0x63, 0x73, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x00, 0x00, 0x00, 0x00,
0x29, 0xf8, 0x3d, 0xde, 0xaf, 0xf2, 0x55, 0xae, 0x78, 0x42, 0xfa, 0xe4,
0xca, 0x83, 0x39, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x00, 0x79,
0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x14,
0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xd4, 0x00, 0x00, 0x08, 0x0c,
0x64, 0x6d, 0x64, 0x64, 0x00, 0x00, 0x09, 0xe0, 0x00, 0x00, 0x00, 0x88,
0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x0a, 0x68, 0x00, 0x00, 0x00, 0x14,
0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xd4, 0x00, 0x00, 0x08, 0x0c,
0x6c, 0x75, 0x6d, 0x69, 0x00, 0x00, 0x0a, 0x7c, 0x00, 0x00, 0x00, 0x14,
0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x0a, 0x90, 0x00, 0x00, 0x00, 0x24,
0x62, 0x6b, 0x70, 0x74, 0x00, 0x00, 0x0a, 0xb4, 0x00, 0x00, 0x00, 0x14,
0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x0a, 0xc8, 0x00, 0x00, 0x00, 0x14,
0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xd4, 0x00, 0x00, 0x08, 0x0c,
0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x0a, 0xdc, 0x00, 0x00, 0x00, 0x0c,
0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x87,
0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x0b, 0x70, 0x00, 0x00, 0x00, 0x14,
0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x0b, 0x84, 0x00, 0x00, 0x00, 0x37,
0x63, 0x68, 0x61, 0x64, 0x00, 0x00, 0x0b, 0xbc, 0x00, 0x00, 0x00, 0x2c,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36,
0x36, 0x2d, 0x32, 0x2d, 0x31, 0x20, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x20,
0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0xb6, 0xcf,
0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff, 0x64, 0x65, 0x73, 0x63,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x49, 0x45, 0x43, 0x20,
0x36, 0x31, 0x39, 0x36, 0x36, 0x2d, 0x32, 0x2d, 0x31, 0x20, 0x44, 0x65,
0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x43, 0x6f,
0x6c, 0x6f, 0x75, 0x72, 0x20, 0x53, 0x70, 0x61, 0x63, 0x65, 0x20, 0x2d,
0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x99,
0x00, 0x00, 0xb7, 0x85, 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6d, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x03, 0x33, 0x00, 0x00, 0x02, 0xa4,
0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa2,
0x00, 0x00, 0x38, 0xf5, 0x00, 0x00, 0x03, 0x90, 0x73, 0x69, 0x67, 0x20,
0x00, 0x00, 0x00, 0x00, 0x43, 0x52, 0x54, 0x20, 0x64, 0x65, 0x73, 0x63,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x52, 0x65, 0x66, 0x65,
0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6e,
0x67, 0x20, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x69, 0x6e, 0x20, 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36,
0x2d, 0x32, 0x2d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x74, 0x65, 0x78, 0x74,
0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
0x74, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x43, 0x6f,
0x6e, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x75, 0x6d, 0x2c, 0x20, 0x32, 0x30,
0x30, 0x39, 0x00, 0x00, 0x73, 0x66, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x0c, 0x44, 0x00, 0x00, 0x05, 0xdf, 0xff, 0xff, 0xf3, 0x26,
0x00, 0x00, 0x07, 0x94, 0x00, 0x00, 0xfd, 0x8f, 0xff, 0xff, 0xfb, 0xa1,
0xff, 0xff, 0xfd, 0xa2, 0x00, 0x00, 0x03, 0xdb, 0x00, 0x00, 0xc0, 0x75,
}
genericGrayGamma22ICCProfile = []byte{
0x00, 0x00, 0x0e, 0x04, 0x61, 0x70, 0x70, 0x6c, 0x02, 0x00, 0x00, 0x00,
0x6d, 0x6e, 0x74, 0x72, 0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5a, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4c, 0x00, 0x00, 0x00, 0x00,
0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x61, 0x70, 0x70, 0x6c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
0x6b, 0x54, 0x52, 0x43, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x08, 0x0c,
0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x08, 0xcc, 0x00, 0x00, 0x00, 0x14,
0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x08, 0xe0, 0x00, 0x00, 0x00, 0x23,
0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0x79,
0x64, 0x73, 0x63, 0x6d, 0x00, 0x00, 0x09, 0x80, 0x00, 0x00, 0x04, 0x82,
0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x19,
0x00, 0x1e, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x37,
0x00, 0x3b, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4a, 0x00, 0x4f, 0x00, 0x54,
0x00, 0x59, 0x00, 0x5e, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6d, 0x00, 0x72,
0x00, 0x77, 0x00, 0x7c, 0x00, 0x81, 0x00, 0x86, 0x00, 0x8b, 0x00, 0x90,
0x00, 0x95, 0x00, 0x9a, 0x00, 0x9f, 0x00, 0xa4, 0x00, 0xa9, 0x00, 0xae,
0x00, 0xb2, 0x00, 0xb7, 0x00, 0xbc, 0x00, 0xc1, 0x00, 0xc6, 0x00, 0xcb,
0x00, 0xd0, 0x00, 0xd5, 0x00, 0xdb, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0xeb,
0x00, 0xf0, 0x00, 0xf6, 0x00, 0xfb, 0x01, 0x01, 0x01, 0x07, 0x01, 0x0d,
0x01, 0x13, 0x01, 0x19, 0x01, 0x1f, 0x01, 0x25, 0x01, 0x2b, 0x01, 0x32,
0x01, 0x38, 0x01, 0x3e, 0x01, 0x45, 0x01, 0x4c, 0x01, 0x52, 0x01, 0x59,
0x01, 0x60, 0x01, 0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 0x83,
0x01, 0x8b, 0x01, 0x92, 0x01, 0x9a, 0x01, 0xa1, 0x01, 0xa9, 0x01, 0xb1,
0x01, 0xb9, 0x01, 0xc1, 0x01, 0xc9, 0x01, 0xd1, 0x01, 0xd9, 0x01, 0xe1,
0x01, 0xe9, 0x01, 0xf2, 0x01, 0xfa, 0x02, 0x03, 0x02, 0x0c, 0x02, 0x14,
0x02, 0x1d, 0x02, 0x26, 0x02, 0x2f, 0x02, 0x38, 0x02, 0x41, 0x02, 0x4b,
0x02, 0x54, 0x02, 0x5d, 0x02, 0x67, 0x02, 0x71, 0x02, 0x7a, 0x02, 0x84,
0x02, 0x8e, 0x02, 0x98, 0x02, 0xa2, 0x02, 0xac, 0x02, 0xb6, 0x02, 0xc1,
0x02, 0xcb, 0x02, 0xd5, 0x02, 0xe0, 0x02, 0xeb, 0x02, 0xf5, 0x03, 0x00,
0x03, 0x0b, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2d, 0x03, 0x38, 0x03, 0x43,
0x03, 0x4f, 0x03, 0x5a, 0x03, 0x66, 0x03, 0x72, 0x03, 0x7e, 0x03, 0x8a,
0x03, 0x96, 0x03, 0xa2, 0x03, 0xae, 0x03, 0xba, 0x03, 0xc7, 0x03, 0xd3,
0x03, 0xe0, 0x03, 0xec, 0x03, 0xf9, 0x04, 0x06, 0x04, 0x13, 0x04, 0x20,
0x04, 0x2d, 0x04, 0x3b, 0x04, 0x48, 0x04, 0x55, 0x04, 0x63, 0x04, 0x71,
0x04, 0x7e, 0x04, 0x8c, 0x04, 0x9a, 0x04, 0xa8, 0x04, 0xb6, 0x04, 0xc4,
0x04, 0xd3, 0x04, 0xe1, 0x04, 0xf0, 0x04, 0xfe, 0x05, 0x0d, 0x05, 0x1c,
0x05, 0x2b, 0x05, 0x3a, 0x05, 0x49, 0x05, 0x58, 0x05, 0x67, 0x05, 0x77,
0x05, 0x86, 0x05, 0x96, 0x05, 0xa6, 0x05, 0xb5, 0x05, 0xc5, 0x05, 0xd5,
0x05, 0xe5, 0x05, 0xf6, 0x06, 0x06, 0x06, 0x16, 0x06, 0x27, 0x06, 0x37,
0x06, 0x48, 0x06, 0x59, 0x06, 0x6a, 0x06, 0x7b, 0x06, 0x8c, 0x06, 0x9d,
0x06, 0xaf, 0x06, 0xc0, 0x06, 0xd1, 0x06, 0xe3, 0x06, 0xf5, 0x07, 0x07,
0x07, 0x19, 0x07, 0x2b, 0x07, 0x3d, 0x07, 0x4f, 0x07, 0x61, 0x07, 0x74,
0x07, 0x86, 0x07, 0x99, 0x07, 0xac, 0x07, 0xbf, 0x07, 0xd2, 0x07, 0xe5,
0x07, 0xf8, 0x08, 0x0b, 0x08, 0x1f, 0x08, 0x32, 0x08, 0x46, 0x08, 0x5a,
0x08, 0x6e, 0x08, 0x82, 0x08, 0x96, 0x08, 0xaa, 0x08, 0xbe, 0x08, 0xd2,
0x08, 0xe7, 0x08, 0xfb, 0x09, 0x10, 0x09, 0x25, 0x09, 0x3a, 0x09, 0x4f,
0x09, 0x64, 0x09, 0x79, 0x09, 0x8f, 0x09, 0xa4, 0x09, 0xba, 0x09, 0xcf,
0x09, 0xe5, 0x09, 0xfb, 0x0a, 0x11, 0x0a, 0x27, 0x0a, 0x3d, 0x0a, 0x54,
0x0a, 0x6a, 0x0a, 0x81, 0x0a, 0x98, 0x0a, 0xae, 0x0a, 0xc5, 0x0a, 0xdc,
0x0a, 0xf3, 0x0b, 0x0b, 0x0b, 0x22, 0x0b, 0x39, 0x0b, 0x51, 0x0b, 0x69,
0x0b, 0x80, 0x0b, 0x98, 0x0b, 0xb0, 0x0b, 0xc8, 0x0b, 0xe1, 0x0b, 0xf9,
0x0c, 0x12, 0x0c, 0x2a, 0x0c, 0x43, 0x0c, 0x5c, 0x0c, 0x75, 0x0c, 0x8e,
0x0c, 0xa7, 0x0c, 0xc0, 0x0c, 0xd9, 0x0c, 0xf3, 0x0d, 0x0d, 0x0d, 0x26,
0x0d, 0x40, 0x0d, 0x5a, 0x0d, 0x74, 0x0d, 0x8e, 0x0d, 0xa9, 0x0d, 0xc3,
0x0d, 0xde, 0x0d, 0xf8, 0x0e, 0x13, 0x0e, 0x2e, 0x0e, 0x49, 0x0e, 0x64,
0x0e, 0x7f, 0x0e, 0x9b, 0x0e, 0xb6, 0x0e, 0xd2, 0x0e, 0xee, 0x0f, 0x09,
0x0f, 0x25, 0x0f, 0x41, 0x0f, 0x5e, 0x0f, 0x7a, 0x0f, 0x96, 0x0f, 0xb3,
0x0f, 0xcf, 0x0f, 0xec, 0x10, 0x09, 0x10, 0x26, 0x10, 0x43, 0x10, 0x61,
0x10, 0x7e, 0x10, 0x9b, 0x10, 0xb9, 0x10, 0xd7, 0x10, 0xf5, 0x11, 0x13,
0x11, 0x31, 0x11, 0x4f, 0x11, 0x6d, 0x11, 0x8c, 0x11, 0xaa, 0x11, 0xc9,
0x11, 0xe8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45, 0x12, 0x64, 0x12, 0x84,
0x12, 0xa3, 0x12, 0xc3, 0x12, 0xe3, 0x13, 0x03, 0x13, 0x23, 0x13, 0x43,
0x13, 0x63, 0x13, 0x83, 0x13, 0xa4, 0x13, 0xc5, 0x13, 0xe5, 0x14, 0x06,
0x14, 0x27, 0x14, 0x49, 0x14, 0x6a, 0x14, 0x8b, 0x14, 0xad, 0x14, 0xce,
0x14, 0xf0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56, 0x15, 0x78, 0x15, 0x9b,
0x15, 0xbd, 0x15, 0xe0, 0x16, 0x03, 0x16, 0x26, 0x16, 0x49, 0x16, 0x6c,
0x16, 0x8f, 0x16, 0xb2, 0x16, 0xd6, 0x16, 0xfa, 0x17, 0x1d, 0x17, 0x41,
0x17, 0x65, 0x17, 0x89, 0x17, 0xae, 0x17, 0xd2, 0x17, 0xf7, 0x18, 0x1b,
0x18, 0x40, 0x18, 0x65, 0x18, 0x8a, 0x18, 0xaf, 0x18, 0xd5, 0x18, 0xfa,
0x19, 0x20, 0x19, 0x45, 0x19, 0x6b, 0x19, 0x91, 0x19, 0xb7, 0x19, 0xdd,
0x1a, 0x04, 0x1a, 0x2a, 0x1a, 0x51, 0x1a, 0x77, 0x1a, 0x9e, 0x1a, 0xc5,
0x1a, 0xec, 0x1b, 0x14, 0x1b, 0x3b, 0x1b, 0x63, 0x1b, 0x8a, 0x1b, 0xb2,
0x1b, 0xda, 0x1c, 0x02, 0x1c, 0x2a, 0x1c, 0x52, 0x1c, 0x7b, 0x1c, 0xa3,
0x1c, 0xcc, 0x1c, 0xf5, 0x1d, 0x1e, 0x1d, 0x47, 0x1d, 0x70, 0x1d, 0x99,
0x1d, 0xc3, 0x1d, 0xec, 0x1e, 0x16, 0x1e, 0x40, 0x1e, 0x6a, 0x1e, 0x94,
0x1e, 0xbe, 0x1e, 0xe9, 0x1f, 0x13, 0x1f, 0x3e, 0x1f, 0x69, 0x1f, 0x94,
0x1f, 0xbf, 0x1f, 0xea, 0x20, 0x15, 0x20, 0x41, 0x20, 0x6c, 0x20, 0x98,
0x20, 0xc4, 0x20, 0xf0, 0x21, 0x1c, 0x21, 0x48, 0x21, 0x75, 0x21, 0xa1,
0x21, 0xce, 0x21, 0xfb, 0x22, 0x27, 0x22, 0x55, 0x22, 0x82, 0x22, 0xaf,
0x22, 0xdd, 0x23, 0x0a, 0x23, 0x38, 0x23, 0x66, 0x23, 0x94, 0x23, 0xc2,
0x23, 0xf0, 0x24, 0x1f, 0x24, 0x4d, 0x24, 0x7c, 0x24, 0xab, 0x24, 0xda,
0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97, 0x25, 0xc7, 0x25, 0xf7,
0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xb7, 0x26, 0xe8, 0x27, 0x18,
0x27, 0x49, 0x27, 0x7a, 0x27, 0xab, 0x27, 0xdc, 0x28, 0x0d, 0x28, 0x3f,
0x28, 0x71, 0x28, 0xa2, 0x28, 0xd4, 0x29, 0x06, 0x29, 0x38, 0x29, 0x6b,
0x29, 0x9d, 0x29, 0xd0, 0x2a, 0x02, 0x2a, 0x35, 0x2a, 0x68, 0x2a, 0x9b,
0x2a, 0xcf, 0x2b, 0x02, 0x2b, 0x36, 0x2b, 0x69, 0x2b, 0x9d, 0x2b, 0xd1,
0x2c, 0x05, 0x2c, 0x39, 0x2c, 0x6e, 0x2c, 0xa2, 0x2c, 0xd7, 0x2d, 0x0c,
0x2d, 0x41, 0x2d, 0x76, 0x2d, 0xab, 0x2d, 0xe1, 0x2e, 0x16, 0x2e, 0x4c,
0x2e, 0x82, 0x2e, 0xb7, 0x2e, 0xee, 0x2f, 0x24, 0x2f, 0x5a, 0x2f, 0x91,
0x2f, 0xc7, 0x2f, 0xfe, 0x30, 0x35, 0x30, 0x6c, 0x30, 0xa4, 0x30, 0xdb,
0x31, 0x12, 0x31, 0x4a, 0x31, 0x82, 0x31, 0xba, 0x31, 0xf2, 0x32, 0x2a,
0x32, 0x63, 0x32, 0x9b, 0x32, 0xd4, 0x33, 0x0d, 0x33, 0x46, 0x33, 0x7f,
0x33, 0xb8, 0x33, 0xf1, 0x34, 0x2b, 0x34, 0x65, 0x34, 0x9e, 0x34, 0xd8,
0x35, 0x13, 0x35, 0x4d, 0x35, 0x87, 0x35, 0xc2, 0x35, 0xfd, 0x36, 0x37,
0x36, 0x72, 0x36, 0xae, 0x36, 0xe9, 0x37, 0x24, 0x37, 0x60, 0x37, 0x9c,
0x37, 0xd7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8c, 0x38, 0xc8, 0x39, 0x05,
0x39, 0x42, 0x39, 0x7f, 0x39, 0xbc, 0x39, 0xf9, 0x3a, 0x36, 0x3a, 0x74,
0x3a, 0xb2, 0x3a, 0xef, 0x3b, 0x2d, 0x3b, 0x6b, 0x3b, 0xaa, 0x3b, 0xe8,
0x3c, 0x27, 0x3c, 0x65, 0x3c, 0xa4, 0x3c, 0xe3, 0x3d, 0x22, 0x3d, 0x61,
0x3d, 0xa1, 0x3d, 0xe0, 0x3e, 0x20, 0x3e, 0x60, 0x3e, 0xa0, 0x3e, 0xe0,
0x3f, 0x21, 0x3f, 0x61, 0x3f, 0xa2, 0x3f, 0xe2, 0x40, 0x23, 0x40, 0x64,
0x40, 0xa6, 0x40, 0xe7, 0x41, 0x29, 0x41, 0x6a, 0x41, 0xac, 0x41, 0xee,
0x42, 0x30, 0x42, 0x72, 0x42, 0xb5, 0x42, 0xf7, 0x43, 0x3a, 0x43, 0x7d,
0x43, 0xc0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8a, 0x44, 0xce, 0x45, 0x12,
0x45, 0x55, 0x45, 0x9a, 0x45, 0xde, 0x46, 0x22, 0x46, 0x67, 0x46, 0xab,
0x46, 0xf0, 0x47, 0x35, 0x47, 0x7b, 0x47, 0xc0, 0x48, 0x05, 0x48, 0x4b,
0x48, 0x91, 0x48, 0xd7, 0x49, 0x1d, 0x49, 0x63, 0x49, 0xa9, 0x49, 0xf0,
0x4a, 0x37, 0x4a, 0x7d, 0x4a, 0xc4, 0x4b, 0x0c, 0x4b, 0x53, 0x4b, 0x9a,
0x4b, 0xe2, 0x4c, 0x2a, 0x4c, 0x72, 0x4c, 0xba, 0x4d, 0x02, 0x4d, 0x4a,
0x4d, 0x93, 0x4d, 0xdc, 0x4e, 0x25, 0x4e, 0x6e, 0x4e, 0xb7, 0x4f, 0x00,
0x4f, 0x49, 0x4f, 0x93, 0x4f, 0xdd, 0x50, 0x27, 0x50, 0x71, 0x50, 0xbb,
0x51, 0x06, 0x51, 0x50, 0x51, 0x9b, 0x51, 0xe6, 0x52, 0x31, 0x52, 0x7c,
0x52, 0xc7, 0x53, 0x13, 0x53, 0x5f, 0x53, 0xaa, 0x53, 0xf6, 0x54, 0x42,
0x54, 0x8f, 0x54, 0xdb, 0x55, 0x28, 0x55, 0x75, 0x55, 0xc2, 0x56, 0x0f,
0x56, 0x5c, 0x56, 0xa9, 0x56, 0xf7, 0x57, 0x44, 0x57, 0x92, 0x57, 0xe0,
0x58, 0x2f, 0x58, 0x7d, 0x58, 0xcb, 0x59, 0x1a, 0x59, 0x69, 0x59, 0xb8,
0x5a, 0x07, 0x5a, 0x56, 0x5a, 0xa6, 0x5a, 0xf5, 0x5b, 0x45, 0x5b, 0x95,
0x5b, 0xe5, 0x5c, 0x35, 0x5c, 0x86, 0x5c, 0xd6, 0x5d, 0x27, 0x5d, 0x78,
0x5d, 0xc9, 0x5e, 0x1a, 0x5e, 0x6c, 0x5e, 0xbd, 0x5f, 0x0f, 0x5f, 0x61,
0x5f, 0xb3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xaa, 0x60, 0xfc, 0x61, 0x4f,
0x61, 0xa2, 0x61, 0xf5, 0x62, 0x49, 0x62, 0x9c, 0x62, 0xf0, 0x63, 0x43,
0x63, 0x97, 0x63, 0xeb, 0x64, 0x40, 0x64, 0x94, 0x64, 0xe9, 0x65, 0x3d,
0x65, 0x92, 0x65, 0xe7, 0x66, 0x3d, 0x66, 0x92, 0x66, 0xe8, 0x67, 0x3d,
0x67, 0x93, 0x67, 0xe9, 0x68, 0x3f, 0x68, 0x96, 0x68, 0xec, 0x69, 0x43,
0x69, 0x9a, 0x69, 0xf1, 0x6a, 0x48, 0x6a, 0x9f, 0x6a, 0xf7, 0x6b, 0x4f,
0x6b, 0xa7, 0x6b, 0xff, 0x6c, 0x57, 0x6c, 0xaf, 0x6d, 0x08, 0x6d, 0x60,
0x6d, 0xb9, 0x6e, 0x12, 0x6e, 0x6b, 0x6e, 0xc4, 0x6f, 0x1e, 0x6f, 0x78,
0x6f, 0xd1, 0x70, 0x2b, 0x70, 0x86, 0x70, 0xe0, 0x71, 0x3a, 0x71, 0x95,
0x71, 0xf0, 0x72, 0x4b, 0x72, 0xa6, 0x73, 0x01, 0x73, 0x5d, 0x73, 0xb8,
0x74, 0x14, 0x74, 0x70, 0x74, 0xcc, 0x75, 0x28, 0x75, 0x85, 0x75, 0xe1,
0x76, 0x3e, 0x76, 0x9b, 0x76, 0xf8, 0x77, 0x56, 0x77, 0xb3, 0x78, 0x11,
0x78, 0x6e, 0x78, 0xcc, 0x79, 0x2a, 0x79, 0x89, 0x79, 0xe7, 0x7a, 0x46,
0x7a, 0xa5, 0x7b, 0x04, 0x7b, 0x63, 0x7b, 0xc2, 0x7c, 0x21, 0x7c, 0x81,
0x7c, 0xe1, 0x7d, 0x41, 0x7d, 0xa1, 0x7e, 0x01, 0x7e, 0x62, 0x7e, 0xc2,
0x7f, 0x23, 0x7f, 0x84, 0x7f, 0xe5, 0x80, 0x47, 0x80, 0xa8, 0x81, 0x0a,
0x81, 0x6b, 0x81, 0xcd, 0x82, 0x30, 0x82, 0x92, 0x82, 0xf4, 0x83, 0x57,
0x83, 0xba, 0x84, 0x1d, 0x84, 0x80, 0x84, 0xe3, 0x85, 0x47, 0x85, 0xab,
0x86, 0x0e, 0x86, 0x72, 0x86, 0xd7, 0x87, 0x3b, 0x87, 0x9f, 0x88, 0x04,
0x88, 0x69, 0x88, 0xce, 0x89, 0x33, 0x89, 0x99, 0x89, 0xfe, 0x8a, 0x64,
0x8a, 0xca, 0x8b, 0x30, 0x8b, 0x96, 0x8b, 0xfc, 0x8c, 0x63, 0x8c, 0xca,
0x8d, 0x31, 0x8d, 0x98, 0x8d, 0xff, 0x8e, 0x66, 0x8e, 0xce, 0x8f, 0x36,
0x8f, 0x9e, 0x90, 0x06, 0x90, 0x6e, 0x90, 0xd6, 0x91, 0x3f, 0x91, 0xa8,
0x92, 0x11, 0x92, 0x7a, 0x92, 0xe3, 0x93, 0x4d, 0x93, 0xb6, 0x94, 0x20,
0x94, 0x8a, 0x94, 0xf4, 0x95, 0x5f, 0x95, 0xc9, 0x96, 0x34, 0x96, 0x9f,
0x97, 0x0a, 0x97, 0x75, 0x97, 0xe0, 0x98, 0x4c, 0x98, 0xb8, 0x99, 0x24,
0x99, 0x90, 0x99, 0xfc, 0x9a, 0x68, 0x9a, 0xd5, 0x9b, 0x42, 0x9b, 0xaf,
0x9c, 0x1c, 0x9c, 0x89, 0x9c, 0xf7, 0x9d, 0x64, 0x9d, 0xd2, 0x9e, 0x40,
0x9e, 0xae, 0x9f, 0x1d, 0x9f, 0x8b, 0x9f, 0xfa, 0xa0, 0x69, 0xa0, 0xd8,
0xa1, 0x47, 0xa1, 0xb6, 0xa2, 0x26, 0xa2, 0x96, 0xa3, 0x06, 0xa3, 0x76,
0xa3, 0xe6, 0xa4, 0x56, 0xa4, 0xc7, 0xa5, 0x38, 0xa5, 0xa9, 0xa6, 0x1a,
0xa6, 0x8b, 0xa6, 0xfd, 0xa7, 0x6e, 0xa7, 0xe0, 0xa8, 0x52, 0xa8, 0xc4,
0xa9, 0x37, 0xa9, 0xa9, 0xaa, 0x1c, 0xaa, 0x8f, 0xab, 0x02, 0xab, 0x75,
0xab, 0xe9, 0xac, 0x5c, 0xac, 0xd0, 0xad, 0x44, 0xad, 0xb8, 0xae, 0x2d,
0xae, 0xa1, 0xaf, 0x16, 0xaf, 0x8b, 0xb0, 0x00, 0xb0, 0x75, 0xb0, 0xea,
0xb1, 0x60, 0xb1, 0xd6, 0xb2, 0x4b, 0xb2, 0xc2, 0xb3, 0x38, 0xb3, 0xae,
0xb4, 0x25, 0xb4, 0x9c, 0xb5, 0x13, 0xb5, 0x8a, 0xb6, 0x01, 0xb6, 0x79,
0xb6, 0xf0, 0xb7, 0x68, 0xb7, 0xe0, 0xb8, 0x59, 0xb8, 0xd1, 0xb9, 0x4a,
0xb9, 0xc2, 0xba, 0x3b, 0xba, 0xb5, 0xbb, 0x2e, 0xbb, 0xa7, 0xbc, 0x21,
0xbc, 0x9b, 0xbd, 0x15, 0xbd, 0x8f, 0xbe, 0x0a, 0xbe, 0x84, 0xbe, 0xff,
0xbf, 0x7a, 0xbf, 0xf5, 0xc0, 0x70, 0xc0, 0xec, 0xc1, 0x67, 0xc1, 0xe3,
0xc2, 0x5f, 0xc2, 0xdb, 0xc3, 0x58, 0xc3, 0xd4, 0xc4, 0x51, 0xc4, 0xce,
0xc5, 0x4b, 0xc5, 0xc8, 0xc6, 0x46, 0xc6, 0xc3, 0xc7, 0x41, 0xc7, 0xbf,
0xc8, 0x3d, 0xc8, 0xbc, 0xc9, 0x3a, 0xc9, 0xb9, 0xca, 0x38, 0xca, 0xb7,
0xcb, 0x36, 0xcb, 0xb6, 0xcc, 0x35, 0xcc, 0xb5, 0xcd, 0x35, 0xcd, 0xb5,
0xce, 0x36, 0xce, 0xb6, 0xcf, 0x37, 0xcf, 0xb8, 0xd0, 0x39, 0xd0, 0xba,
0xd1, 0x3c, 0xd1, 0xbe, 0xd2, 0x3f, 0xd2, 0xc1, 0xd3, 0x44, 0xd3, 0xc6,
0xd4, 0x49, 0xd4, 0xcb, 0xd5, 0x4e, 0xd5, 0xd1, 0xd6, 0x55, 0xd6, 0xd8,
0xd7, 0x5c, 0xd7, 0xe0, 0xd8, 0x64, 0xd8, 0xe8, 0xd9, 0x6c, 0xd9, 0xf1,
0xda, 0x76, 0xda, 0xfb, 0xdb, 0x80, 0xdc, 0x05, 0xdc, 0x8a, 0xdd, 0x10,
0xdd, 0x96, 0xde, 0x1c, 0xde, 0xa2, 0xdf, 0x29, 0xdf, 0xaf, 0xe0, 0x36,
0xe0, 0xbd, 0xe1, 0x44, 0xe1, 0xcc, 0xe2, 0x53, 0xe2, 0xdb, 0xe3, 0x63,
0xe3, 0xeb, 0xe4, 0x73, 0xe4, 0xfc, 0xe5, 0x84, 0xe6, 0x0d, 0xe6, 0x96,
0xe7, 0x1f, 0xe7, 0xa9, 0xe8, 0x32, 0xe8, 0xbc, 0xe9, 0x46, 0xe9, 0xd0,
0xea, 0x5b, 0xea, 0xe5, 0xeb, 0x70, 0xeb, 0xfb, 0xec, 0x86, 0xed, 0x11,
0xed, 0x9c, 0xee, 0x28, 0xee, 0xb4, 0xef, 0x40, 0xef, 0xcc, 0xf0, 0x58,
0xf0, 0xe5, 0xf1, 0x72, 0xf1, 0xff, 0xf2, 0x8c, 0xf3, 0x19, 0xf3, 0xa7,
0xf4, 0x34, 0xf4, 0xc2, 0xf5, 0x50, 0xf5, 0xde, 0xf6, 0x6d, 0xf6, 0xfb,
0xf7, 0x8a, 0xf8, 0x19, 0xf8, 0xa8, 0xf9, 0x38, 0xf9, 0xc7, 0xfa, 0x57,
0xfa, 0xe7, 0xfb, 0x77, 0xfc, 0x07, 0xfc, 0x98, 0xfd, 0x29, 0xfd, 0xba,
0xfe, 0x4b, 0xfe, 0xdc, 0xff, 0x6d, 0xff, 0xff, 0x58, 0x59, 0x5a, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0x51, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x16, 0xcc, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00,
0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x41, 0x70,
0x70, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x2c, 0x20, 0x32, 0x30,
0x30, 0x38, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20,
0x47, 0x72, 0x61, 0x79, 0x20, 0x47, 0x61, 0x6d, 0x6d, 0x61, 0x20, 0x32,
0x2e, 0x32, 0x20, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6c, 0x75, 0x63,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0c,
0x65, 0x6e, 0x55, 0x53, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xdc,
0x65, 0x73, 0x45, 0x53, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x01, 0x18,
0x64, 0x61, 0x44, 0x4b, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0x2a,
0x64, 0x65, 0x44, 0x45, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x01, 0xde,
0x66, 0x69, 0x46, 0x49, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x02, 0xa0,
0x66, 0x72, 0x46, 0x55, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x02, 0x62,
0x69, 0x74, 0x49, 0x54, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x03, 0x70,
0x6e, 0x6c, 0x4e, 0x4c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x64,
0x6e, 0x62, 0x4e, 0x4f, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x03, 0xc4,
0x70, 0x74, 0x42, 0x52, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x03, 0x26,
0x73, 0x76, 0x53, 0x45, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0x2a,
0x6a, 0x61, 0x4a, 0x50, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x03, 0xfe,
0x6b, 0x6f, 0x4b, 0x52, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x04, 0x24,
0x7a, 0x68, 0x54, 0x57, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x04, 0x46,
0x7a, 0x68, 0x43, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x04, 0x64,
0x72, 0x75, 0x52, 0x55, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x01, 0xa4,
0x70, 0x6c, 0x50, 0x4c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0xe6,
0x00, 0x47, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69,
0x00, 0x63, 0x00, 0x20, 0x00, 0x47, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79,
0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61,
0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x20, 0x00, 0x50,
0x00, 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65,
0x00, 0x50, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c,
0x00, 0x20, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0xe9, 0x00, 0x72,
0x00, 0x69, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x64, 0x00, 0x65,
0x00, 0x20, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61,
0x00, 0x20, 0x00, 0x64, 0x00, 0x65, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72,
0x00, 0x69, 0x00, 0x73, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x32,
0x00, 0x2c, 0x00, 0x32, 0x00, 0x41, 0x00, 0x6c, 0x00, 0x67, 0x00, 0x65,
0x00, 0x6d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x67,
0x00, 0x72, 0x00, 0x69, 0x00, 0x6a, 0x00, 0x73, 0x00, 0x20, 0x00, 0x67,
0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x20, 0x00, 0x32,
0x00, 0x2c, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f,
0x00, 0x66, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6c, 0x04, 0x1e, 0x04, 0x31,
0x04, 0x49, 0x04, 0x30, 0x04, 0x4f, 0x00, 0x20, 0x04, 0x41, 0x04, 0x35,
0x04, 0x40, 0x04, 0x30, 0x04, 0x4f, 0x00, 0x20, 0x04, 0x33, 0x04, 0x30,
0x04, 0x3c, 0x04, 0x3c, 0x04, 0x30, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2c,
0x00, 0x32, 0x00, 0x2d, 0x04, 0x3f, 0x04, 0x40, 0x04, 0x3e, 0x04, 0x44,
0x04, 0x38, 0x04, 0x3b, 0x04, 0x4c, 0x00, 0x41, 0x00, 0x6c, 0x00, 0x6c,
0x00, 0x67, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x69, 0x00, 0x6e,
0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x47, 0x00, 0x72, 0x00, 0x61,
0x00, 0x75, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x66, 0x00, 0x65,
0x00, 0x6e, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x69,
0x00, 0x6c, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d,
0x00, 0x61, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x47,
0x00, 0x65, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x73,
0x00, 0x6b, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72, 0x00, 0xe5, 0x00, 0x20,
0x00, 0x32, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x20, 0x00, 0x67, 0x00, 0x61,
0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f,
0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f,
0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x67, 0x00, 0xe9,
0x00, 0x6e, 0x00, 0xe9, 0x00, 0x72, 0x00, 0x69, 0x00, 0x71, 0x00, 0x75,
0x00, 0x65, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72, 0x00, 0x69, 0x00, 0x73,
0x00, 0x20, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61,
0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x59, 0x00, 0x6c,
0x00, 0x65, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x20,
0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x61,
0x00, 0x6e, 0x00, 0x20, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d,
0x00, 0x61, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x20,
0x00, 0x2d, 0x00, 0x70, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x69,
0x00, 0x69, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x4f, 0x00, 0x67, 0x00, 0xf3,
0x00, 0x6c, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x20, 0x00, 0x70, 0x00, 0x72,
0x00, 0x6f, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x73,
0x00, 0x7a, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6f, 0x01, 0x5b, 0x00, 0x63,
0x00, 0x69, 0x00, 0x20, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d,
0x00, 0x61, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x50,
0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x20,
0x00, 0x47, 0x00, 0x65, 0x00, 0x6e, 0x00, 0xe9, 0x00, 0x72, 0x00, 0x69,
0x00, 0x63, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x64, 0x00, 0x61, 0x00, 0x20,
0x00, 0x47, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x20, 0x00, 0x64,
0x00, 0x65, 0x00, 0x20, 0x00, 0x43, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x7a,
0x00, 0x61, 0x00, 0x73, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32,
0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c,
0x00, 0x6f, 0x00, 0x20, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x65,
0x00, 0x72, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x64,
0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x20, 0x00, 0x67,
0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x20, 0x00, 0x64,
0x00, 0x65, 0x00, 0x69, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72, 0x00, 0x69,
0x00, 0x67, 0x00, 0x69, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32,
0x00, 0x47, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69,
0x00, 0x73, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x67, 0x00, 0x72, 0x00, 0xe5,
0x00, 0x20, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61,
0x00, 0x20, 0x00, 0x32, 0x00, 0x2c, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x70,
0x00, 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6c, 0x4e, 0x00,
0x82, 0x2c, 0x30, 0xb0, 0x30, 0xec, 0x30, 0xa4, 0x30, 0xac, 0x30, 0xf3,
0x30, 0xde, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x20,
0x30, 0xd7, 0x30, 0xed, 0x30, 0xd5, 0x30, 0xa1, 0x30, 0xa4, 0x30, 0xeb,
0xc7, 0x7c, 0xbc, 0x18, 0x00, 0x20, 0xd6, 0x8c, 0xc0, 0xc9, 0x00, 0x20,
0xac, 0x10, 0xb9, 0xc8, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x32,
0x00, 0x20, 0xd5, 0x04, 0xb8, 0x5c, 0xd3, 0x0c, 0xc7, 0x7c, 0x90, 0x1a,
0x75, 0x28, 0x70, 0x70, 0x96, 0x8e, 0x51, 0x49, 0x5e, 0xa6, 0x00, 0x20,
0x00, 0x32, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x20, 0x82, 0x72, 0x5f, 0x69,
0x63, 0xcf, 0x8f, 0xf0, 0x90, 0x1a, 0x75, 0x28, 0x70, 0x70, 0x5e, 0xa6,
0x7c, 0xfb, 0x65, 0x70, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x32,
0x00, 0x20, 0x63, 0xcf, 0x8f, 0xf0, 0x65, 0x87, 0x4e, 0xf6, 0x00, 0x00,
}
sRGBV2MicroICCProfilePathToken = "\x00srgb_v2_micro.icc"
sGrayV2MicroICCProfilePathToken = "\x00sgray_v2_micro.icc"
sRGBIEC6196621ICCProfilePathToken = "\x00srgb_iec61966_2_1.icc"
genericGrayGamma22ICCProfilePathToken = "\x00generic_gray_gamma_2_2.icc"
temporaryDirectory = ""
SRGBV2MicroICCProfilePath = sRGBV2MicroICCProfilePathToken
SGrayV2MicroICCProfilePath = sGrayV2MicroICCProfilePathToken
SRGBIEC6196621ICCProfilePath = sRGBIEC6196621ICCProfilePathToken
GenericGrayGamma22ICCProfilePath = genericGrayGamma22ICCProfilePathToken
)
// Back support
func ensureLoadICCPath(name *string) (err error) {
if len(*name) > 0 && (*name)[0] == 0 {
switch *name {
case sRGBV2MicroICCProfilePathToken:
*name, err = GetSRGBV2MicroICCProfilePath()
return
case sGrayV2MicroICCProfilePathToken:
*name, err = GetSGrayV2MicroICCProfilePath()
return
case sRGBIEC6196621ICCProfilePathToken:
*name, err = GetSRGBIEC6196621ICCProfilePath()
return
case genericGrayGamma22ICCProfilePathToken:
*name, err = GetGenericGrayGamma22ICCProfilePath()
return
}
}
return
}
func getTemporaryDirectory() (string, error) {
if temporaryDirectory != "" {
return temporaryDirectory, nil
}
var err error
temporaryDirectory, err = os.MkdirTemp("", "govips-")
if err != nil {
return "", err
}
return temporaryDirectory, nil
}
var lockIcc sync.Mutex
func GetSRGBV2MicroICCProfilePath() (string, error) {
return getOrLoad(&SRGBV2MicroICCProfilePath, "srgb_v2_micro.icc", sRGBV2MicroICCProfile)
}
func GetSGrayV2MicroICCProfilePath() (string, error) {
return getOrLoad(&SGrayV2MicroICCProfilePath, "sgray_v2_micro.icc", sGrayV2MicroICCProfile)
}
func GetSRGBIEC6196621ICCProfilePath() (string, error) {
return getOrLoad(&SRGBIEC6196621ICCProfilePath, "srgb_iec61966_2_1.icc", sRGBIEC6196621ICCProfile)
}
func GetGenericGrayGamma22ICCProfilePath() (string, error) {
return getOrLoad(&GenericGrayGamma22ICCProfilePath, "generic_gray_gamma_2_2.icc", genericGrayGamma22ICCProfile)
}
func getOrLoad(pathFile *string, name string, fileBytes []byte) (string, error) {
lockIcc.Lock()
defer lockIcc.Unlock()
if len(*pathFile) > 0 && (*pathFile)[0] != 0 {
return *pathFile, nil
}
if _, err := getTemporaryDirectory(); err != nil {
return "", err
}
*pathFile = filepath.Join(temporaryDirectory, name)
if err := os.WriteFile(*pathFile, fileBytes, 0600); err != nil {
return "", err
}
return *pathFile, nil
}

View File

@@ -1,9 +0,0 @@
#include "image.h"
int has_alpha_channel(VipsImage *image) { return vips_image_hasalpha(image); }
void clear_image(VipsImage **image) {
// Reference-counting in libvips: https://www.libvips.org/API/current/using-from-c.html#using-C-ref
// https://docs.gtk.org/gobject/method.Object.unref.html
if (G_IS_OBJECT(*image)) g_object_unref(*image);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
// https://libvips.github.io/libvips/API/current/VipsImage.html
#include <stdlib.h>
#include <vips/vips.h>
int has_alpha_channel(VipsImage *image);
void clear_image(VipsImage **image);

View File

@@ -1,37 +0,0 @@
#include "label.h"
int text(VipsImage **out, const char *text, const char *font, int width,
int height, VipsAlign align, int dpi) {
return vips_text(out, text, "font", font, "width", width, "height", height,
"align", align, "dpi", dpi, NULL);
}
int label(VipsImage *in, VipsImage **out, LabelOptions *o) {
double ones[3] = {1, 1, 1};
VipsImage *base = vips_image_new();
VipsImage **t = (VipsImage **)vips_object_local_array(VIPS_OBJECT(base), 9);
if (vips_text(&t[0], o->Text, "font", o->Font, "width", o->Width, "height",
o->Height, "align", o->Align, NULL) ||
vips_linear1(t[0], &t[1], o->Opacity, 0.0, NULL) ||
vips_cast(t[1], &t[2], VIPS_FORMAT_UCHAR, NULL) ||
vips_embed(t[2], &t[3], o->OffsetX, o->OffsetY, t[2]->Xsize + o->OffsetX,
t[2]->Ysize + o->OffsetY, NULL)) {
g_object_unref(base);
return 1;
}
if (vips_black(&t[4], 1, 1, NULL) ||
vips_linear(t[4], &t[5], ones, o->Color, 3, NULL) ||
vips_cast(t[5], &t[6], VIPS_FORMAT_UCHAR, NULL) ||
vips_copy(t[6], &t[7], "interpretation", in->Type, NULL) ||
vips_embed(t[7], &t[8], 0, 0, in->Xsize, in->Ysize, "extend",
VIPS_EXTEND_COPY, NULL)) {
g_object_unref(base);
return 1;
}
if (vips_ifthenelse(t[3], t[8], in, out, "blend", TRUE, NULL)) {
g_object_unref(base);
return 1;
}
g_object_unref(base);
return 0;
}

View File

@@ -1,84 +0,0 @@
package vips
// #include "label.h"
import "C"
import "unsafe"
// Align represents VIPS_ALIGN
type Align int
// Direction enum
const (
AlignLow Align = C.VIPS_ALIGN_LOW
AlignCenter Align = C.VIPS_ALIGN_CENTRE
AlignHigh Align = C.VIPS_ALIGN_HIGH
)
// DefaultFont is the default font to be used for label texts created by govips
const DefaultFont = "sans 10"
// LabelParams represents a text-based label
type LabelParams struct {
Text string
Font string
Width Scalar
Height Scalar
OffsetX Scalar
OffsetY Scalar
Opacity float32
Color Color
Alignment Align
}
type vipsLabelOptions struct {
Text *C.char
Font *C.char
Width C.int
Height C.int
OffsetX C.int
OffsetY C.int
Alignment C.VipsAlign
DPI C.int
Margin C.int
Opacity C.float
Color [3]C.double
}
func labelImage(in *C.VipsImage, params *LabelParams) (*C.VipsImage, error) {
incOpCounter("label")
var out *C.VipsImage
text := C.CString(params.Text)
defer freeCString(text)
font := C.CString(params.Font)
defer freeCString(font)
// todo: release color?
color := [3]C.double{C.double(params.Color.R), C.double(params.Color.G), C.double(params.Color.B)}
w := params.Width.GetRounded(int(in.Xsize))
h := params.Height.GetRounded(int(in.Ysize))
offsetX := params.OffsetX.GetRounded(int(in.Xsize))
offsetY := params.OffsetY.GetRounded(int(in.Ysize))
opts := vipsLabelOptions{
Text: text,
Font: font,
Width: C.int(w),
Height: C.int(h),
OffsetX: C.int(offsetX),
OffsetY: C.int(offsetY),
Alignment: C.VipsAlign(params.Alignment),
Opacity: C.float(params.Opacity),
Color: color,
}
// todo: release inline pointer?
err := C.label(in, &out, (*C.LabelOptions)(unsafe.Pointer(&opts)))
if err != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,21 +0,0 @@
#include <stdlib.h>
#include <vips/vips.h>
typedef struct {
const char *Text;
const char *Font;
int Width;
int Height;
int OffsetX;
int OffsetY;
VipsAlign Align;
int DPI;
int Margin;
float Opacity;
double Color[3];
} LabelOptions;
int label(VipsImage *in, VipsImage **out, LabelOptions *o);
int text(VipsImage **out, const char *text, const char *font, int width,
int height, VipsAlign align, int dpi);

View File

@@ -1,49 +0,0 @@
package vips
// #include <vips/vips.h>
// #include <stdlib.h>
import "C"
import (
"reflect"
"unsafe"
)
func freeCString(s *C.char) {
C.free(unsafe.Pointer(s))
}
func gFreePointer(ref unsafe.Pointer) {
C.g_free(C.gpointer(ref))
}
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}
func toGboolean(b bool) C.gboolean {
if b {
return C.gboolean(1)
}
return C.gboolean(0)
}
func fromGboolean(b C.gboolean) bool {
return b != 0
}
func fromCArrayInt(out *C.int, n int) []int {
var result = make([]int, n)
var data []C.int
sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
sh.Data = uintptr(unsafe.Pointer(out))
sh.Len = n
sh.Cap = n
for i := range data {
result[i] = int(data[i])
}
return result
}

View File

@@ -1,4 +0,0 @@
#include <stdlib.h>
#include <vips/vips.h>
#define INT_TO_GBOOLEAN(bool) (bool > 0 ? TRUE : FALSE)

View File

@@ -1,98 +0,0 @@
package vips
// #include <glib.h>
import "C"
import (
"log"
)
// LogLevel is the enum controlling logging message verbosity.
type LogLevel int
// The logging verbosity levels classify and filter logging messages.
// From most to least verbose, they are debug, info, message, warning, critical and error.
const (
LogLevelError LogLevel = C.G_LOG_LEVEL_ERROR
LogLevelCritical LogLevel = C.G_LOG_LEVEL_CRITICAL
LogLevelWarning LogLevel = C.G_LOG_LEVEL_WARNING
LogLevelMessage LogLevel = C.G_LOG_LEVEL_MESSAGE
LogLevelInfo LogLevel = C.G_LOG_LEVEL_INFO
LogLevelDebug LogLevel = C.G_LOG_LEVEL_DEBUG
)
// Three global variables which keep state of the current logging handler
// function, desired verbosity for logging and whether defaults have been
// overridden. Set by LoggingSettings()
var (
currentLoggingHandlerFunction LoggingHandlerFunction
currentLoggingVerbosity LogLevel
currentLoggingOverridden bool
)
// govipsLoggingHandler is the private bridge function exported to the C library
// and called by glib and libvips for each logging message. It will call govipsLog
// which in turn will filter based on verbosity and direct the messages to the
// currently chosen LoggingHandlerFunction.
//
//export govipsLoggingHandler
func govipsLoggingHandler(messageDomain *C.char, messageLevel C.int, message *C.char) {
govipsLog(C.GoString(messageDomain), LogLevel(messageLevel), C.GoString(message))
}
// LoggingHandlerFunction is a function which will be called for each log message.
// By default, govips sends logging messages to os.Stderr. If you want to log elsewhere
// such as to a file or to a state variable which you inspect yourself, define a new
// logging handler function and set it via LoggingSettings().
type LoggingHandlerFunction func(messageDomain string, messageLevel LogLevel, message string)
// LoggingSettings sets the logging handler and logging verbosity for govips.
// The handler function is the function which will be called for each log message.
// You can define one yourself to log somewhere else besides the default (stderr).
// Use nil as handler to use standard logging handler.
// Verbosity is the minimum logLevel you want to log. Default is logLevelInfo
// due to backwards compatibility but it's quite verbose for a library.
// Suggest setting it to at least logLevelWarning. Use logLevelDebug for debugging.
func LoggingSettings(handler LoggingHandlerFunction, verbosity LogLevel) {
currentLoggingOverridden = true
govipsLoggingSettings(handler, verbosity)
}
func govipsLoggingSettings(handler LoggingHandlerFunction, verbosity LogLevel) {
if handler == nil {
currentLoggingHandlerFunction = defaultLoggingHandlerFunction
} else {
currentLoggingHandlerFunction = handler
}
currentLoggingVerbosity = verbosity
// TODO turn on debugging in libvips and redirect to handler when setting verbosity to debug
// This way debugging information would go to the same channel as all other logging
}
func defaultLoggingHandlerFunction(messageDomain string, messageLevel LogLevel, message string) {
var messageLevelDescription string
switch messageLevel {
case LogLevelError:
messageLevelDescription = "error"
case LogLevelCritical:
messageLevelDescription = "critical"
case LogLevelWarning:
messageLevelDescription = "warning"
case LogLevelMessage:
messageLevelDescription = "message"
case LogLevelInfo:
messageLevelDescription = "info"
case LogLevelDebug:
messageLevelDescription = "debug"
}
log.Printf("[%v.%v] %v", messageDomain, messageLevelDescription, message)
}
// govipsLog is the default function used to log debug or error messages internally in govips.
// It's used by all govips functionality directly, as well as by glib and libvips via the C bridge.
func govipsLog(messageDomain string, messageLevel LogLevel, message string) {
if messageLevel <= currentLoggingVerbosity {
currentLoggingHandlerFunction(messageDomain, messageLevel, message)
}
}

View File

@@ -1,57 +0,0 @@
package vips
import "math"
// Scalar is the basic scalar measurement of an image's height, width or offset coordinate.
type Scalar struct {
Value float64
Relative bool
}
// ValueOf takes a floating point value and returns a corresponding Scalar struct
func ValueOf(value float64) Scalar {
return Scalar{value, false}
}
// IsZero checkes whether the associated Scalar's value is zero.
func (s *Scalar) IsZero() bool {
return s.Value == 0 && !s.Relative
}
// SetInt sets an integer value for the associated Scalar.
func (s *Scalar) SetInt(value int) {
s.Set(float64(value))
}
// Set sets a float value for the associated Scalar.
func (s *Scalar) Set(value float64) {
s.Value = value
s.Relative = false
}
// SetScale sets a float value for the associated Scalar and makes it relative.
func (s *Scalar) SetScale(f float64) {
s.Value = f
s.Relative = true
}
// Get returns the value of the scalar. Either absolute, or if relative, multiplied by the base given as parameter.
func (s *Scalar) Get(base int) float64 {
if s.Relative {
return s.Value * float64(base)
}
return s.Value
}
// GetRounded returns the value of the associated Scalar, rounded to the nearest integer, if absolute.
// If the Scalar is relative, it will be multiplied by the supplied base parameter.
func (s *Scalar) GetRounded(base int) int {
return roundFloat(s.Get(base))
}
func roundFloat(f float64) int {
if f < 0 {
return int(math.Ceil(f - 0.5))
}
return int(math.Floor(f + 0.5))
}

View File

@@ -1,6 +0,0 @@
#include "morphology.h"
int rank(VipsImage *in, VipsImage **out, int width, int height, int index) {
return vips_rank(in, out, width, height, index, NULL);
}

View File

@@ -1,17 +0,0 @@
package vips
// #include "morphology.h"
import "C"
// https://libvips.github.io/libvips/API/current/libvips-morphology.html#vips-rank
func vipsRank(in *C.VipsImage, width int, height int, index int) (*C.VipsImage, error) {
incOpCounter("rank")
var out *C.VipsImage
err := C.rank(in, &out, C.int(width), C.int(height), C.int(index))
if int(err) != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,6 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-morphology.html
#include <stdlib.h>
#include <vips/vips.h>
int rank(VipsImage *in, VipsImage **out, int width, int height, int index);

View File

@@ -1,61 +0,0 @@
#include "resample.h"
int shrink_image(VipsImage *in, VipsImage **out, double xshrink,
double yshrink) {
return vips_shrink(in, out, xshrink, yshrink, NULL);
}
int reduce_image(VipsImage *in, VipsImage **out, double xshrink,
double yshrink) {
return vips_reduce(in, out, xshrink, yshrink, NULL);
}
int affine_image(VipsImage *in, VipsImage **out, double a, double b, double c,
double d, VipsInterpolate *interpolator) {
return vips_affine(in, out, a, b, c, d, "interpolate", interpolator, NULL);
}
int resize_image(VipsImage *in, VipsImage **out, double scale, gdouble vscale,
int kernel) {
if (vscale > 0) {
return vips_resize(in, out, scale, "vscale", vscale, "kernel", kernel,
NULL);
}
return vips_resize(in, out, scale, "kernel", kernel, NULL);
}
int thumbnail(const char *filename, VipsImage **out,
int width, int height, int crop, int size) {
return vips_thumbnail(filename, out, width, "height", height,
"crop", crop, "size", size, NULL);
}
int thumbnail_image(VipsImage *in, VipsImage **out, int width, int height,
int crop, int size) {
return vips_thumbnail_image(in, out, width, "height", height, "crop", crop,
"size", size, NULL);
}
int thumbnail_buffer_with_option(void *buf, size_t len, VipsImage **out,
int width, int height, int crop, int size,
const char *option_string) {
return vips_thumbnail_buffer(buf, len, out, width, "height", height,
"crop", crop, "size", size,
"option_string", option_string, NULL);
}
int thumbnail_buffer(void *buf, size_t len, VipsImage **out,
int width, int height, int crop, int size) {
return vips_thumbnail_buffer(buf, len, out, width, "height", height,
"crop", crop, "size", size, NULL);
}
int mapim(VipsImage *in, VipsImage **out, VipsImage *index) {
return vips_mapim(in, out, index, NULL);
}
int maplut(VipsImage *in, VipsImage **out, VipsImage *lut) {
return vips_maplut(in, out, lut, NULL);
}

View File

@@ -1,146 +0,0 @@
package vips
// #include "resample.h"
import "C"
import (
"os"
"runtime"
"unsafe"
)
// Kernel represents VipsKernel type
type Kernel int
// Kernel enum
const (
KernelAuto Kernel = -1
KernelNearest Kernel = C.VIPS_KERNEL_NEAREST
KernelLinear Kernel = C.VIPS_KERNEL_LINEAR
KernelCubic Kernel = C.VIPS_KERNEL_CUBIC
KernelLanczos2 Kernel = C.VIPS_KERNEL_LANCZOS2
KernelLanczos3 Kernel = C.VIPS_KERNEL_LANCZOS3
KernelMitchell Kernel = C.VIPS_KERNEL_MITCHELL
)
// Size represents VipsSize type
type Size int
const (
SizeBoth Size = C.VIPS_SIZE_BOTH
SizeUp Size = C.VIPS_SIZE_UP
SizeDown Size = C.VIPS_SIZE_DOWN
SizeForce Size = C.VIPS_SIZE_FORCE
SizeLast Size = C.VIPS_SIZE_LAST
)
// https://libvips.github.io/libvips/API/current/libvips-resample.html#vips-resize
func vipsResizeWithVScale(in *C.VipsImage, hscale, vscale float64, kernel Kernel) (*C.VipsImage, error) {
incOpCounter("resize")
var out *C.VipsImage
// libvips recommends Lanczos3 as the default kernel
if kernel == KernelAuto {
kernel = KernelLanczos3
}
if err := C.resize_image(in, &out, C.double(hscale), C.double(vscale), C.int(kernel)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
func vipsThumbnail(in *C.VipsImage, width, height int, crop Interesting, size Size) (*C.VipsImage, error) {
incOpCounter("thumbnail")
var out *C.VipsImage
if err := C.thumbnail_image(in, &out, C.int(width), C.int(height), C.int(crop), C.int(size)); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://www.libvips.org/API/current/libvips-resample.html#vips-thumbnail
func vipsThumbnailFromFile(filename string, width, height int, crop Interesting, size Size, params *ImportParams) (*C.VipsImage, ImageType, error) {
var out *C.VipsImage
filenameOption := filename
if params != nil {
filenameOption += "[" + params.OptionString() + "]"
}
cFileName := C.CString(filenameOption)
defer freeCString(cFileName)
if err := C.thumbnail(cFileName, &out, C.int(width), C.int(height), C.int(crop), C.int(size)); err != 0 {
err := handleImageError(out)
if src, err2 := os.ReadFile(filename); err2 == nil {
if isBMP(src) {
if src2, err3 := bmpToPNG(src); err3 == nil {
return vipsThumbnailFromBuffer(src2, width, height, crop, size, params)
}
}
}
return nil, ImageTypeUnknown, err
}
imageType := vipsDetermineImageTypeFromMetaLoader(out)
return out, imageType, nil
}
// https://www.libvips.org/API/current/libvips-resample.html#vips-thumbnail-buffer
func vipsThumbnailFromBuffer(buf []byte, width, height int, crop Interesting, size Size, params *ImportParams) (*C.VipsImage, ImageType, error) {
src := buf
// Reference src here so it's not garbage collected during image initialization.
defer runtime.KeepAlive(src)
var out *C.VipsImage
var err C.int
if params == nil {
err = C.thumbnail_buffer(unsafe.Pointer(&src[0]), C.size_t(len(src)), &out, C.int(width), C.int(height), C.int(crop), C.int(size))
} else {
cOptionString := C.CString(params.OptionString())
defer freeCString(cOptionString)
err = C.thumbnail_buffer_with_option(unsafe.Pointer(&src[0]), C.size_t(len(src)), &out, C.int(width), C.int(height), C.int(crop), C.int(size), cOptionString)
}
if err != 0 {
err := handleImageError(out)
if isBMP(src) {
if src2, err2 := bmpToPNG(src); err2 == nil {
return vipsThumbnailFromBuffer(src2, width, height, crop, size, params)
}
}
return nil, ImageTypeUnknown, err
}
imageType := vipsDetermineImageTypeFromMetaLoader(out)
return out, imageType, nil
}
// https://libvips.github.io/libvips/API/current/libvips-resample.html#vips-mapim
func vipsMapim(in *C.VipsImage, index *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("mapim")
var out *C.VipsImage
if err := C.mapim(in, &out, index); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}
// https://libvips.github.io/libvips/API/current/libvips-histogram.html#vips-maplut
func vipsMaplut(in *C.VipsImage, lut *C.VipsImage) (*C.VipsImage, error) {
incOpCounter("maplut")
var out *C.VipsImage
if err := C.maplut(in, &out, lut); err != 0 {
return nil, handleImageError(out)
}
return out, nil
}

View File

@@ -1,24 +0,0 @@
// https://libvips.github.io/libvips/API/current/libvips-resample.html
#include <stdlib.h>
#include <vips/vips.h>
int shrink_image(VipsImage *in, VipsImage **out, double xshrink,
double yshrink);
int reduce_image(VipsImage *in, VipsImage **out, double xshrink,
double yshrink);
int affine_image(VipsImage *in, VipsImage **out, double a, double b, double c,
double d, VipsInterpolate *interpolator);
int resize_image(VipsImage *in, VipsImage **out, double scale, gdouble vscale,
int kernel);
int thumbnail(const char *filename, VipsImage **out, int width, int height,
int crop, int size);
int thumbnail_image(VipsImage *in, VipsImage **out, int width, int height,
int crop, int size);
int thumbnail_buffer(void *buf, size_t len, VipsImage **out, int width, int height,
int crop, int size);
int thumbnail_buffer_with_option(void *buf, size_t len, VipsImage **out,
int width, int height, int crop, int size,
const char *option_string);
int mapim(VipsImage *in, VipsImage **out, VipsImage *index);
int maplut(VipsImage *in, VipsImage **out, VipsImage *lut);

View File

@@ -1,56 +0,0 @@
package vips
import "sync"
// RuntimeStats is a data structure to house a map of govips operation counts
type RuntimeStats struct {
OperationCounts map[string]int64
}
var (
operationCounter chan string
runtimeStats *RuntimeStats
statLock sync.RWMutex
)
func incOpCounter(op string) {
if operationCounter != nil {
operationCounter <- op
}
}
func collectStats() chan struct{} {
operationCounter = make(chan string, 100)
done := make(chan struct{})
exit := false
go func() {
for !exit {
select {
case op := <-operationCounter:
statLock.Lock()
runtimeStats.OperationCounts[op] = runtimeStats.OperationCounts[op] + 1
statLock.Unlock()
case <-done:
exit = true
break
}
}
}()
return done
}
// ReadRuntimeStats returns operation counts for govips
func ReadRuntimeStats(stats *RuntimeStats) {
statLock.RLock()
defer statLock.RUnlock()
stats.OperationCounts = make(map[string]int64)
for k, v := range runtimeStats.OperationCounts {
stats.OperationCounts[k] = v
}
}
func init() {
runtimeStats = &RuntimeStats{
OperationCounts: make(map[string]int64),
}
}

View File

@@ -1,6 +0,0 @@
package vips
// relative to "/vips/.."
const (
resources = "../resources/"
)

View File

@@ -3,11 +3,14 @@
// license that can be found in the LICENSE file.
// Package curve25519 provides an implementation of the X25519 function, which
// performs scalar multiplication on the elliptic curve known as Curve25519.
// See RFC 7748.
// performs scalar multiplication on the elliptic curve known as Curve25519
// according to [RFC 7748].
//
// This package is a wrapper for the X25519 implementation
// in the crypto/ecdh package.
// The curve25519 package is a wrapper for the X25519 implementation in the
// crypto/ecdh package. It is [frozen] and is not accepting new features.
//
// [RFC 7748]: https://datatracker.ietf.org/doc/html/rfc7748
// [frozen]: https://go.dev/wiki/Frozen
package curve25519
import "crypto/ecdh"

View File

@@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) {
return keys, nil
case *failureAgentMsg:
return nil, errors.New("agent: failed to list keys")
default:
return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg)
}
panic("unreachable")
}
// Sign has the agent sign the data using a protocol 2 key as defined
@@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl
return &sig, nil
case *failureAgentMsg:
return nil, errors.New("agent: failed to sign challenge")
default:
return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg)
}
panic("unreachable")
}
// unmarshal parses an agent message in packet, returning the parsed

View File

@@ -8,6 +8,7 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/fips140"
"crypto/rc4"
"crypto/subtle"
"encoding/binary"
@@ -15,6 +16,7 @@ import (
"fmt"
"hash"
"io"
"slices"
"golang.org/x/crypto/chacha20"
"golang.org/x/crypto/internal/poly1305"
@@ -93,41 +95,41 @@ func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream,
}
// cipherModes documents properties of supported ciphers. Ciphers not included
// are not supported and will not be negotiated, even if explicitly requested in
// ClientConfig.Crypto.Ciphers.
var cipherModes = map[string]*cipherMode{
// Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms
// are defined in the order specified in the RFC.
CipherAES128CTR: {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
CipherAES192CTR: {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
CipherAES256CTR: {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
// are not supported and will not be negotiated, even if explicitly configured.
// When FIPS mode is enabled, only FIPS-approved algorithms are included.
var cipherModes = map[string]*cipherMode{}
// Ciphers from RFC 4345, which introduces security-improved arcfour ciphers.
// They are defined in the order specified in the RFC.
InsecureCipherRC4128: {16, 0, streamCipherMode(1536, newRC4)},
InsecureCipherRC4256: {32, 0, streamCipherMode(1536, newRC4)},
func init() {
cipherModes[CipherAES128CTR] = &cipherMode{16, aes.BlockSize, streamCipherMode(0, newAESCTR)}
cipherModes[CipherAES192CTR] = &cipherMode{24, aes.BlockSize, streamCipherMode(0, newAESCTR)}
cipherModes[CipherAES256CTR] = &cipherMode{32, aes.BlockSize, streamCipherMode(0, newAESCTR)}
// Use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode,
// we'll wire it up to NewGCMForSSH in Go 1.26.
//
// For now it means we'll work with fips140=on but not fips140=only.
cipherModes[CipherAES128GCM] = &cipherMode{16, 12, newGCMCipher}
cipherModes[CipherAES256GCM] = &cipherMode{32, 12, newGCMCipher}
// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
// RC4) has problems with weak keys, and should be used with caution."
// RFC 4345 introduces improved versions of Arcfour.
InsecureCipherRC4: {16, 0, streamCipherMode(0, newRC4)},
// AEAD ciphers
CipherAES128GCM: {16, 12, newGCMCipher},
CipherAES256GCM: {32, 12, newGCMCipher},
CipherChaCha20Poly1305: {64, 0, newChaCha20Cipher},
if fips140.Enabled() {
defaultCiphers = slices.DeleteFunc(defaultCiphers, func(algo string) bool {
_, ok := cipherModes[algo]
return !ok
})
return
}
cipherModes[CipherChaCha20Poly1305] = &cipherMode{64, 0, newChaCha20Cipher}
// Insecure ciphers not included in the default configuration.
cipherModes[InsecureCipherRC4128] = &cipherMode{16, 0, streamCipherMode(1536, newRC4)}
cipherModes[InsecureCipherRC4256] = &cipherMode{32, 0, streamCipherMode(1536, newRC4)}
cipherModes[InsecureCipherRC4] = &cipherMode{16, 0, streamCipherMode(0, newRC4)}
// CBC mode is insecure and so is not included in the default config.
// (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely
// needed, it's possible to specify a custom Config to enable it.
// You should expect that an active attacker can recover plaintext if
// you do.
InsecureCipherAES128CBC: {16, aes.BlockSize, newAESCBCCipher},
// 3des-cbc is insecure and is not included in the default
// config.
InsecureCipherTripleDESCBC: {24, des.BlockSize, newTripleDESCBCCipher},
cipherModes[InsecureCipherAES128CBC] = &cipherMode{16, aes.BlockSize, newAESCBCCipher}
cipherModes[InsecureCipherTripleDESCBC] = &cipherMode{24, des.BlockSize, newTripleDESCBCCipher}
}
// prefixLen is the length of the packet prefix that contains the packet length

View File

@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
"slices"
"strings"
)
@@ -83,7 +84,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
// success
return nil
} else if ok == authFailure {
if m := auth.method(); !contains(tried, m) {
if m := auth.method(); !slices.Contains(tried, m) {
tried = append(tried, m)
}
}
@@ -97,7 +98,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
findNext:
for _, a := range config.Auth {
candidateMethod := a.method()
if contains(tried, candidateMethod) {
if slices.Contains(tried, candidateMethod) {
continue
}
for _, meth := range methods {
@@ -117,15 +118,6 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried)
}
func contains(list []string, e string) bool {
for _, s := range list {
if s == e {
return true
}
}
return false
}
// An AuthMethod represents an instance of an RFC 4252 authentication method.
type AuthMethod interface {
// auth authenticates user over transport t.
@@ -255,7 +247,7 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiA
// Fallback to use if there is no "server-sig-algs" extension or a
// common algorithm cannot be found. We use the public key format if the
// MultiAlgorithmSigner supports it, otherwise we return an error.
if !contains(as.Algorithms(), underlyingAlgo(keyFormat)) {
if !slices.Contains(as.Algorithms(), underlyingAlgo(keyFormat)) {
return "", fmt.Errorf("ssh: no common public key signature algorithm, server only supports %q for key type %q, signer only supports %v",
underlyingAlgo(keyFormat), keyFormat, as.Algorithms())
}
@@ -284,7 +276,7 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiA
// Filter algorithms based on those supported by MultiAlgorithmSigner.
var keyAlgos []string
for _, algo := range algorithmsForKeyFormat(keyFormat) {
if contains(as.Algorithms(), underlyingAlgo(algo)) {
if slices.Contains(as.Algorithms(), underlyingAlgo(algo)) {
keyAlgos = append(keyAlgos, algo)
}
}
@@ -334,7 +326,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
// the key try to use the obtained algorithm as if "server-sig-algs" had
// not been implemented if supported from the algorithm signer.
if !ok && idx < origSignersLen && isRSACert(algo) && algo != CertAlgoRSAv01 {
if contains(as.Algorithms(), KeyAlgoRSA) {
if slices.Contains(as.Algorithms(), KeyAlgoRSA) {
// We retry using the compat algorithm after all signers have
// been tried normally.
signers = append(signers, &multiAlgorithmSigner{
@@ -385,7 +377,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
// contain the "publickey" method, do not attempt to authenticate with any
// other keys. According to RFC 4252 Section 7, the latter can occur when
// additional authentication methods are required.
if success == authSuccess || !contains(methods, cb.method()) {
if success == authSuccess || !slices.Contains(methods, cb.method()) {
return success, methods, err
}
}
@@ -434,7 +426,7 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
// servers send the key type instead. OpenSSH allows any algorithm
// that matches the public key, so we do the same.
// https://github.com/openssh/openssh-portable/blob/86bdd385/sshconnect2.c#L709
if !contains(algorithmsForKeyFormat(key.Type()), msg.Algo) {
if !slices.Contains(algorithmsForKeyFormat(key.Type()), msg.Algo) {
return false, nil
}
if !bytes.Equal(msg.PubKey, pubKey) {

View File

@@ -6,6 +6,7 @@ package ssh
import (
"crypto"
"crypto/fips140"
"crypto/rand"
"fmt"
"io"
@@ -256,6 +257,40 @@ type Algorithms struct {
PublicKeyAuths []string
}
func init() {
if fips140.Enabled() {
defaultHostKeyAlgos = slices.DeleteFunc(defaultHostKeyAlgos, func(algo string) bool {
_, err := hashFunc(underlyingAlgo(algo))
return err != nil
})
defaultPubKeyAuthAlgos = slices.DeleteFunc(defaultPubKeyAuthAlgos, func(algo string) bool {
_, err := hashFunc(underlyingAlgo(algo))
return err != nil
})
}
}
func hashFunc(format string) (crypto.Hash, error) {
switch format {
case KeyAlgoRSASHA256, KeyAlgoECDSA256, KeyAlgoSKED25519, KeyAlgoSKECDSA256:
return crypto.SHA256, nil
case KeyAlgoECDSA384:
return crypto.SHA384, nil
case KeyAlgoRSASHA512, KeyAlgoECDSA521:
return crypto.SHA512, nil
case KeyAlgoED25519:
// KeyAlgoED25519 doesn't pre-hash.
return 0, nil
case KeyAlgoRSA, InsecureKeyAlgoDSA:
if fips140.Enabled() {
return 0, fmt.Errorf("ssh: hash algorithm for format %q not allowed in FIPS 140 mode", format)
}
return crypto.SHA1, nil
default:
return 0, fmt.Errorf("ssh: hash algorithm for format %q not mapped", format)
}
}
// SupportedAlgorithms returns algorithms currently implemented by this package,
// excluding those with security issues, which are returned by
// InsecureAlgorithms. The algorithms listed here are in preference order.
@@ -283,21 +318,6 @@ func InsecureAlgorithms() Algorithms {
var supportedCompressions = []string{compressionNone}
// hashFuncs keeps the mapping of supported signature algorithms to their
// respective hashes needed for signing and verification.
var hashFuncs = map[string]crypto.Hash{
KeyAlgoRSA: crypto.SHA1,
KeyAlgoRSASHA256: crypto.SHA256,
KeyAlgoRSASHA512: crypto.SHA512,
InsecureKeyAlgoDSA: crypto.SHA1,
KeyAlgoECDSA256: crypto.SHA256,
KeyAlgoECDSA384: crypto.SHA384,
KeyAlgoECDSA521: crypto.SHA512,
// KeyAlgoED25519 doesn't pre-hash.
KeyAlgoSKECDSA256: crypto.SHA256,
KeyAlgoSKED25519: crypto.SHA256,
}
// algorithmsForKeyFormat returns the supported signature algorithms for a given
// public key format (PublicKey.Type), in order of preference. See RFC 8332,
// Section 2. See also the note in sendKexInit on backwards compatibility.
@@ -312,11 +332,40 @@ func algorithmsForKeyFormat(keyFormat string) []string {
}
}
// keyFormatForAlgorithm returns the key format corresponding to the given
// signature algorithm. It returns an empty string if the signature algorithm is
// invalid or unsupported.
func keyFormatForAlgorithm(sigAlgo string) string {
switch sigAlgo {
case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512:
return KeyAlgoRSA
case CertAlgoRSAv01, CertAlgoRSASHA256v01, CertAlgoRSASHA512v01:
return CertAlgoRSAv01
case KeyAlgoED25519,
KeyAlgoSKED25519,
KeyAlgoSKECDSA256,
KeyAlgoECDSA256,
KeyAlgoECDSA384,
KeyAlgoECDSA521,
InsecureKeyAlgoDSA,
InsecureCertAlgoDSAv01,
CertAlgoECDSA256v01,
CertAlgoECDSA384v01,
CertAlgoECDSA521v01,
CertAlgoSKECDSA256v01,
CertAlgoED25519v01,
CertAlgoSKED25519v01:
return sigAlgo
default:
return ""
}
}
// isRSA returns whether algo is a supported RSA algorithm, including certificate
// algorithms.
func isRSA(algo string) bool {
algos := algorithmsForKeyFormat(KeyAlgoRSA)
return contains(algos, underlyingAlgo(algo))
return slices.Contains(algos, underlyingAlgo(algo))
}
func isRSACert(algo string) bool {
@@ -515,7 +564,7 @@ func (c *Config) SetDefaults() {
if kexAlgoMap[k] != nil {
// Ignore the KEX if we have no kexAlgoMap definition.
kexs = append(kexs, k)
if k == KeyExchangeCurve25519 && !contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) {
if k == KeyExchangeCurve25519 && !slices.Contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) {
kexs = append(kexs, keyExchangeCurve25519LibSSH)
}
}

View File

@@ -17,8 +17,18 @@ References:
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
[SSH-CERTS]: https://datatracker.ietf.org/doc/html/draft-miller-ssh-cert-01
[FIPS 140-3 mode]: https://go.dev/doc/security/fips140
This package does not fall under the stability promise of the Go language itself,
so its API may be changed when pressing needs arise.
# FIPS 140-3 mode
When the program is in [FIPS 140-3 mode], this package behaves as if only SP
800-140C and SP 800-140D approved cipher suites, signature algorithms,
certificate public key types and sizes, and key exchange and derivation
algorithms were implemented. Others are silently ignored and not negotiated, or
rejected. This set may depend on the algorithms supported by the FIPS 140-3 Go
Cryptographic Module selected with GOFIPS140, and may change across Go versions.
*/
package ssh

View File

@@ -10,6 +10,7 @@ import (
"io"
"log"
"net"
"slices"
"strings"
"sync"
)
@@ -527,7 +528,7 @@ func (t *handshakeTransport) sendKexInit() error {
switch s := k.(type) {
case MultiAlgorithmSigner:
for _, algo := range algorithmsForKeyFormat(keyFormat) {
if contains(s.Algorithms(), underlyingAlgo(algo)) {
if slices.Contains(s.Algorithms(), underlyingAlgo(algo)) {
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo)
}
}
@@ -679,7 +680,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
return err
}
if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
if t.sessionID == nil && ((isClient && slices.Contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && slices.Contains(clientInit.KexAlgos, kexStrictClient))) {
t.strictMode = true
if err := t.conn.setStrictMode(); err != nil {
return err
@@ -736,7 +737,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
// On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO
// message with the server-sig-algs extension if the client supports it. See
// RFC 8308, Sections 2.4 and 3.1, and [PROTOCOL], Section 1.9.
if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {
if !isClient && firstKeyExchange && slices.Contains(clientInit.KexAlgos, "ext-info-c") {
supportedPubKeyAuthAlgosList := strings.Join(t.publicKeyAuthAlgorithms, ",")
extInfo := &extInfoMsg{
NumExtensions: 2,
@@ -790,7 +791,7 @@ func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, a
func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
for _, k := range hostKeys {
if s, ok := k.(MultiAlgorithmSigner); ok {
if !contains(s.Algorithms(), underlyingAlgo(algo)) {
if !slices.Contains(s.Algorithms(), underlyingAlgo(algo)) {
continue
}
}

View File

@@ -8,12 +8,14 @@ import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/fips140"
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"io"
"math/big"
"slices"
"golang.org/x/crypto/curve25519"
)
@@ -395,9 +397,27 @@ func ecHash(curve elliptic.Curve) crypto.Hash {
return crypto.SHA512
}
// kexAlgoMap defines the supported KEXs. KEXs not included are not supported
// and will not be negotiated, even if explicitly configured. When FIPS mode is
// enabled, only FIPS-approved algorithms are included.
var kexAlgoMap = map[string]kexAlgorithm{}
func init() {
// mlkem768x25519-sha256 we'll work with fips140=on but not fips140=only
// until Go 1.26.
kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
kexAlgoMap[KeyExchangeECDHP521] = &ecdh{elliptic.P521()}
kexAlgoMap[KeyExchangeECDHP384] = &ecdh{elliptic.P384()}
kexAlgoMap[KeyExchangeECDHP256] = &ecdh{elliptic.P256()}
if fips140.Enabled() {
defaultKexAlgos = slices.DeleteFunc(defaultKexAlgos, func(algo string) bool {
_, ok := kexAlgoMap[algo]
return !ok
})
return
}
p, _ := new(big.Int).SetString(oakleyGroup2, 16)
kexAlgoMap[InsecureKeyExchangeDH1SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2),
@@ -431,14 +451,10 @@ func init() {
hashFunc: crypto.SHA512,
}
kexAlgoMap[KeyExchangeECDHP521] = &ecdh{elliptic.P521()}
kexAlgoMap[KeyExchangeECDHP384] = &ecdh{elliptic.P384()}
kexAlgoMap[KeyExchangeECDHP256] = &ecdh{elliptic.P256()}
kexAlgoMap[KeyExchangeCurve25519] = &curve25519sha256{}
kexAlgoMap[keyExchangeCurve25519LibSSH] = &curve25519sha256{}
kexAlgoMap[InsecureKeyExchangeDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[KeyExchangeDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
}
// curve25519sha256 implements the curve25519-sha256 (formerly known as

View File

@@ -27,6 +27,7 @@ import (
"fmt"
"io"
"math/big"
"slices"
"strings"
"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
@@ -89,6 +90,11 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
}
return cert, nil, nil
}
if keyFormat := keyFormatForAlgorithm(algo); keyFormat != "" {
return nil, nil, fmt.Errorf("ssh: signature algorithm %q isn't a key format; key is malformed and should be re-encoded with type %q",
algo, keyFormat)
}
return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
}
@@ -191,9 +197,10 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey
return "", nil, nil, "", nil, io.EOF
}
// ParseAuthorizedKey parses a public key from an authorized_keys
// file used in OpenSSH according to the sshd(8) manual page.
// ParseAuthorizedKey parses a public key from an authorized_keys file used in
// OpenSSH according to the sshd(8) manual page. Invalid lines are ignored.
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
var lastErr error
for len(in) > 0 {
end := bytes.IndexByte(in, '\n')
if end != -1 {
@@ -222,6 +229,8 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str
if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
return out, comment, options, rest, nil
} else {
lastErr = err
}
// No key type recognised. Maybe there's an options field at
@@ -264,12 +273,18 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str
if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
options = candidateOptions
return out, comment, options, rest, nil
} else {
lastErr = err
}
in = rest
continue
}
if lastErr != nil {
return nil, "", nil, nil, fmt.Errorf("ssh: no key found; last parsing error for ignored line: %w", lastErr)
}
return nil, "", nil, nil, errors.New("ssh: no key found")
}
@@ -395,11 +410,11 @@ func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string) (Multi
}
for _, algo := range algorithms {
if !contains(supportedAlgos, algo) {
if !slices.Contains(supportedAlgos, algo) {
return nil, fmt.Errorf("ssh: algorithm %q is not supported for key type %q",
algo, signer.PublicKey().Type())
}
if !contains(signerAlgos, algo) {
if !slices.Contains(signerAlgos, algo) {
return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", algo)
}
}
@@ -486,10 +501,13 @@ func (r *rsaPublicKey) Marshal() []byte {
func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
supportedAlgos := algorithmsForKeyFormat(r.Type())
if !contains(supportedAlgos, sig.Format) {
if !slices.Contains(supportedAlgos, sig.Format) {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
}
hash := hashFuncs[sig.Format]
hash, err := hashFunc(sig.Format)
if err != nil {
return err
}
h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -606,7 +624,11 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
h := hashFuncs[sig.Format].New()
hash, err := hashFunc(sig.Format)
if err != nil {
return err
}
h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -651,7 +673,11 @@ func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
}
h := hashFuncs[k.PublicKey().Type()].New()
hash, err := hashFunc(k.PublicKey().Type())
if err != nil {
return nil, err
}
h := hash.New()
h.Write(data)
digest := h.Sum(nil)
r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
@@ -801,8 +827,11 @@ func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
h := hashFuncs[sig.Format].New()
hash, err := hashFunc(sig.Format)
if err != nil {
return err
}
h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -905,8 +934,11 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
h := hashFuncs[sig.Format].New()
hash, err := hashFunc(sig.Format)
if err != nil {
return err
}
h := hash.New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
@@ -1009,7 +1041,11 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
return fmt.Errorf("invalid size %d for Ed25519 public key", l)
}
h := hashFuncs[sig.Format].New()
hash, err := hashFunc(sig.Format)
if err != nil {
return err
}
h := hash.New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
@@ -1112,11 +1148,14 @@ func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm
algorithm = s.pubKey.Type()
}
if !contains(s.Algorithms(), algorithm) {
if !slices.Contains(s.Algorithms(), algorithm) {
return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())
}
hashFunc := hashFuncs[algorithm]
hashFunc, err := hashFunc(algorithm)
if err != nil {
return nil, err
}
var digest []byte
if hashFunc != 0 {
h := hashFunc.New()

View File

@@ -7,11 +7,13 @@ package ssh
// Message authentication support
import (
"crypto/fips140"
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
"slices"
)
type macMode struct {
@@ -46,23 +48,37 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{
HMACSHA512ETM: {64, true, func(key []byte) hash.Hash {
// macModes defines the supported MACs. MACs not included are not supported
// and will not be negotiated, even if explicitly configured. When FIPS mode is
// enabled, only FIPS-approved algorithms are included.
var macModes = map[string]*macMode{}
func init() {
macModes[HMACSHA512ETM] = &macMode{64, true, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key)
}},
HMACSHA256ETM: {32, true, func(key []byte) hash.Hash {
}}
macModes[HMACSHA256ETM] = &macMode{32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
HMACSHA512: {64, false, func(key []byte) hash.Hash {
}}
macModes[HMACSHA512] = &macMode{64, false, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key)
}},
HMACSHA256: {32, false, func(key []byte) hash.Hash {
}}
macModes[HMACSHA256] = &macMode{32, false, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
HMACSHA1: {20, false, func(key []byte) hash.Hash {
}}
if fips140.Enabled() {
defaultMACs = slices.DeleteFunc(defaultMACs, func(algo string) bool {
_, ok := macModes[algo]
return !ok
})
return
}
macModes[HMACSHA1] = &macMode{20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key)
}},
InsecureHMACSHA196: {20, false, func(key []byte) hash.Hash {
}}
macModes[InsecureHMACSHA196] = &macMode{20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)}
}},
}}
}

View File

@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"net"
"slices"
"strings"
)
@@ -43,6 +44,9 @@ type Permissions struct {
// pass data from the authentication callbacks to the server
// application layer.
Extensions map[string]string
// ExtraData allows to store user defined data.
ExtraData map[any]any
}
type GSSAPIWithMICConfig struct {
@@ -126,6 +130,21 @@ type ServerConfig struct {
// Permissions.Extensions entry.
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
// VerifiedPublicKeyCallback, if non-nil, is called after a client
// successfully confirms having control over a key that was previously
// approved by PublicKeyCallback. The permissions object passed to the
// callback is the one returned by PublicKeyCallback for the given public
// key and its ownership is transferred to the callback. The returned
// Permissions object can be the same object, optionally modified, or a
// completely new object. If VerifiedPublicKeyCallback is non-nil,
// PublicKeyCallback is not allowed to return a PartialSuccessError, which
// can instead be returned by VerifiedPublicKeyCallback.
//
// VerifiedPublicKeyCallback does not affect which authentication methods
// are included in the list of methods that can be attempted by the client.
VerifiedPublicKeyCallback func(conn ConnMetadata, key PublicKey, permissions *Permissions,
signatureAlgorithm string) (*Permissions, error)
// KeyboardInteractiveCallback, if non-nil, is called when
// keyboard-interactive authentication is selected (RFC
// 4256). The client object's Challenge function should be
@@ -246,7 +265,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
fullConf.PublicKeyAuthAlgorithms = defaultPubKeyAuthAlgos
} else {
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
if !contains(SupportedAlgorithms().PublicKeyAuths, algo) && !contains(InsecureAlgorithms().PublicKeyAuths, algo) {
if !slices.Contains(SupportedAlgorithms().PublicKeyAuths, algo) && !slices.Contains(InsecureAlgorithms().PublicKeyAuths, algo) {
c.Close()
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
}
@@ -631,7 +650,7 @@ userAuthLoop:
return nil, parseError(msgUserAuthRequest)
}
algo := string(algoBytes)
if !contains(config.PublicKeyAuthAlgorithms, underlyingAlgo(algo)) {
if !slices.Contains(config.PublicKeyAuthAlgorithms, underlyingAlgo(algo)) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
break
}
@@ -652,6 +671,9 @@ userAuthLoop:
candidate.pubKeyData = pubKeyData
candidate.perms, candidate.result = authConfig.PublicKeyCallback(s, pubKey)
_, isPartialSuccessError := candidate.result.(*PartialSuccessError)
if isPartialSuccessError && config.VerifiedPublicKeyCallback != nil {
return nil, errors.New("ssh: invalid library usage: PublicKeyCallback must not return partial success when VerifiedPublicKeyCallback is defined")
}
if (candidate.result == nil || isPartialSuccessError) &&
candidate.perms != nil &&
@@ -695,7 +717,7 @@ userAuthLoop:
// ssh-rsa-cert-v01@openssh.com algorithm with ssh-rsa public
// key type. The algorithm and public key type must be
// consistent: both must be certificate algorithms, or neither.
if !contains(algorithmsForKeyFormat(pubKey.Type()), algo) {
if !slices.Contains(algorithmsForKeyFormat(pubKey.Type()), algo) {
authErr = fmt.Errorf("ssh: public key type %q not compatible with selected algorithm %q",
pubKey.Type(), algo)
break
@@ -705,7 +727,7 @@ userAuthLoop:
// algorithm name that corresponds to algo with
// sig.Format. This is usually the same, but
// for certs, the names differ.
if !contains(config.PublicKeyAuthAlgorithms, sig.Format) {
if !slices.Contains(config.PublicKeyAuthAlgorithms, sig.Format) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
break
}
@@ -722,6 +744,12 @@ userAuthLoop:
authErr = candidate.result
perms = candidate.perms
if authErr == nil && config.VerifiedPublicKeyCallback != nil {
// Only call VerifiedPublicKeyCallback after the key has been accepted
// and successfully verified. If authErr is non-nil, the key is not
// considered verified and the callback must not run.
perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo)
}
}
case "gssapi-with-mic":
if authConfig.GSSAPIWithMICConfig == nil {

View File

@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"log"
)
@@ -254,6 +255,9 @@ var (
// (to setup server->client keys) or clientKeys (for client->server keys).
func newPacketCipher(d direction, algs DirectionAlgorithms, kex *kexResult) (packetCipher, error) {
cipherMode := cipherModes[algs.Cipher]
if cipherMode == nil {
return nil, fmt.Errorf("ssh: unsupported cipher %v", algs.Cipher)
}
iv := make([]byte, cipherMode.ivSize)
key := make([]byte, cipherMode.keySize)

27
vendor/golang.org/x/image/LICENSE generated vendored
View File

@@ -1,27 +0,0 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
vendor/golang.org/x/image/PATENTS generated vendored
View File

@@ -1,22 +0,0 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

View File

@@ -1,253 +0,0 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bmp implements a BMP image decoder and encoder.
//
// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html.
package bmp // import "golang.org/x/image/bmp"
import (
"errors"
"image"
"image/color"
"io"
)
// ErrUnsupported means that the input BMP image uses a valid but unsupported
// feature.
var ErrUnsupported = errors.New("bmp: unsupported BMP image")
func readUint16(b []byte) uint16 {
return uint16(b[0]) | uint16(b[1])<<8
}
func readUint32(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
// decodePaletted reads an 8 bit-per-pixel BMP image from r.
// If topDown is false, the image rows will be read bottom-up.
func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
if c.Width == 0 || c.Height == 0 {
return paletted, nil
}
var tmp [4]byte
y0, y1, yDelta := c.Height-1, -1, -1
if topDown {
y0, y1, yDelta = 0, c.Height, +1
}
for y := y0; y != y1; y += yDelta {
p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
if _, err := io.ReadFull(r, p); err != nil {
return nil, err
}
// Each row is 4-byte aligned.
if c.Width%4 != 0 {
_, err := io.ReadFull(r, tmp[:4-c.Width%4])
if err != nil {
return nil, err
}
}
}
return paletted, nil
}
// decodeRGB reads a 24 bit-per-pixel BMP image from r.
// If topDown is false, the image rows will be read bottom-up.
func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
if c.Width == 0 || c.Height == 0 {
return rgba, nil
}
// There are 3 bytes per pixel, and each row is 4-byte aligned.
b := make([]byte, (3*c.Width+3)&^3)
y0, y1, yDelta := c.Height-1, -1, -1
if topDown {
y0, y1, yDelta = 0, c.Height, +1
}
for y := y0; y != y1; y += yDelta {
if _, err := io.ReadFull(r, b); err != nil {
return nil, err
}
p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
// BMP images are stored in BGR order rather than RGB order.
p[i+0] = b[j+2]
p[i+1] = b[j+1]
p[i+2] = b[j+0]
p[i+3] = 0xFF
}
}
return rgba, nil
}
// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
// If topDown is false, the image rows will be read bottom-up.
func decodeNRGBA(r io.Reader, c image.Config, topDown, allowAlpha bool) (image.Image, error) {
rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
if c.Width == 0 || c.Height == 0 {
return rgba, nil
}
y0, y1, yDelta := c.Height-1, -1, -1
if topDown {
y0, y1, yDelta = 0, c.Height, +1
}
for y := y0; y != y1; y += yDelta {
p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
if _, err := io.ReadFull(r, p); err != nil {
return nil, err
}
for i := 0; i < len(p); i += 4 {
// BMP images are stored in BGRA order rather than RGBA order.
p[i+0], p[i+2] = p[i+2], p[i+0]
if !allowAlpha {
p[i+3] = 0xFF
}
}
}
return rgba, nil
}
// Decode reads a BMP image from r and returns it as an image.Image.
// Limitation: The file must be 8, 24 or 32 bits per pixel.
func Decode(r io.Reader) (image.Image, error) {
c, bpp, topDown, allowAlpha, err := decodeConfig(r)
if err != nil {
return nil, err
}
switch bpp {
case 8:
return decodePaletted(r, c, topDown)
case 24:
return decodeRGB(r, c, topDown)
case 32:
return decodeNRGBA(r, c, topDown, allowAlpha)
}
panic("unreachable")
}
// DecodeConfig returns the color model and dimensions of a BMP image without
// decoding the entire image.
// Limitation: The file must be 8, 24 or 32 bits per pixel.
func DecodeConfig(r io.Reader) (image.Config, error) {
config, _, _, _, err := decodeConfig(r)
return config, err
}
func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, allowAlpha bool, err error) {
// We only support those BMP images with one of the following DIB headers:
// - BITMAPINFOHEADER (40 bytes)
// - BITMAPV4HEADER (108 bytes)
// - BITMAPV5HEADER (124 bytes)
const (
fileHeaderLen = 14
infoHeaderLen = 40
v4InfoHeaderLen = 108
v5InfoHeaderLen = 124
)
var b [1024]byte
if _, err := io.ReadFull(r, b[:fileHeaderLen+4]); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return image.Config{}, 0, false, false, err
}
if string(b[:2]) != "BM" {
return image.Config{}, 0, false, false, errors.New("bmp: invalid format")
}
offset := readUint32(b[10:14])
infoLen := readUint32(b[14:18])
if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen {
return image.Config{}, 0, false, false, ErrUnsupported
}
if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return image.Config{}, 0, false, false, err
}
width := int(int32(readUint32(b[18:22])))
height := int(int32(readUint32(b[22:26])))
if height < 0 {
height, topDown = -height, true
}
if width < 0 || height < 0 {
return image.Config{}, 0, false, false, ErrUnsupported
}
// We only support 1 plane and 8, 24 or 32 bits per pixel and no
// compression.
planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
// if compression is set to BI_BITFIELDS, but the bitmask is set to the default bitmask
// that would be used if compression was set to 0, we can continue as if compression was 0
if compression == 3 && infoLen > infoHeaderLen &&
readUint32(b[54:58]) == 0xff0000 && readUint32(b[58:62]) == 0xff00 &&
readUint32(b[62:66]) == 0xff && readUint32(b[66:70]) == 0xff000000 {
compression = 0
}
if planes != 1 || compression != 0 {
return image.Config{}, 0, false, false, ErrUnsupported
}
switch bpp {
case 8:
colorUsed := readUint32(b[46:50])
// If colorUsed is 0, it is set to the maximum number of colors for the given bpp, which is 2^bpp.
if colorUsed == 0 {
colorUsed = 256
} else if colorUsed > 256 {
return image.Config{}, 0, false, false, ErrUnsupported
}
if offset != fileHeaderLen+infoLen+colorUsed*4 {
return image.Config{}, 0, false, false, ErrUnsupported
}
_, err = io.ReadFull(r, b[:colorUsed*4])
if err != nil {
return image.Config{}, 0, false, false, err
}
pcm := make(color.Palette, colorUsed)
for i := range pcm {
// BMP images are stored in BGR order rather than RGB order.
// Every 4th byte is padding.
pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
}
return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, false, nil
case 24:
if offset != fileHeaderLen+infoLen {
return image.Config{}, 0, false, false, ErrUnsupported
}
return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, false, nil
case 32:
if offset != fileHeaderLen+infoLen {
return image.Config{}, 0, false, false, ErrUnsupported
}
// 32 bits per pixel is possibly RGBX (X is padding) or RGBA (A is
// alpha transparency). However, for BMP images, "Alpha is a
// poorly-documented and inconsistently-used feature" says
// https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=621
//
// That goes on to say "BITMAPV3HEADER+ have an alpha bitmask in the
// info header... so we respect it at all times... [For earlier
// (smaller) headers we] ignore alpha in Windows V3 BMPs except inside
// ICO files".
//
// "Ignore" means to always set alpha to 0xFF (fully opaque):
// https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h;l=272
//
// Confusingly, "Windows V3" does not correspond to BITMAPV3HEADER, but
// instead corresponds to the earlier (smaller) BITMAPINFOHEADER:
// https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=258
//
// This Go package does not support ICO files and the (infoLen >
// infoHeaderLen) condition distinguishes BITMAPINFOHEADER (40 bytes)
// vs later (larger) headers.
allowAlpha = infoLen > infoHeaderLen
return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, allowAlpha, nil
}
return image.Config{}, 0, false, false, ErrUnsupported
}
func init() {
image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig)
}

View File

@@ -1,262 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bmp
import (
"encoding/binary"
"errors"
"image"
"io"
)
type header struct {
sigBM [2]byte
fileSize uint32
resverved [2]uint16
pixOffset uint32
dibHeaderSize uint32
width uint32
height uint32
colorPlane uint16
bpp uint16
compression uint32
imageSize uint32
xPixelsPerMeter uint32
yPixelsPerMeter uint32
colorUse uint32
colorImportant uint32
}
func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
var padding []byte
if dx < step {
padding = make([]byte, step-dx)
}
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx
if _, err := w.Write(pix[min:max]); err != nil {
return err
}
if padding != nil {
if _, err := w.Write(padding); err != nil {
return err
}
}
}
return nil
}
func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
buf := make([]byte, step)
if opaque {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
off += 3
}
if _, err := w.Write(buf); err != nil {
return err
}
}
} else {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
a := uint32(pix[i+3])
if a == 0 {
buf[off+2] = 0
buf[off+1] = 0
buf[off+0] = 0
buf[off+3] = 0
off += 4
continue
} else if a == 0xff {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
buf[off+3] = 0xff
off += 4
continue
}
buf[off+2] = uint8(((uint32(pix[i+0]) * 0xffff) / a) >> 8)
buf[off+1] = uint8(((uint32(pix[i+1]) * 0xffff) / a) >> 8)
buf[off+0] = uint8(((uint32(pix[i+2]) * 0xffff) / a) >> 8)
buf[off+3] = uint8(a)
off += 4
}
if _, err := w.Write(buf); err != nil {
return err
}
}
}
return nil
}
func encodeNRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error {
buf := make([]byte, step)
if opaque {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
off += 3
}
if _, err := w.Write(buf); err != nil {
return err
}
}
} else {
for y := dy - 1; y >= 0; y-- {
min := y*stride + 0
max := y*stride + dx*4
off := 0
for i := min; i < max; i += 4 {
buf[off+2] = pix[i+0]
buf[off+1] = pix[i+1]
buf[off+0] = pix[i+2]
buf[off+3] = pix[i+3]
off += 4
}
if _, err := w.Write(buf); err != nil {
return err
}
}
}
return nil
}
func encode(w io.Writer, m image.Image, step int) error {
b := m.Bounds()
buf := make([]byte, step)
for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
off := 0
for x := b.Min.X; x < b.Max.X; x++ {
r, g, b, _ := m.At(x, y).RGBA()
buf[off+2] = byte(r >> 8)
buf[off+1] = byte(g >> 8)
buf[off+0] = byte(b >> 8)
off += 3
}
if _, err := w.Write(buf); err != nil {
return err
}
}
return nil
}
// Encode writes the image m to w in BMP format.
func Encode(w io.Writer, m image.Image) error {
d := m.Bounds().Size()
if d.X < 0 || d.Y < 0 {
return errors.New("bmp: negative bounds")
}
h := &header{
sigBM: [2]byte{'B', 'M'},
fileSize: 14 + 40,
pixOffset: 14 + 40,
dibHeaderSize: 40,
width: uint32(d.X),
height: uint32(d.Y),
colorPlane: 1,
}
var step int
var palette []byte
var opaque bool
switch m := m.(type) {
case *image.Gray:
step = (d.X + 3) &^ 3
palette = make([]byte, 1024)
for i := 0; i < 256; i++ {
palette[i*4+0] = uint8(i)
palette[i*4+1] = uint8(i)
palette[i*4+2] = uint8(i)
palette[i*4+3] = 0xFF
}
h.imageSize = uint32(d.Y * step)
h.fileSize += uint32(len(palette)) + h.imageSize
h.pixOffset += uint32(len(palette))
h.bpp = 8
case *image.Paletted:
step = (d.X + 3) &^ 3
palette = make([]byte, 1024)
for i := 0; i < len(m.Palette) && i < 256; i++ {
r, g, b, _ := m.Palette[i].RGBA()
palette[i*4+0] = uint8(b >> 8)
palette[i*4+1] = uint8(g >> 8)
palette[i*4+2] = uint8(r >> 8)
palette[i*4+3] = 0xFF
}
h.imageSize = uint32(d.Y * step)
h.fileSize += uint32(len(palette)) + h.imageSize
h.pixOffset += uint32(len(palette))
h.bpp = 8
case *image.RGBA:
opaque = m.Opaque()
if opaque {
step = (3*d.X + 3) &^ 3
h.bpp = 24
} else {
step = 4 * d.X
h.bpp = 32
}
h.imageSize = uint32(d.Y * step)
h.fileSize += h.imageSize
case *image.NRGBA:
opaque = m.Opaque()
if opaque {
step = (3*d.X + 3) &^ 3
h.bpp = 24
} else {
step = 4 * d.X
h.bpp = 32
}
h.imageSize = uint32(d.Y * step)
h.fileSize += h.imageSize
default:
step = (3*d.X + 3) &^ 3
h.imageSize = uint32(d.Y * step)
h.fileSize += h.imageSize
h.bpp = 24
}
if err := binary.Write(w, binary.LittleEndian, h); err != nil {
return err
}
if palette != nil {
if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
return err
}
}
if d.X == 0 || d.Y == 0 {
return nil
}
switch m := m.(type) {
case *image.Gray:
return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
case *image.Paletted:
return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
case *image.RGBA:
return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
case *image.NRGBA:
return encodeNRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque)
}
return encode(w, m, step)
}

View File

@@ -1,257 +0,0 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package charset provides common text encodings for HTML documents.
//
// The mapping from encoding labels to encodings is defined at
// https://encoding.spec.whatwg.org/.
package charset // import "golang.org/x/net/html/charset"
import (
"bytes"
"fmt"
"io"
"mime"
"strings"
"unicode/utf8"
"golang.org/x/net/html"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/htmlindex"
"golang.org/x/text/transform"
)
// Lookup returns the encoding with the specified label, and its canonical
// name. It returns nil and the empty string if label is not one of the
// standard encodings for HTML. Matching is case-insensitive and ignores
// leading and trailing whitespace. Encoders will use HTML escape sequences for
// runes that are not supported by the character set.
func Lookup(label string) (e encoding.Encoding, name string) {
e, err := htmlindex.Get(label)
if err != nil {
return nil, ""
}
name, _ = htmlindex.Name(e)
return &htmlEncoding{e}, name
}
type htmlEncoding struct{ encoding.Encoding }
func (h *htmlEncoding) NewEncoder() *encoding.Encoder {
// HTML requires a non-terminating legacy encoder. We use HTML escapes to
// substitute unsupported code points.
return encoding.HTMLEscapeUnsupported(h.Encoding.NewEncoder())
}
// DetermineEncoding determines the encoding of an HTML document by examining
// up to the first 1024 bytes of content and the declared Content-Type.
//
// See http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#determining-the-character-encoding
func DetermineEncoding(content []byte, contentType string) (e encoding.Encoding, name string, certain bool) {
if len(content) > 1024 {
content = content[:1024]
}
for _, b := range boms {
if bytes.HasPrefix(content, b.bom) {
e, name = Lookup(b.enc)
return e, name, true
}
}
if _, params, err := mime.ParseMediaType(contentType); err == nil {
if cs, ok := params["charset"]; ok {
if e, name = Lookup(cs); e != nil {
return e, name, true
}
}
}
if len(content) > 0 {
e, name = prescan(content)
if e != nil {
return e, name, false
}
}
// Try to detect UTF-8.
// First eliminate any partial rune at the end.
for i := len(content) - 1; i >= 0 && i > len(content)-4; i-- {
b := content[i]
if b < 0x80 {
break
}
if utf8.RuneStart(b) {
content = content[:i]
break
}
}
hasHighBit := false
for _, c := range content {
if c >= 0x80 {
hasHighBit = true
break
}
}
if hasHighBit && utf8.Valid(content) {
return encoding.Nop, "utf-8", false
}
// TODO: change default depending on user's locale?
return charmap.Windows1252, "windows-1252", false
}
// NewReader returns an io.Reader that converts the content of r to UTF-8.
// It calls DetermineEncoding to find out what r's encoding is.
func NewReader(r io.Reader, contentType string) (io.Reader, error) {
preview := make([]byte, 1024)
n, err := io.ReadFull(r, preview)
switch {
case err == io.ErrUnexpectedEOF:
preview = preview[:n]
r = bytes.NewReader(preview)
case err != nil:
return nil, err
default:
r = io.MultiReader(bytes.NewReader(preview), r)
}
if e, _, _ := DetermineEncoding(preview, contentType); e != encoding.Nop {
r = transform.NewReader(r, e.NewDecoder())
}
return r, nil
}
// NewReaderLabel returns a reader that converts from the specified charset to
// UTF-8. It uses Lookup to find the encoding that corresponds to label, and
// returns an error if Lookup returns nil. It is suitable for use as
// encoding/xml.Decoder's CharsetReader function.
func NewReaderLabel(label string, input io.Reader) (io.Reader, error) {
e, _ := Lookup(label)
if e == nil {
return nil, fmt.Errorf("unsupported charset: %q", label)
}
return transform.NewReader(input, e.NewDecoder()), nil
}
func prescan(content []byte) (e encoding.Encoding, name string) {
z := html.NewTokenizer(bytes.NewReader(content))
for {
switch z.Next() {
case html.ErrorToken:
return nil, ""
case html.StartTagToken, html.SelfClosingTagToken:
tagName, hasAttr := z.TagName()
if !bytes.Equal(tagName, []byte("meta")) {
continue
}
attrList := make(map[string]bool)
gotPragma := false
const (
dontKnow = iota
doNeedPragma
doNotNeedPragma
)
needPragma := dontKnow
name = ""
e = nil
for hasAttr {
var key, val []byte
key, val, hasAttr = z.TagAttr()
ks := string(key)
if attrList[ks] {
continue
}
attrList[ks] = true
for i, c := range val {
if 'A' <= c && c <= 'Z' {
val[i] = c + 0x20
}
}
switch ks {
case "http-equiv":
if bytes.Equal(val, []byte("content-type")) {
gotPragma = true
}
case "content":
if e == nil {
name = fromMetaElement(string(val))
if name != "" {
e, name = Lookup(name)
if e != nil {
needPragma = doNeedPragma
}
}
}
case "charset":
e, name = Lookup(string(val))
needPragma = doNotNeedPragma
}
}
if needPragma == dontKnow || needPragma == doNeedPragma && !gotPragma {
continue
}
if strings.HasPrefix(name, "utf-16") {
name = "utf-8"
e = encoding.Nop
}
if e != nil {
return e, name
}
}
}
}
func fromMetaElement(s string) string {
for s != "" {
csLoc := strings.Index(s, "charset")
if csLoc == -1 {
return ""
}
s = s[csLoc+len("charset"):]
s = strings.TrimLeft(s, " \t\n\f\r")
if !strings.HasPrefix(s, "=") {
continue
}
s = s[1:]
s = strings.TrimLeft(s, " \t\n\f\r")
if s == "" {
return ""
}
if q := s[0]; q == '"' || q == '\'' {
s = s[1:]
closeQuote := strings.IndexRune(s, rune(q))
if closeQuote == -1 {
return ""
}
return s[:closeQuote]
}
end := strings.IndexAny(s, "; \t\n\f\r")
if end == -1 {
end = len(s)
}
return s[:end]
}
return ""
}
var boms = []struct {
bom []byte
enc string
}{
{[]byte{0xfe, 0xff}, "utf-16be"},
{[]byte{0xff, 0xfe}, "utf-16le"},
{[]byte{0xef, 0xbb, 0xbf}, "utf-8"},
}

View File

@@ -299,7 +299,7 @@ func escape(w writer, s string) error {
case '\r':
esc = "&#13;"
default:
panic("unrecognized escape character")
panic("html: unrecognized escape character")
}
s = s[i+1:]
if _, err := w.WriteString(esc); err != nil {

View File

@@ -136,7 +136,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
return -1
}
default:
panic("unreachable")
panic(fmt.Sprintf("html: internal error: indexOfElementInScope unknown scope: %d", s))
}
}
switch s {
@@ -179,7 +179,7 @@ func (p *parser) clearStackToContext(s scope) {
return
}
default:
panic("unreachable")
panic(fmt.Sprintf("html: internal error: clearStackToContext unknown scope: %d", s))
}
}
}
@@ -231,7 +231,14 @@ func (p *parser) addChild(n *Node) {
}
if n.Type == ElementNode {
p.oe = append(p.oe, n)
p.insertOpenElement(n)
}
}
func (p *parser) insertOpenElement(n *Node) {
p.oe = append(p.oe, n)
if len(p.oe) > 512 {
panic("html: open stack of elements exceeds 512 nodes")
}
}
@@ -810,7 +817,7 @@ func afterHeadIM(p *parser) bool {
p.im = inFramesetIM
return true
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
p.oe = append(p.oe, p.head)
p.insertOpenElement(p.head)
defer p.oe.remove(p.head)
return inHeadIM(p)
case a.Head:
@@ -1678,7 +1685,7 @@ func inTableBodyIM(p *parser) bool {
return inTableIM(p)
}
// Section 12.2.6.4.14.
// Section 13.2.6.4.14.
func inRowIM(p *parser) bool {
switch p.tok.Type {
case StartTagToken:
@@ -1690,7 +1697,9 @@ func inRowIM(p *parser) bool {
p.im = inCellIM
return true
case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
if p.popUntil(tableScope, a.Tr) {
if p.elementInScope(tableScope, a.Tr) {
p.clearStackToContext(tableRowScope)
p.oe.pop()
p.im = inTableBodyIM
return false
}
@@ -1700,22 +1709,28 @@ func inRowIM(p *parser) bool {
case EndTagToken:
switch p.tok.DataAtom {
case a.Tr:
if p.popUntil(tableScope, a.Tr) {
if p.elementInScope(tableScope, a.Tr) {
p.clearStackToContext(tableRowScope)
p.oe.pop()
p.im = inTableBodyIM
return true
}
// Ignore the token.
return true
case a.Table:
if p.popUntil(tableScope, a.Tr) {
if p.elementInScope(tableScope, a.Tr) {
p.clearStackToContext(tableRowScope)
p.oe.pop()
p.im = inTableBodyIM
return false
}
// Ignore the token.
return true
case a.Tbody, a.Tfoot, a.Thead:
if p.elementInScope(tableScope, p.tok.DataAtom) {
p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
if p.elementInScope(tableScope, p.tok.DataAtom) && p.elementInScope(tableScope, a.Tr) {
p.clearStackToContext(tableRowScope)
p.oe.pop()
p.im = inTableBodyIM
return false
}
// Ignore the token.
@@ -2222,16 +2237,20 @@ func parseForeignContent(p *parser) bool {
p.acknowledgeSelfClosingTag()
}
case EndTagToken:
if strings.EqualFold(p.oe[len(p.oe)-1].Data, p.tok.Data) {
p.oe = p.oe[:len(p.oe)-1]
return true
}
for i := len(p.oe) - 1; i >= 0; i-- {
if p.oe[i].Namespace == "" {
return p.im(p)
}
if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
p.oe = p.oe[:i]
return true
}
if i > 0 && p.oe[i-1].Namespace == "" {
break
}
}
return true
return p.im(p)
default:
// Ignore the token.
}
@@ -2312,9 +2331,13 @@ func (p *parser) parseCurrentToken() {
}
}
func (p *parser) parse() error {
func (p *parser) parse() (err error) {
defer func() {
if panicErr := recover(); panicErr != nil {
err = fmt.Errorf("%s", panicErr)
}
}()
// Iterate until EOF. Any other error will cause an early return.
var err error
for err != io.EOF {
// CDATA sections are allowed only in foreign content.
n := p.oe.top()
@@ -2343,6 +2366,8 @@ func (p *parser) parse() error {
// <tag>s. Conversely, explicit <tag>s in r's data can be silently dropped,
// with no corresponding node in the resulting tree.
//
// Parse will reject HTML that is nested deeper than 512 elements.
//
// The input is assumed to be UTF-8 encoded.
func Parse(r io.Reader) (*Node, error) {
return ParseWithOptions(r)

View File

@@ -184,7 +184,7 @@ func render1(w writer, n *Node) error {
return err
}
// Add initial newline where there is danger of a newline beging ignored.
// Add initial newline where there is danger of a newline being ignored.
if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
switch n.Data {
case "pre", "listing", "textarea":

View File

@@ -27,6 +27,7 @@ import (
// - If the resulting value is zero or out of range, use a default.
type http2Config struct {
MaxConcurrentStreams uint32
StrictMaxConcurrentRequests bool
MaxDecoderHeaderTableSize uint32
MaxEncoderHeaderTableSize uint32
MaxReadFrameSize uint32
@@ -64,12 +65,13 @@ func configFromServer(h1 *http.Server, h2 *Server) http2Config {
// (the net/http Transport).
func configFromTransport(h2 *Transport) http2Config {
conf := http2Config{
MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
MaxReadFrameSize: h2.MaxReadFrameSize,
SendPingTimeout: h2.ReadIdleTimeout,
PingTimeout: h2.PingTimeout,
WriteByteTimeout: h2.WriteByteTimeout,
StrictMaxConcurrentRequests: h2.StrictMaxConcurrentStreams,
MaxEncoderHeaderTableSize: h2.MaxEncoderHeaderTableSize,
MaxDecoderHeaderTableSize: h2.MaxDecoderHeaderTableSize,
MaxReadFrameSize: h2.MaxReadFrameSize,
SendPingTimeout: h2.ReadIdleTimeout,
PingTimeout: h2.PingTimeout,
WriteByteTimeout: h2.WriteByteTimeout,
}
// Unlike most config fields, where out-of-range values revert to the default,
@@ -128,6 +130,9 @@ func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) {
if h2.MaxConcurrentStreams != 0 {
conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams)
}
if http2ConfigStrictMaxConcurrentRequests(h2) {
conf.StrictMaxConcurrentRequests = true
}
if h2.MaxEncoderHeaderTableSize != 0 {
conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize)
}

15
vendor/golang.org/x/net/http2/config_go125.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.26
package http2
import (
"net/http"
)
func http2ConfigStrictMaxConcurrentRequests(h2 *http.HTTP2Config) bool {
return false
}

Some files were not shown because too many files have changed in this diff Show More