Compare commits

...

4 Commits

Author SHA1 Message Date
dbarrosop
2979e6ccf4 release(services/storage): 0.10.0 2025-11-19 07:46:31 +00:00
David Barroso
ab890d8593 fix(cli): update traefik (#3710) 2025-11-19 08:45:12 +01:00
David Barroso
ee2d9763f7 feat(storage): added support for images/heic (#3694) 2025-11-19 08:21:43 +01:00
David Barroso
f7ea20db61 feat(docs): added guide to use the guild's codegen directly with Nhost (#3696) 2025-11-19 08:21:30 +01:00
181 changed files with 50711 additions and 160684 deletions

View File

@@ -250,7 +250,7 @@ func traefik(subdomain, projectName string, port uint, dotnhostfolder string) (*
}
return &Service{
Image: "traefik:v3.1",
Image: "traefik:v3.6",
DependsOn: nil,
EntryPoint: nil,
Command: []string{

View File

@@ -4191,32 +4191,34 @@ type Plans struct {
// An array relationship
Organizations []*Organizations `json:"organizations"`
Price int64 `json:"price"`
SLALevel SLALevelEnum `json:"slaLevel"`
Sort int64 `json:"sort"`
UpatedAt time.Time `json:"upatedAt"`
}
// Boolean expression to filter rows from the table "plans". All fields are combined with a logical 'AND'.
type PlansBoolExp struct {
And []*PlansBoolExp `json:"_and,omitempty"`
Not *PlansBoolExp `json:"_not,omitempty"`
Or []*PlansBoolExp `json:"_or,omitempty"`
Apps *AppsBoolExp `json:"apps,omitempty"`
CreatedAt *TimestamptzComparisonExp `json:"createdAt,omitempty"`
Deprecated *BooleanComparisonExp `json:"deprecated,omitempty"`
FeatureBackupEnabled *BooleanComparisonExp `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *BooleanComparisonExp `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *BooleanComparisonExp `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *IntComparisonExp `json:"featureMaxDbSize,omitempty"`
ID *UUIDComparisonExp `json:"id,omitempty"`
Individual *BooleanComparisonExp `json:"individual,omitempty"`
IsDefault *BooleanComparisonExp `json:"isDefault,omitempty"`
IsFree *BooleanComparisonExp `json:"isFree,omitempty"`
IsPublic *BooleanComparisonExp `json:"isPublic,omitempty"`
Name *StringComparisonExp `json:"name,omitempty"`
Organizations *OrganizationsBoolExp `json:"organizations,omitempty"`
Price *IntComparisonExp `json:"price,omitempty"`
Sort *IntComparisonExp `json:"sort,omitempty"`
UpatedAt *TimestamptzComparisonExp `json:"upatedAt,omitempty"`
And []*PlansBoolExp `json:"_and,omitempty"`
Not *PlansBoolExp `json:"_not,omitempty"`
Or []*PlansBoolExp `json:"_or,omitempty"`
Apps *AppsBoolExp `json:"apps,omitempty"`
CreatedAt *TimestamptzComparisonExp `json:"createdAt,omitempty"`
Deprecated *BooleanComparisonExp `json:"deprecated,omitempty"`
FeatureBackupEnabled *BooleanComparisonExp `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *BooleanComparisonExp `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *BooleanComparisonExp `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *IntComparisonExp `json:"featureMaxDbSize,omitempty"`
ID *UUIDComparisonExp `json:"id,omitempty"`
Individual *BooleanComparisonExp `json:"individual,omitempty"`
IsDefault *BooleanComparisonExp `json:"isDefault,omitempty"`
IsFree *BooleanComparisonExp `json:"isFree,omitempty"`
IsPublic *BooleanComparisonExp `json:"isPublic,omitempty"`
Name *StringComparisonExp `json:"name,omitempty"`
Organizations *OrganizationsBoolExp `json:"organizations,omitempty"`
Price *IntComparisonExp `json:"price,omitempty"`
SLALevel *SLALevelEnumComparisonExp `json:"slaLevel,omitempty"`
Sort *IntComparisonExp `json:"sort,omitempty"`
UpatedAt *TimestamptzComparisonExp `json:"upatedAt,omitempty"`
}
// Ordering options when selecting data from "plans".
@@ -4236,6 +4238,7 @@ type PlansOrderBy struct {
Name *OrderBy `json:"name,omitempty"`
OrganizationsAggregate *OrganizationsAggregateOrderBy `json:"organizations_aggregate,omitempty"`
Price *OrderBy `json:"price,omitempty"`
SLALevel *OrderBy `json:"slaLevel,omitempty"`
Sort *OrderBy `json:"sort,omitempty"`
UpatedAt *OrderBy `json:"upatedAt,omitempty"`
}
@@ -4250,21 +4253,22 @@ type PlansStreamCursorInput struct {
// Initial value of the column from where the streaming should start
type PlansStreamCursorValueInput struct {
CreatedAt *time.Time `json:"createdAt,omitempty"`
Deprecated *bool `json:"deprecated,omitempty"`
FeatureBackupEnabled *bool `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *bool `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *bool `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *int64 `json:"featureMaxDbSize,omitempty"`
ID *string `json:"id,omitempty"`
Individual *bool `json:"individual,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
IsFree *bool `json:"isFree,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
Name *string `json:"name,omitempty"`
Price *int64 `json:"price,omitempty"`
Sort *int64 `json:"sort,omitempty"`
UpatedAt *time.Time `json:"upatedAt,omitempty"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
Deprecated *bool `json:"deprecated,omitempty"`
FeatureBackupEnabled *bool `json:"featureBackupEnabled,omitempty"`
FeatureCustomDomainsEnabled *bool `json:"featureCustomDomainsEnabled,omitempty"`
FeatureCustomEmailTemplatesEnabled *bool `json:"featureCustomEmailTemplatesEnabled,omitempty"`
FeatureMaxDbSize *int64 `json:"featureMaxDbSize,omitempty"`
ID *string `json:"id,omitempty"`
Individual *bool `json:"individual,omitempty"`
IsDefault *bool `json:"isDefault,omitempty"`
IsFree *bool `json:"isFree,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
Name *string `json:"name,omitempty"`
Price *int64 `json:"price,omitempty"`
SLALevel *SLALevelEnum `json:"slaLevel,omitempty"`
Sort *int64 `json:"sort,omitempty"`
UpatedAt *time.Time `json:"upatedAt,omitempty"`
}
type QueryRoot struct {
@@ -4694,6 +4698,15 @@ type RunServiceStreamCursorValueInput struct {
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}
// Boolean expression to compare columns of type "sla_level_enum". All fields are combined with logical 'AND'.
type SLALevelEnumComparisonExp struct {
Eq *SLALevelEnum `json:"_eq,omitempty"`
In []SLALevelEnum `json:"_in,omitempty"`
IsNull *bool `json:"_is_null,omitempty"`
Neq *SLALevelEnum `json:"_neq,omitempty"`
Nin []SLALevelEnum `json:"_nin,omitempty"`
}
// Boolean expression to compare columns of type "software_type_enum". All fields are combined with logical 'AND'.
type SoftwareTypeEnumComparisonExp struct {
Eq *SoftwareTypeEnum `json:"_eq,omitempty"`
@@ -8542,6 +8555,8 @@ const (
// column name
PlansSelectColumnPrice PlansSelectColumn = "price"
// column name
PlansSelectColumnSLALevel PlansSelectColumn = "slaLevel"
// column name
PlansSelectColumnSort PlansSelectColumn = "sort"
// column name
PlansSelectColumnUpatedAt PlansSelectColumn = "upatedAt"
@@ -8561,13 +8576,14 @@ var AllPlansSelectColumn = []PlansSelectColumn{
PlansSelectColumnIsPublic,
PlansSelectColumnName,
PlansSelectColumnPrice,
PlansSelectColumnSLALevel,
PlansSelectColumnSort,
PlansSelectColumnUpatedAt,
}
func (e PlansSelectColumn) IsValid() bool {
switch e {
case PlansSelectColumnCreatedAt, PlansSelectColumnDeprecated, PlansSelectColumnFeatureBackupEnabled, PlansSelectColumnFeatureCustomDomainsEnabled, PlansSelectColumnFeatureCustomEmailTemplatesEnabled, PlansSelectColumnFeatureMaxDbSize, PlansSelectColumnID, PlansSelectColumnIndividual, PlansSelectColumnIsDefault, PlansSelectColumnIsFree, PlansSelectColumnIsPublic, PlansSelectColumnName, PlansSelectColumnPrice, PlansSelectColumnSort, PlansSelectColumnUpatedAt:
case PlansSelectColumnCreatedAt, PlansSelectColumnDeprecated, PlansSelectColumnFeatureBackupEnabled, PlansSelectColumnFeatureCustomDomainsEnabled, PlansSelectColumnFeatureCustomEmailTemplatesEnabled, PlansSelectColumnFeatureMaxDbSize, PlansSelectColumnID, PlansSelectColumnIndividual, PlansSelectColumnIsDefault, PlansSelectColumnIsFree, PlansSelectColumnIsPublic, PlansSelectColumnName, PlansSelectColumnPrice, PlansSelectColumnSLALevel, PlansSelectColumnSort, PlansSelectColumnUpatedAt:
return true
}
return false
@@ -8954,6 +8970,66 @@ func (e RunServiceSelectColumn) MarshalJSON() ([]byte, error) {
return buf.Bytes(), nil
}
type SLALevelEnum string
const (
// No SLA
SLALevelEnumNone SLALevelEnum = "none"
// Premium SLA
SLALevelEnumPremium SLALevelEnum = "premium"
// Standard SLA
SLALevelEnumStandard SLALevelEnum = "standard"
)
var AllSLALevelEnum = []SLALevelEnum{
SLALevelEnumNone,
SLALevelEnumPremium,
SLALevelEnumStandard,
}
func (e SLALevelEnum) IsValid() bool {
switch e {
case SLALevelEnumNone, SLALevelEnumPremium, SLALevelEnumStandard:
return true
}
return false
}
func (e SLALevelEnum) String() string {
return string(e)
}
func (e *SLALevelEnum) UnmarshalGQL(v any) error {
str, ok := v.(string)
if !ok {
return fmt.Errorf("enums must be strings")
}
*e = SLALevelEnum(str)
if !e.IsValid() {
return fmt.Errorf("%s is not a valid sla_level_enum", str)
}
return nil
}
func (e SLALevelEnum) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
func (e *SLALevelEnum) UnmarshalJSON(b []byte) error {
s, err := strconv.Unquote(string(b))
if err != nil {
return err
}
return e.UnmarshalGQL(s)
}
func (e SLALevelEnum) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
e.MarshalGQL(&buf)
return buf.Bytes(), nil
}
type SoftwareTypeEnum string
const (

View File

@@ -220,7 +220,8 @@
"pages": [
"/products/graphql/guides/react-apollo",
"/products/graphql/guides/react-query",
"/products/graphql/guides/react-urql"
"/products/graphql/guides/react-urql",
"/products/graphql/guides/codegen-nhost"
]
}
]

View File

@@ -1326,10 +1326,9 @@ After we complete the next tutorial on user authentication, you will be able to
1. **Server-Side Helpers**: Utilities for handling authentication in Next.js server components and middleware
2. **Middleware Route Protection**: Next.js middleware runs before any page renders, automatically redirecting unauthenticated users from protected routes and refreshing tokens
3. **AuthProvider**: Client-side provider that manages authentication state using Nhost's client with cookie-based storage for server/client synchronization
4. **Protected Pages**: Server components can assume authentication since middleware handles protection, focusing purely on rendering authenticated content
5. **Navigation**: Server-side navigation component that adapts its links based on authentication status
6. **Automatic Redirects**: All route protection and redirects are handled at the middleware level for optimal performance and security
3. **Protected Pages**: Server components can assume authentication since middleware handles protection, focusing purely on rendering authenticated content
4. **Navigation**: Server-side navigation component that adapts its links based on authentication status
5. **Automatic Redirects**: All route protection and redirects are handled at the middleware level for optimal performance and security
## Key Features Demonstrated

View File

@@ -0,0 +1,9 @@
---
title: "Codegen + Nhost"
description: "How to use The Guild's codegen with Nhost"
icon: U
---
You can use [The Guild's codegen](https://the-guild.dev/graphql/codegen) to generate types and document nodes for your GraphQL operations and use them directly with Nhost's GraphQL client.
You can find a working example with instructions in our [GitHub repository](https://github.com/nhost/nhost/blob/main/examples/guides/codegen-nhost/README.md).

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

View File

@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.vite

View File

@@ -0,0 +1,443 @@
# GraphQL Code Generation with Nhost SDK
This guide demonstrates how to use GraphQL Code Generator with TypedDocumentNode to get full type safety when working with the Nhost SDK.
Note: While the project uses React to illustrate usage, the generated types and documents can be used in any JavaScript/TypeScript environment.
## Overview
The Nhost SDK's GraphQL client supports `TypedDocumentNode` from `@graphql-typed-document-node/core`, allowing you to use generated types and documents for type-safe GraphQL operations. This guide shows you how to set up GraphQL Code Generator to work seamlessly with Nhost.
## Setup
### 1. Install Dependencies
```bash
npm install @nhost/nhost-js graphql graphql-typed-document-node/core
# or
yarn add @nhost/nhost-js graphql graphql-typed-document-node/core
# or
pnpm add @nhost/nhost-js graphql graphql-typed-document-node/core
```
### 2. Install GraphQL CodeGen
Install the necessary code generation packages:
```bash
npm install -D @graphql-codegen/cli @graphql-codegen/client-preset @graphql-codegen/schema-ast
# or
pnpm add -D @graphql-codegen/cli @graphql-codegen/client-preset @graphql-codegen/schema-ast
```
### 3. Configure GraphQL CodeGen
Create a `codegen.ts` file with the client preset configuration:
```typescript
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: [
{
"https://local.graphql.local.nhost.run/v1": {
headers: {
"x-hasura-admin-secret": "nhost-admin-secret",
},
},
},
],
documents: ["src/lib/graphql/**/*.graphql"],
ignoreNoDocuments: true,
generates: {
"./src/lib/graphql/__generated__/": {
preset: "client",
presetConfig: {
persistedDocuments: false,
},
plugins: [
{
"./add-query-source-plugin.cjs": {},
},
],
config: {
scalars: {
UUID: "string",
uuid: "string",
timestamptz: "string",
jsonb: "Record<string, any>",
bigint: "number",
bytea: "Buffer",
citext: "string",
},
useTypeImports: true,
},
},
"./schema.graphql": {
plugins: ["schema-ast"],
config: {
includeDirectives: true,
},
},
},
};
export default config;
```
### 4. Create the Custom Plugin
The Nhost SDK expects documents to have a `loc.source.body` property containing the query string. Create a custom plugin to add this:
**add-query-source-plugin.cjs:**
```javascript
// Custom GraphQL Codegen plugin to add loc.source.body to generated documents
// This allows the Nhost SDK to extract the query string without needing the graphql package
const { print } = require("graphql");
/**
* @type {import('@graphql-codegen/plugin-helpers').PluginFunction}
*/
const plugin = (_schema, documents, _config) => {
let output = "";
for (const doc of documents) {
if (!doc.document) continue;
for (const definition of doc.document.definitions) {
if (definition.kind === "OperationDefinition" && definition.name) {
const operationName = definition.name.value;
const documentName = `${operationName}Document`;
// Create a document with just this operation
const singleOpDocument = {
kind: "Document",
definitions: [definition],
};
// Use graphql print to convert AST to string
const source = print(singleOpDocument);
output += `
// Add query source to ${documentName}
if (${documentName}) {
Object.assign(${documentName}, {
loc: { source: { body: ${JSON.stringify(source)} } }
});
}
`;
}
}
}
return output;
};
module.exports = { plugin };
```
## Integration Guide
### 1. Create an Auth Provider
Create an authentication context to manage the Nhost client and user session:
```typescript
// src/lib/nhost/AuthProvider.tsx
import {
createContext,
useContext,
useEffect,
useState,
useMemo,
type ReactNode,
} from "react";
import { createClient, type NhostClient } from "@nhost/nhost-js";
import { type Session } from "@nhost/nhost-js/auth";
interface AuthContextType {
user: Session["user"] | null;
session: Session | null;
isAuthenticated: boolean;
isLoading: boolean;
nhost: NhostClient;
}
const AuthContext = createContext<AuthContextType | null>(null);
export const AuthProvider = ({ children }: { children: ReactNode }) => {
const [user, setUser] = useState<Session["user"] | null>(null);
const [session, setSession] = useState<Session | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
// Create the nhost client
const nhost = useMemo(
() =>
createClient({
region: import.meta.env.VITE_NHOST_REGION || "local",
subdomain: import.meta.env.VITE_NHOST_SUBDOMAIN || "local",
}),
[],
);
useEffect(() => {
setIsLoading(true);
const currentSession = nhost.getUserSession();
setUser(currentSession?.user || null);
setSession(currentSession);
setIsAuthenticated(!!currentSession);
setIsLoading(false);
const unsubscribe = nhost.sessionStorage.onChange((currentSession) => {
setUser(currentSession?.user || null);
setSession(currentSession);
setIsAuthenticated(!!currentSession);
});
return () => {
unsubscribe();
};
}, [nhost]);
const value: AuthContextType = {
user,
session,
isAuthenticated,
isLoading,
nhost,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
export const useAuth = (): AuthContextType => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};
```
### 2. Set Up Your App Providers
Wrap your application with the Auth provider:
```tsx
// src/main.tsx
import React from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App";
import { AuthProvider } from "./lib/nhost/AuthProvider";
const Root = () => (
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>
);
const rootElement = document.getElementById("root");
if (!rootElement) throw new Error("Root element not found");
createRoot(rootElement).render(<Root />);
```
### 3. Define GraphQL Operations
Create GraphQL files with your queries and mutations:
```graphql
# src/lib/graphql/operations.graphql
query GetNinjaTurtlesWithComments {
ninjaTurtles {
id
name
description
createdAt
updatedAt
comments {
id
comment
createdAt
user {
id
displayName
email
}
}
}
}
mutation AddComment($ninjaTurtleId: uuid!, $comment: String!) {
insertComment(object: { ninjaTurtleId: $ninjaTurtleId, comment: $comment }) {
id
comment
createdAt
ninjaTurtleId
}
}
```
### 4. Generate TypeScript Types
Run the code generator:
```bash
npx graphql-codegen
```
You can also add a script to your `package.json`:
```json
{
"scripts": {
"generate": "graphql-codegen --config codegen.ts"
}
}
```
Then run:
```bash
npm run generate
# or
pnpm generate
```
### 5. Use in Components
Use the generated types and documents with the Nhost SDK:
```tsx
// src/pages/Home.tsx
import { type JSX, useCallback, useEffect, useState } from "react";
import {
AddCommentDocument,
GetNinjaTurtlesWithCommentsDocument,
type GetNinjaTurtlesWithCommentsQuery,
} from "../lib/graphql/__generated__/graphql";
import { useAuth } from "../lib/nhost/AuthProvider";
export default function Home(): JSX.Element {
const { isLoading, nhost } = useAuth();
const [activeCommentId, setActiveCommentId] = useState<string | null>(null);
const [commentText, setCommentText] = useState("");
const [activeTabId, setActiveTabId] = useState<string | null>(null);
const [data, setData] = useState<GetNinjaTurtlesWithCommentsQuery | null>(
null,
);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
// Fetch ninja turtles data
const fetchNinjaTurtles = useCallback(async () => {
setLoading(true);
setError(null);
try {
const result = await nhost.graphql.request(
GetNinjaTurtlesWithCommentsDocument,
{},
);
if (result.body.errors) {
throw new Error(result.body.errors[0]?.message);
}
setData(result.body.data ?? null);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
}, [nhost.graphql]);
// Load data on mount
useEffect(() => {
if (!isLoading) {
fetchNinjaTurtles();
}
}, [isLoading, fetchNinjaTurtles]);
const addComment = async (ninjaTurtleId: string, comment: string) => {
try {
const result = await nhost.graphql.request(AddCommentDocument, {
ninjaTurtleId,
comment,
});
if (result.body.errors) {
throw new Error(result.body.errors[0]?.message);
}
// Clear form and refetch data
setCommentText("");
setActiveCommentId(null);
await fetchNinjaTurtles();
} catch (err) {
console.error("Error adding comment:", err);
}
};
// ... rest of component
}
```
## Key Points
### Type-Safe GraphQL Requests
The Nhost SDK's `graphql.request()` method has overloads that support `TypedDocumentNode`:
```typescript
// Type inference works automatically
const result = await nhost.graphql.request(
GetNinjaTurtlesWithCommentsDocument,
{}, // Variables are type-checked
);
// result.body.data is typed as GetNinjaTurtlesWithCommentsQuery | undefined
```
### How It Works
1. **GraphQL Code Generator** creates `TypedDocumentNode` types and documents using the client preset
2. **Custom Plugin** adds the `loc.source.body` property to each document at runtime
3. **Nhost SDK** detects the `TypedDocumentNode`, extracts the query string from `loc.source.body`, and executes the request
4. **TypeScript** infers response types automatically based on the document types
### Benefits
- ✅ Full type safety for queries, mutations, and variables
- ✅ Automatic type inference - no manual type annotations needed
- ✅ Type-checked variables prevent runtime errors
- ✅ IntelliSense support in your IDE
- ✅ Compile-time errors for invalid queries or mismatched types
## Troubleshooting
### "not a valid graphql query" Error
If you see this error, make sure:
1. The custom plugin (`add-query-source-plugin.cjs`) is in place
2. The plugin is configured in your `codegen.ts`
3. You've run `pnpm generate` after adding the plugin
### TypeScript Errors
If you get type errors:
1. Make sure you're not passing explicit generic type parameters to `nhost.graphql.request()`
2. Let TypeScript infer types from the document
3. Pass an empty object `{}` for queries without variables
## Additional Resources
- [GraphQL Code Generator Docs](https://the-guild.dev/graphql/codegen)
- [Nhost Documentation](https://docs.nhost.io)
- [TypedDocumentNode](https://github.com/dotansimha/graphql-typed-document-node)

View File

@@ -0,0 +1,44 @@
// Custom GraphQL Codegen plugin to add loc.source.body to generated documents
// This allows the Nhost SDK to extract the query string without needing the graphql package
const { print } = require("graphql");
/**
* @type {import('@graphql-codegen/plugin-helpers').PluginFunction}
*/
const plugin = (_schema, documents, _config) => {
let output = "";
for (const doc of documents) {
if (!doc.document) continue;
for (const definition of doc.document.definitions) {
if (definition.kind === "OperationDefinition" && definition.name) {
const operationName = definition.name.value;
const documentName = `${operationName}Document`;
// Create a document with just this operation
const singleOpDocument = {
kind: "Document",
definitions: [definition],
};
// Use graphql print to convert AST to string
const source = print(singleOpDocument);
output += `
// Add query source to ${documentName}
if (${documentName}) {
Object.assign(${documentName}, {
loc: { source: { body: ${JSON.stringify(source)} } }
});
}
`;
}
}
}
return output;
};
module.exports = { plugin };

View File

@@ -0,0 +1,7 @@
{
"root": false,
"extends": "//",
"linter": {
"includes": ["**", "!src/lib/graphql/__generated__/*.ts"]
}
}

View File

@@ -0,0 +1,27 @@
#!/bin/bash
set -e
echo "Running GraphQL code generator..."
pnpm graphql-codegen --config codegen.ts
GENERATED_TS_FILE="src/lib/graphql/__generated__/"
GENERATED_SCHEMA_FILE="schema.graphql"
if [ -d "$GENERATED_TS_FILE" ]; then
echo "Formatting $GENERATED_TS_FILE..."
biome check --write "$GENERATED_TS_FILE"
else
echo "Error: Generated TypeScript file not found at $GENERATED_TS_FILE"
exit 1
fi
if [ -f "$GENERATED_SCHEMA_FILE" ]; then
echo "Formatting $GENERATED_SCHEMA_FILE..."
biome check --write "$GENERATED_SCHEMA_FILE"
echo "Successfully formatted $GENERATED_SCHEMA_FILE"
else
echo "Warning: Generated schema file not found at $GENERATED_SCHEMA_FILE"
fi
echo "All tasks completed successfully."

View File

@@ -0,0 +1,48 @@
import type { CodegenConfig } from "@graphql-codegen/cli";
const config: CodegenConfig = {
schema: [
{
"https://local.graphql.local.nhost.run/v1": {
headers: {
"x-hasura-admin-secret": "nhost-admin-secret",
},
},
},
],
documents: ["src/lib/graphql/**/*.graphql"],
ignoreNoDocuments: true,
generates: {
"./src/lib/graphql/__generated__/": {
preset: "client",
presetConfig: {
persistedDocuments: false,
},
plugins: [
{
"./add-query-source-plugin.cjs": {},
},
],
config: {
scalars: {
UUID: "string",
uuid: "string",
timestamptz: "string",
jsonb: "Record<string, any>",
bigint: "number",
bytea: "Buffer",
citext: "string",
},
useTypeImports: true,
},
},
"./schema.graphql": {
plugins: ["schema-ast"],
config: {
includeDirectives: true,
},
},
},
};
export default config;

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,40 @@
{
"name": "guides/codegen-nhost",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"generate": "bash codegen-wrapper.sh",
"test": "pnpm test:typecheck && pnpm test:lint",
"test:typecheck": "tsc --noEmit",
"test:lint": "biome check",
"format": "biome format --write",
"preview": "vite preview"
},
"dependencies": {
"@graphql-typed-document-node/core": "^3.2.0",
"@nhost/nhost-js": "workspace:*",
"graphql": "^16.11.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.0"
},
"devDependencies": {
"@graphql-codegen/cli": "^5.0.6",
"@graphql-codegen/client-preset": "^5.1.2",
"@graphql-codegen/schema-ast": "^4.1.0",
"@graphql-codegen/typescript": "^4.1.6",
"@graphql-codegen/typescript-operations": "^4.6.1",
"@types/node": "^22.15.17",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^4.4.1"
},
"pnpm": {
"overrides": {
"js-yaml@<4.1.1": ">=4.1.1"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
import type { JSX } from "react";
import {
createBrowserRouter,
createRoutesFromElements,
Navigate,
Outlet,
Route,
RouterProvider,
} from "react-router-dom";
import Navigation from "./components/Navigation";
import ProtectedRoute from "./components/ProtectedRoute";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import SignIn from "./pages/SignIn";
import SignUp from "./pages/SignUp";
// Root layout component to wrap all routes
const RootLayout = (): JSX.Element => {
return (
<div className="flex-col min-h-screen">
<Navigation />
<main className="max-w-2xl mx-auto p-6 w-full">
<Outlet />
</main>
<footer>
<p
className="text-sm text-center"
style={{ color: "var(--text-muted)" }}
>
© {new Date().getFullYear()} Nhost Demo
</p>
</footer>
</div>
);
};
// Create router with routes
const router = createBrowserRouter(
createRoutesFromElements(
<Route element={<RootLayout />}>
<Route path="signin" element={<SignIn />} />
<Route path="signup" element={<SignUp />} />
<Route element={<ProtectedRoute />}>
<Route path="home" element={<Home />} />
<Route path="profile" element={<Profile />} />
</Route>
<Route path="*" element={<Navigate to="/" />} />
</Route>,
),
);
const App = (): JSX.Element => {
return <RouterProvider router={router} />;
};
export default App;

View File

@@ -0,0 +1,85 @@
import type { JSX } from "react";
import { Link, useLocation } from "react-router-dom";
import { useAuth } from "../lib/nhost/AuthProvider";
export default function Navigation(): JSX.Element {
const { isAuthenticated, nhost, session } = useAuth();
const location = useLocation();
// Helper function to determine if a link is active
const isActive = (path: string): string => {
return location.pathname === path ? "active" : "";
};
return (
<nav className="navbar">
<div className="navbar-container">
<div className="flex items-center">
<span className="navbar-brand">Nhost Demo</span>
<div className="navbar-links">
{isAuthenticated ? (
<>
<Link to="/home" className={`nav-link ${isActive("/home")}`}>
Home
</Link>
<Link
to="/profile"
className={`nav-link ${isActive("/profile")}`}
>
Profile
</Link>
</>
) : (
<>
<Link
to="/signin"
className={`nav-link ${isActive("/signin")}`}
>
Sign In
</Link>
<Link
to="/signup"
className={`nav-link ${isActive("/signup")}`}
>
Sign Up
</Link>
</>
)}
</div>
</div>
{isAuthenticated && (
<div>
<button
type="button"
onClick={async () => {
if (session) {
await nhost.auth.signOut({
refreshToken: session.refreshToken,
});
}
}}
className="icon-button"
title="Sign Out"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-label="Sign Out"
role="img"
>
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
<polyline points="16 17 21 12 16 7" />
<line x1="21" y1="12" x2="9" y2="12" />
</svg>
</button>
</div>
)}
</div>
</nav>
);
}

View File

@@ -0,0 +1,26 @@
import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "../lib/nhost/AuthProvider";
interface ProtectedRouteProps {
redirectTo?: string;
}
export default function ProtectedRoute({
redirectTo = "/signin",
}: ProtectedRouteProps) {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) {
return (
<div className="loading-container">
<p>Loading...</p>
</div>
);
}
if (!isAuthenticated) {
return <Navigate to={redirectTo} />;
}
return <Outlet />;
}

View File

@@ -0,0 +1,552 @@
/* Base styles */
:root {
--background: #030712;
--foreground: #ffffff;
--card-bg: #111827;
--card-border: #1f2937;
--primary: #6366f1;
--primary-hover: #4f46e5;
--secondary: #10b981;
--secondary-hover: #059669;
--accent: #8b5cf6;
--accent-hover: #7c3aed;
--success: #22c55e;
--error: #ef4444;
--text-primary: #f9fafb;
--text-secondary: #d1d5db;
--text-muted: #9ca3af;
--border-color: rgba(31, 41, 55, 0.7);
--font-geist-mono:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: var(--background);
color: var(--foreground);
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
min-height: 100vh;
}
/* Layout */
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.items-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.justify-between {
justify-content: space-between;
}
.min-h-screen {
min-height: 100vh;
}
.w-full {
width: 100%;
}
.max-w-2xl {
max-width: 42rem;
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.p-6 {
padding: 1.5rem;
}
.p-8 {
padding: 2rem;
}
.py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
}
.mb-6 {
margin-bottom: 1.5rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.mt-4 {
margin-top: 1rem;
}
.mr-8 {
margin-right: 2rem;
}
.ml-2 {
margin-left: 0.5rem;
}
.space-y-5 > * + * {
margin-top: 1.25rem;
}
.space-x-4 > * + * {
margin-left: 1rem;
}
/* Typography */
h1,
h2,
h3 {
font-weight: bold;
line-height: 1.2;
}
.text-3xl {
font-size: 1.875rem;
}
.text-2xl {
font-size: 1.5rem;
}
.text-xl {
font-size: 1.25rem;
}
.text-lg {
font-size: 1.125rem;
}
.text-sm {
font-size: 0.875rem;
}
.text-xs {
font-size: 0.75rem;
}
.font-bold {
font-weight: 700;
}
.font-semibold {
font-weight: 600;
}
.font-medium {
font-weight: 500;
}
.text-center {
text-align: center;
}
.gradient-text {
background: linear-gradient(to right, var(--primary), var(--accent));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
/* Components */
.glass-card {
background: rgba(17, 24, 39, 0.7);
backdrop-filter: blur(8px);
border: 1px solid var(--border-color);
border-radius: 0.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2);
}
.btn {
display: inline-block;
padding: 0.625rem 1rem;
font-weight: 500;
border-radius: 0.375rem;
transition: all 0.2s ease;
cursor: pointer;
text-align: center;
border: none;
}
.btn-primary {
background-color: var(--primary);
color: white;
}
.btn-primary:hover:not(:disabled) {
background-color: var(--primary-hover);
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.1);
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-secondary {
background-color: var(--secondary);
color: white;
}
.btn-secondary:hover:not(:disabled) {
background-color: var(--secondary-hover);
}
.nav-link {
display: inline-block;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-weight: 600;
font-size: 0.875rem;
transition: all 0.2s ease;
color: var(--text-secondary);
text-decoration: none;
}
.nav-link:hover {
color: white;
background-color: rgba(31, 41, 55, 0.7);
}
.nav-link.active {
background-color: var(--primary);
color: white;
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3);
}
input,
textarea,
select {
width: 100%;
padding: 0.625rem 0.75rem;
background-color: rgba(31, 41, 55, 0.8);
border: 1px solid var(--border-color);
color: white;
border-radius: 0.375rem;
transition: all 0.2s;
}
input:focus,
textarea:focus,
select:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
}
label {
display: block;
margin-bottom: 0.25rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--text-secondary);
}
.alert {
padding: 0.75rem;
border-radius: 0.375rem;
margin-bottom: 1rem;
}
.alert-error {
background-color: rgba(239, 68, 68, 0.2);
border: 1px solid rgba(239, 68, 68, 0.5);
color: white;
}
.alert-success {
background-color: rgba(34, 197, 94, 0.2);
border: 1px solid rgba(34, 197, 94, 0.5);
color: white;
}
/* Navigation */
.navbar {
position: sticky;
top: 0;
z-index: 10;
background-color: rgba(17, 24, 39, 0.8);
backdrop-filter: blur(8px);
border-bottom: 1px solid var(--border-color);
padding: 1rem 0;
margin-bottom: 2rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.navbar-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 42rem;
margin: 0 auto;
padding: 0 1.5rem;
}
.navbar-brand {
color: var(--primary);
font-weight: bold;
font-size: 1.125rem;
margin-right: 2rem;
}
.navbar-links {
display: flex;
gap: 1rem;
}
/* Tables */
table {
width: 100%;
border-collapse: collapse;
}
th {
text-align: left;
padding: 0.75rem 1rem;
font-size: 0.75rem;
text-transform: uppercase;
color: var(--text-secondary);
border-bottom: 1px solid var(--border-color);
}
td {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--border-color);
font-size: 0.875rem;
}
tr:hover {
background-color: rgba(31, 41, 55, 0.3);
}
/* File upload styles */
.file-upload {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 1.5rem;
border: 2px dashed rgba(99, 102, 241, 0.3);
border-radius: 0.5rem;
background-color: rgba(31, 41, 55, 0.3);
cursor: pointer;
transition: all 0.2s;
}
.file-upload:hover {
border-color: var(--primary);
}
/* Footer */
footer {
padding: 1.25rem 0;
border-top: 1px solid var(--border-color);
display: flex;
justify-content: center;
align-items: center;
}
/* Link styles */
a {
color: var(--primary);
text-decoration: none;
transition: color 0.2s;
}
a:hover {
color: var(--primary-hover);
text-decoration: underline;
}
/* Loading state */
.loading-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 50vh;
}
/* Code blocks */
pre {
background-color: rgba(31, 41, 55, 0.8);
padding: 1rem;
border-radius: 0.375rem;
overflow: auto;
font-family: monospace;
border: 1px solid var(--border-color);
font-size: 0.875rem;
color: var(--text-secondary);
}
/* Profile data */
.profile-item {
padding-bottom: 0.75rem;
margin-bottom: 0.75rem;
border-bottom: 1px solid var(--border-color);
}
.profile-item strong {
color: var(--text-secondary);
}
.action-link {
color: var(--primary);
font-weight: 500;
margin-right: 0.75rem;
cursor: pointer;
}
.action-link:hover {
color: var(--primary-hover);
text-decoration: underline;
}
.action-link-danger {
color: var(--error);
}
.action-link-danger:hover {
color: #f05252;
}
/* Icon button */
.icon-button {
background-color: transparent;
color: var(--primary);
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: none;
transition: all 0.2s;
}
.icon-button:hover {
background-color: rgba(99, 102, 241, 0.1);
color: var(--primary-hover);
}
.icon-button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.icon-button svg {
width: 20px;
height: 20px;
}
/* Table action icons */
.table-actions {
display: flex;
gap: 8px;
}
.action-icon {
background-color: transparent;
border: none;
width: 32px;
height: 32px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s;
padding: 0;
}
.action-icon svg {
width: 18px;
height: 18px;
}
.action-icon:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.action-icon-view {
color: var(--primary);
}
.action-icon-view:hover:not(:disabled) {
background-color: rgba(99, 102, 241, 0.1);
color: var(--primary-hover);
}
.action-icon-delete {
color: var(--error);
}
.action-icon-delete:hover:not(:disabled) {
background-color: rgba(239, 68, 68, 0.1);
color: #f05252;
}
/* Tab styles */
.tabs-container {
display: flex;
border-radius: 0.5rem;
overflow: hidden;
margin-bottom: 1.5rem;
border: 1px solid var(--border-color);
}
.tab-button {
flex: 1;
padding: 0.75rem 1rem;
font-weight: 500;
transition: all 0.2s ease;
background-color: rgba(31, 41, 55, 0.5);
color: var(--text-secondary);
}
.tab-button:hover:not(.tab-active) {
background-color: rgba(31, 41, 55, 0.8);
color: var(--text-primary);
}
.tab-button.tab-active {
background-color: var(--primary);
color: white;
box-shadow: 0 0 0 1px rgba(99, 102, 241, 0.3);
}
.tab-button:first-child {
border-top-left-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
}
.tab-button:last-child {
border-top-right-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
}
.tab-content {
margin-top: 1.5rem;
}

View File

@@ -0,0 +1,110 @@
/* eslint-disable */
import type {
DocumentTypeDecoration,
ResultOf,
TypedDocumentNode,
} from "@graphql-typed-document-node/core";
import type { FragmentDefinitionNode } from "graphql";
import type { Incremental } from "./graphql";
export type FragmentType<
TDocumentType extends DocumentTypeDecoration<any, any>,
> = TDocumentType extends DocumentTypeDecoration<infer TType, any>
? [TType] extends [{ " $fragmentName"?: infer TKey }]
? TKey extends string
? { " $fragmentRefs"?: { [key in TKey]: TType } }
: never
: never
: never;
// return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>,
): TType;
// return nullable if `fragmentType` is undefined
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | undefined,
): TType | undefined;
// return nullable if `fragmentType` is nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null,
): TType | null;
// return nullable if `fragmentType` is nullable or undefined
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentTypeDecoration<TType, any>>
| null
| undefined,
): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: Array<FragmentType<DocumentTypeDecoration<TType, any>>>,
): Array<TType>;
// return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| Array<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined,
): Array<TType> | null | undefined;
// return readonly array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>,
): ReadonlyArray<TType>;
// return readonly array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined,
): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>(
_documentNode: DocumentTypeDecoration<TType, any>,
fragmentType:
| FragmentType<DocumentTypeDecoration<TType, any>>
| Array<FragmentType<DocumentTypeDecoration<TType, any>>>
| ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
| null
| undefined,
): TType | Array<TType> | ReadonlyArray<TType> | null | undefined {
return fragmentType as any;
}
export function makeFragmentData<
F extends DocumentTypeDecoration<any, any>,
FT extends ResultOf<F>,
>(data: FT, _fragment: F): FragmentType<F> {
return data as FragmentType<F>;
}
export function isFragmentReady<TQuery, TFrag>(
queryNode: DocumentTypeDecoration<TQuery, any>,
fragmentNode: TypedDocumentNode<TFrag>,
data:
| FragmentType<TypedDocumentNode<Incremental<TFrag>, any>>
| null
| undefined,
): data is FragmentType<typeof fragmentNode> {
const deferredFields = (
queryNode as {
__meta__?: { deferredFields: Record<string, (keyof TFrag)[]> };
}
).__meta__?.deferredFields;
if (!deferredFields) return true;
const fragDef = fragmentNode.definitions[0] as
| FragmentDefinitionNode
| undefined;
const fragName = fragDef?.name?.value;
const fields = (fragName && deferredFields[fragName]) || [];
return fields.length > 0 && fields.every((field) => data && field in data);
}

View File

@@ -0,0 +1,51 @@
/* eslint-disable */
import type { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-node/core";
import * as types from "./graphql";
/**
* Map of all GraphQL operations in the project.
*
* This map has several performance disadvantages:
* 1. It is not tree-shakeable, so it will include all operations in the project.
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle.
* 3. It does not support dead code elimination, so it will add unused operations.
*
* Therefore it is highly recommended to use the babel or swc plugin for production.
* Learn more about it here: https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#reducing-bundle-size
*/
type Documents = {
"query GetNinjaTurtlesWithComments {\n ninjaTurtles {\n id\n name\n description\n createdAt\n updatedAt\n comments {\n id\n comment\n createdAt\n user {\n id\n displayName\n email\n }\n }\n }\n}\n\nmutation AddComment($ninjaTurtleId: uuid!, $comment: String!) {\n insertComment(object: {ninjaTurtleId: $ninjaTurtleId, comment: $comment}) {\n id\n comment\n createdAt\n ninjaTurtleId\n }\n}": typeof types.GetNinjaTurtlesWithCommentsDocument;
};
const documents: Documents = {
"query GetNinjaTurtlesWithComments {\n ninjaTurtles {\n id\n name\n description\n createdAt\n updatedAt\n comments {\n id\n comment\n createdAt\n user {\n id\n displayName\n email\n }\n }\n }\n}\n\nmutation AddComment($ninjaTurtleId: uuid!, $comment: String!) {\n insertComment(object: {ninjaTurtleId: $ninjaTurtleId, comment: $comment}) {\n id\n comment\n createdAt\n ninjaTurtleId\n }\n}":
types.GetNinjaTurtlesWithCommentsDocument,
};
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*
*
* @example
* ```ts
* const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`);
* ```
*
* The query argument is unknown!
* Please regenerate the types.
*/
export function graphql(source: string): unknown;
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(
source: "query GetNinjaTurtlesWithComments {\n ninjaTurtles {\n id\n name\n description\n createdAt\n updatedAt\n comments {\n id\n comment\n createdAt\n user {\n id\n displayName\n email\n }\n }\n }\n}\n\nmutation AddComment($ninjaTurtleId: uuid!, $comment: String!) {\n insertComment(object: {ninjaTurtleId: $ninjaTurtleId, comment: $comment}) {\n id\n comment\n createdAt\n ninjaTurtleId\n }\n}",
): (typeof documents)["query GetNinjaTurtlesWithComments {\n ninjaTurtles {\n id\n name\n description\n createdAt\n updatedAt\n comments {\n id\n comment\n createdAt\n user {\n id\n displayName\n email\n }\n }\n }\n}\n\nmutation AddComment($ninjaTurtleId: uuid!, $comment: String!) {\n insertComment(object: {ninjaTurtleId: $ninjaTurtleId, comment: $comment}) {\n id\n comment\n createdAt\n ninjaTurtleId\n }\n}"];
export function graphql(source: string) {
return (documents as any)[source] ?? {};
}
export type DocumentType<TDocumentNode extends DocumentNode<any, any>> =
TDocumentNode extends DocumentNode<infer TType, any> ? TType : never;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
export * from "./fragment-masking";
export * from "./gql";

View File

@@ -0,0 +1,28 @@
query GetNinjaTurtlesWithComments {
ninjaTurtles {
id
name
description
createdAt
updatedAt
comments {
id
comment
createdAt
user {
id
displayName
email
}
}
}
}
mutation AddComment($ninjaTurtleId: uuid!, $comment: String!) {
insertComment(object: { ninjaTurtleId: $ninjaTurtleId, comment: $comment }) {
id
comment
createdAt
ninjaTurtleId
}
}

View File

@@ -0,0 +1,175 @@
import { createClient, type NhostClient } from "@nhost/nhost-js";
import type { Session } from "@nhost/nhost-js/auth";
import {
createContext,
type ReactNode,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "react";
/**
* Authentication context interface providing access to user session state and Nhost client.
* Used throughout the React application to access authentication-related data and operations.
*/
interface AuthContextType {
/** Current authenticated user object, null if not authenticated */
user: Session["user"] | null;
/** Current session object containing tokens and user data, null if no active session */
session: Session | null;
/** Boolean indicating if user is currently authenticated */
isAuthenticated: boolean;
/** Boolean indicating if authentication state is still loading */
isLoading: boolean;
/** Nhost client instance for making authenticated requests */
nhost: NhostClient;
}
// Create React context for authentication state and nhost client
const AuthContext = createContext<AuthContextType | null>(null);
interface AuthProviderProps {
children: ReactNode;
}
/**
* AuthProvider component that provides authentication context to the React application.
*
* This component handles:
* - Initializing the Nhost client with default EventEmitterStorage
* - Managing authentication state (user, session, loading, authenticated status)
* - Cross-tab session synchronization using sessionStorage.onChange events
* - Page visibility and focus event handling to maintain session consistency
* - Client-side only session management (no server-side rendering)
*/
export const AuthProvider = ({ children }: AuthProviderProps) => {
const [user, setUser] = useState<Session["user"] | null>(null);
const [session, setSession] = useState<Session | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
const lastRefreshTokenIdRef = useRef<string | null>(null);
// Initialize Nhost client with default SessionStorage (local storage)
const nhost = useMemo(
() =>
createClient({
region: import.meta.env.VITE_NHOST_REGION || "local",
subdomain: import.meta.env.VITE_NHOST_SUBDOMAIN || "local",
}),
[],
);
/**
* Handles session reload when refresh token changes.
* This detects when the session has been updated from other tabs.
* Unlike the Next.js version, this only updates local state without server synchronization.
*
* @param currentRefreshTokenId - The current refresh token ID to compare against stored value
*/
const reloadSession = useCallback(
(currentRefreshTokenId: string | null) => {
if (currentRefreshTokenId !== lastRefreshTokenIdRef.current) {
lastRefreshTokenIdRef.current = currentRefreshTokenId;
// Update local authentication state to match current session
const currentSession = nhost.getUserSession();
setUser(currentSession?.user || null);
setSession(currentSession);
setIsAuthenticated(!!currentSession);
}
},
[nhost],
);
// Initialize authentication state and set up cross-tab session synchronization
useEffect(() => {
setIsLoading(true);
// Load initial session state from Nhost client
const currentSession = nhost.getUserSession();
setUser(currentSession?.user || null);
setSession(currentSession);
setIsAuthenticated(!!currentSession);
lastRefreshTokenIdRef.current = currentSession?.refreshTokenId ?? null;
setIsLoading(false);
// Subscribe to session changes from other browser tabs
// This enables real-time synchronization when user signs in/out in another tab
const unsubscribe = nhost.sessionStorage.onChange((session) => {
reloadSession(session?.refreshTokenId ?? null);
});
return unsubscribe;
}, [nhost, reloadSession]);
// Handle session changes from page focus events (for additional session consistency)
useEffect(() => {
/**
* Checks for session changes when page becomes visible or focused.
* In the React SPA context, this provides additional consistency checks
* though it's less critical than in the Next.js SSR version.
*/
const checkSessionOnFocus = () => {
reloadSession(nhost.getUserSession()?.refreshTokenId ?? null);
};
// Monitor page visibility changes (tab switching, window minimizing)
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
checkSessionOnFocus();
}
});
// Monitor window focus events (clicking back into the browser window)
window.addEventListener("focus", checkSessionOnFocus);
// Cleanup event listeners on component unmount
return () => {
document.removeEventListener("visibilitychange", checkSessionOnFocus);
window.removeEventListener("focus", checkSessionOnFocus);
};
}, [nhost, reloadSession]);
const value: AuthContextType = {
user,
session,
isAuthenticated,
isLoading,
nhost,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
/**
* Custom hook to access the authentication context.
*
* Must be used within a component wrapped by AuthProvider.
* Provides access to current user session, authentication state, and Nhost client.
*
* @throws {Error} When used outside of AuthProvider
* @returns {AuthContextType} Authentication context containing user, session, and client
*
* @example
* ```tsx
* function MyComponent() {
* const { user, isAuthenticated, nhost } = useAuth();
*
* if (!isAuthenticated) {
* return <div>Please sign in</div>;
* }
*
* return <div>Welcome, {user?.displayName}!</div>;
* }
* ```
*/
export const useAuth = (): AuthContextType => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth must be used within an AuthProvider");
}
return context;
};

View File

@@ -0,0 +1,19 @@
import React from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App";
import { AuthProvider } from "./lib/nhost/AuthProvider";
// Root component that sets up providers
const Root = () => (
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>
);
const rootElement = document.getElementById("root");
if (!rootElement) throw new Error("Root element not found");
createRoot(rootElement).render(<Root />);

View File

@@ -0,0 +1,217 @@
/* Custom styles for Ninja Turtles tabs interface */
.ninja-turtles-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.ninja-turtles-title {
text-align: center;
margin-bottom: 25px;
color: #1a9c44;
text-transform: uppercase;
letter-spacing: 1px;
}
/* Tab navigation */
.turtle-tabs {
display: flex;
border-bottom: 2px solid #1a9c44;
margin-bottom: 20px;
overflow-x: auto;
}
.turtle-tab {
padding: 10px 20px;
margin-right: 5px;
background: none;
border: none;
cursor: pointer;
font-weight: 600;
color: var(--text-secondary);
transition: all 0.3s ease;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
position: relative;
outline: none;
}
.turtle-tab:hover {
color: var(--text-primary);
background: rgba(26, 156, 68, 0.1);
}
.turtle-tab.active {
color: white;
background: #1a9c44;
}
/* Turtle Card Styles */
.turtle-card {
border-radius: 8px;
overflow: hidden;
transition: all 0.3s ease;
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.turtle-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.turtle-name {
color: #1a9c44;
font-weight: 700;
}
.turtle-description {
margin-bottom: 20px;
line-height: 1.6;
}
.turtle-date {
font-size: 0.85rem;
margin-bottom: 20px;
color: var(--text-muted);
}
/* Comments section */
.comments-section {
margin-top: 25px;
border-top: 1px solid var(--border-color);
padding-top: 15px;
}
.comments-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 15px;
color: #1a9c44;
}
.comment-card {
margin-bottom: 15px;
padding: 12px;
border-radius: 6px;
background-color: rgba(26, 156, 68, 0.05);
border: 1px solid rgba(26, 156, 68, 0.1);
}
.comment-text {
margin-bottom: 8px;
}
.comment-meta {
display: flex;
align-items: center;
font-size: 0.8rem;
color: var(--text-muted);
}
.comment-avatar {
width: 24px;
height: 24px;
border-radius: 50%;
background-color: #1a9c44;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
margin-right: 8px;
}
/* Comment form */
.comment-form {
margin-top: 20px;
}
.comment-textarea {
width: 100%;
background-color: rgba(31, 41, 55, 0.8);
border: 1px solid var(--border-color);
border-radius: 6px;
padding: 10px;
color: white;
transition: all 0.2s;
margin-bottom: 10px;
}
.comment-textarea:focus {
border-color: #1a9c44;
box-shadow: 0 0 0 2px rgba(26, 156, 68, 0.2);
outline: none;
}
.comment-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
.cancel-button {
background-color: transparent;
border: 1px solid var(--border-color);
color: var(--text-secondary);
}
.cancel-button:hover {
background-color: rgba(31, 41, 55, 0.8);
}
.submit-button {
background-color: #1a9c44;
color: white;
}
.submit-button:hover {
background-color: #148035;
}
.add-comment-button {
display: inline-flex;
align-items: center;
color: #1a9c44;
background: none;
border: none;
padding: 5px 0;
font-size: 0.9rem;
cursor: pointer;
transition: all 0.2s;
}
.add-comment-button:hover {
color: #148035;
text-decoration: underline;
}
.add-comment-button svg {
width: 14px;
height: 14px;
margin-right: 5px;
}
/* Responsive adjustments */
@media (max-width: 640px) {
.turtle-tabs {
flex-wrap: nowrap;
overflow-x: auto;
}
.turtle-tab {
flex: 0 0 auto;
}
}

View File

@@ -0,0 +1,237 @@
import { type JSX, useCallback, useEffect, useState } from "react";
import {
AddCommentDocument,
GetNinjaTurtlesWithCommentsDocument,
type GetNinjaTurtlesWithCommentsQuery,
} from "../lib/graphql/__generated__/graphql";
import { useAuth } from "../lib/nhost/AuthProvider";
import "./Home.css";
export default function Home(): JSX.Element {
const { isLoading, nhost } = useAuth();
const [activeCommentId, setActiveCommentId] = useState<string | null>(null);
const [commentText, setCommentText] = useState("");
const [activeTabId, setActiveTabId] = useState<string | null>(null);
const [data, setData] = useState<GetNinjaTurtlesWithCommentsQuery | null>(
null,
);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
// Fetch ninja turtles data
const fetchNinjaTurtles = useCallback(async () => {
setLoading(true);
setError(null);
try {
const result = await nhost.graphql.request(
GetNinjaTurtlesWithCommentsDocument,
{},
);
if (result.body.errors) {
throw new Error(result.body.errors[0]?.message);
}
setData(result.body.data ?? null);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
}, [nhost.graphql]);
// Load data on mount
useEffect(() => {
if (!isLoading) {
fetchNinjaTurtles();
}
}, [isLoading, fetchNinjaTurtles]);
const addComment = async (ninjaTurtleId: string, comment: string) => {
try {
const result = await nhost.graphql.request(AddCommentDocument, {
ninjaTurtleId,
comment,
});
if (result.body.errors) {
throw new Error(result.body.errors[0]?.message);
}
// Clear form and refetch data
setCommentText("");
setActiveCommentId(null);
await fetchNinjaTurtles();
} catch (err) {
console.error("Error adding comment:", err);
}
};
// If authentication is still loading, show a loading state
if (isLoading) {
return (
<div className="loading-container">
<p>Loading...</p>
</div>
);
}
const handleAddComment = (turtleId: string) => {
if (!commentText.trim()) return;
addComment(turtleId, commentText);
};
if (loading)
return (
<div className="loading-container">
<p>Loading ninja turtles...</p>
</div>
);
if (error)
return (
<div className="alert alert-error">
Error loading ninja turtles: {(error as Error).message}
</div>
);
// Access the data using the correct field name from the GraphQL response
const ninjaTurtles = data?.ninjaTurtles || [];
if (!ninjaTurtles || ninjaTurtles.length === 0) {
return (
<div className="no-turtles-container">
<p>No ninja turtles found. Please add some!</p>
</div>
);
}
// Set the active tab to the first turtle if there's no active tab and there are turtles
if (activeTabId === null) {
setActiveTabId(ninjaTurtles[0] ? ninjaTurtles[0].id : null);
}
const formatDate = (dateString: string) => {
const date = new Date(dateString);
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
};
return (
<div className="ninja-turtles-container">
<h1 className="ninja-turtles-title text-3xl font-bold mb-6">
Teenage Mutant Ninja Turtles
</h1>
{/* Tabs navigation */}
<div className="turtle-tabs">
{ninjaTurtles.map((turtle) => (
<button
key={turtle.id}
type="button"
className={`turtle-tab ${activeTabId === turtle.id ? "active" : ""}`}
onClick={() => setActiveTabId(turtle.id)}
>
{turtle.name}
</button>
))}
</div>
{/* Display active turtle */}
{ninjaTurtles
.filter((turtle) => turtle.id === activeTabId)
.map((turtle) => (
<div key={turtle.id} className="turtle-card glass-card p-6">
<div className="turtle-header">
<h2 className="turtle-name text-2xl font-semibold">
{turtle.name}
</h2>
</div>
<p className="turtle-description">{turtle.description}</p>
<div className="turtle-date">
Added on {formatDate(turtle.createdAt || turtle.createdAt)}
</div>
<div className="comments-section">
<h3 className="comments-title">
Comments ({turtle.comments.length})
</h3>
{turtle.comments.map((comment) => (
<div key={comment.id} className="comment-card">
<p className="comment-text">{comment.comment}</p>
<div className="comment-meta">
<div className="comment-avatar">
{(comment.user?.displayName || comment.user?.email || "?")
.charAt(0)
.toUpperCase()}
</div>
<p>
{comment.user?.displayName ||
comment.user?.email ||
"Anonymous"}{" "}
- {formatDate(comment.createdAt || comment.createdAt)}
</p>
</div>
</div>
))}
{activeCommentId === turtle.id ? (
<div className="comment-form">
<textarea
className="comment-textarea"
value={commentText}
onChange={(e) => setCommentText(e.target.value)}
placeholder="Add your comment..."
rows={3}
/>
<div className="comment-actions">
<button
type="button"
onClick={() => {
setActiveCommentId(null);
setCommentText("");
}}
className="btn cancel-button"
>
Cancel
</button>
<button
type="button"
onClick={() => handleAddComment(turtle.id)}
className="btn submit-button"
>
Submit
</button>
</div>
</div>
) : (
<button
type="button"
onClick={() => setActiveCommentId(turtle.id)}
className="add-comment-button"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
aria-label="Add Comment"
role="img"
>
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
Add a comment
</button>
)}
</div>
</div>
))}
</div>
);
}

View File

@@ -0,0 +1,66 @@
import type { JSX } from "react";
import { useAuth } from "../lib/nhost/AuthProvider";
export default function Profile(): JSX.Element {
const { user, session } = useAuth();
// ProtectedRoute component now handles authentication check
// We can just focus on the component logic here
return (
<div className="flex flex-col">
<h1 className="text-3xl mb-6 gradient-text">Your Profile</h1>
<div className="glass-card p-8 mb-6">
<div className="space-y-5">
<div className="profile-item">
<strong>Display Name:</strong>
<span className="ml-2">{user?.displayName || "Not set"}</span>
</div>
<div className="profile-item">
<strong>Email:</strong>
<span className="ml-2">{user?.email || "Not available"}</span>
</div>
<div className="profile-item">
<strong>User ID:</strong>
<span
className="ml-2"
style={{
fontFamily: "var(--font-geist-mono)",
fontSize: "0.875rem",
}}
>
{user?.id || "Not available"}
</span>
</div>
<div className="profile-item">
<strong>Roles:</strong>
<span className="ml-2">{user?.roles?.join(", ") || "None"}</span>
</div>
<div className="profile-item">
<strong>Email Verified:</strong>
<span className="ml-2">{user?.emailVerified ? "Yes" : "No"}</span>
</div>
</div>
</div>
<div className="glass-card p-8 mb-6">
<h3 className="text-xl mb-4">Session Information</h3>
<pre>
{JSON.stringify(
{
refreshTokenId: session?.refreshTokenId,
accessTokenExpiresIn: session?.accessTokenExpiresIn,
},
null,
2,
)}
</pre>
</div>
</div>
);
}

View File

@@ -0,0 +1,120 @@
import type { ErrorResponse } from "@nhost/nhost-js/auth";
import type { FetchError } from "@nhost/nhost-js/fetch";
import { type JSX, useEffect, useId, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { useAuth } from "../lib/nhost/AuthProvider";
export default function SignIn(): JSX.Element {
const { nhost, isAuthenticated } = useAuth();
const navigate = useNavigate();
const location = useLocation();
const params = new URLSearchParams(location.search);
const emailId = useId();
const passwordId = useId();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(
params.get("error") || null,
);
const isVerifying = params.has("fromVerify");
// Use useEffect for navigation after authentication is confirmed
useEffect(() => {
if (isAuthenticated && !isVerifying) {
navigate("/home");
}
}, [isAuthenticated, isVerifying, navigate]);
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsLoading(true);
setError(null);
try {
// Use the signIn function from auth context
const response = await nhost.auth.signInEmailPassword({
email,
password,
});
// Check if MFA is required
if (response.body?.mfa) {
navigate(`/signin/mfa?ticket=${response.body.mfa.ticket}`);
return;
}
// If we have a session, sign in was successful
if (response.body?.session) {
navigate("/home");
} else {
setError("Failed to sign in");
}
} catch (err) {
const error = err as FetchError<ErrorResponse>;
setError(`An error occurred during sign in: ${error.message}`);
} finally {
setIsLoading(false);
}
};
return (
<div className="flex flex-col items-center justify-center">
<h1 className="text-3xl mb-6 gradient-text">Nhost SDK Demo</h1>
<div className="glass-card w-full p-8 mb-6">
<h2 className="text-2xl mb-6">Sign In</h2>
<div>
<div className="tabs-container">
<button type="button" className="tab-button tab-active">
Email + Password
</button>
</div>
<div className="tab-content">
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label htmlFor={emailId}>Email</label>
<input
id={emailId}
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div>
<label htmlFor={passwordId}>Password</label>
<input
id={passwordId}
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
{error && <div className="alert alert-error">{error}</div>}
<button
type="submit"
className="btn btn-primary w-full"
disabled={isLoading}
>
{isLoading ? "Signing In..." : "Sign In"}
</button>
</form>
</div>
</div>
</div>
<div className="mt-4">
<p>
Don&apos;t have an account? <Link to="/signup">Sign Up</Link>
</p>
</div>
</div>
);
}

View File

@@ -0,0 +1,127 @@
import type { ErrorResponse } from "@nhost/nhost-js/auth";
import type { FetchError } from "@nhost/nhost-js/fetch";
import { type JSX, useId, useState } from "react";
import { Link, Navigate, useNavigate } from "react-router-dom";
import { useAuth } from "../lib/nhost/AuthProvider";
export default function SignUp(): JSX.Element {
const { nhost, isAuthenticated } = useAuth();
const navigate = useNavigate();
const displayNameId = useId();
const emailId = useId();
const passwordId = useId();
const [email, setEmail] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [displayName, setDisplayName] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
// If already authenticated, redirect to profile
if (isAuthenticated) {
return <Navigate to="/home" />;
}
const handleSubmit = async (
e: React.FormEvent<HTMLFormElement>,
): Promise<void> => {
e.preventDefault();
setIsLoading(true);
setError(null);
try {
const response = await nhost.auth.signUpEmailPassword({
email,
password,
options: {
displayName,
},
});
if (response.body) {
// Successfully signed up and automatically signed in
navigate("/home");
} else {
// Verification email sent
navigate("/verify");
}
} catch (err) {
const error = err as FetchError<ErrorResponse>;
setError(`An error occurred during sign up: ${error.message}`);
} finally {
setIsLoading(false);
}
};
return (
<div className="flex flex-col items-center justify-center">
<h1 className="text-3xl mb-6 gradient-text">Nhost SDK Demo</h1>
<div className="glass-card w-full p-8 mb-6">
<h2 className="text-2xl mb-6">Sign Up</h2>
<div>
<div className="tabs-container">
<button type="button" className="tab-button tab-active">
Email + Password
</button>
</div>
<div className="tab-content">
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label htmlFor={displayNameId}>Display Name</label>
<input
id={displayNameId}
type="text"
value={displayName}
onChange={(e) => setDisplayName(e.target.value)}
/>
</div>
<div>
<label htmlFor={emailId}>Email</label>
<input
id={emailId}
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<div>
<label htmlFor={passwordId}>Password</label>
<input
id={passwordId}
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<p className="text-xs mt-1 text-gray-400">
Password must be at least 8 characters long
</p>
</div>
{error && <div className="alert alert-error">{error}</div>}
<button
type="submit"
className="btn btn-primary w-full"
disabled={isLoading}
>
{isLoading ? "Signing Up..." : "Sign Up"}
</button>
</form>
</div>
</div>
</div>
<div className="mt-4">
<p>
Already have an account? <Link to="/signin">Sign In</Link>
</p>
</div>
</div>
);
}

View File

@@ -0,0 +1,11 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_NHOST_REGION: string | undefined;
readonly VITE_NHOST_SUBDOMAIN: string | undefined;
readonly VITE_ENV: string | undefined;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}

View File

@@ -0,0 +1,6 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../../../build/configs/tsconfig/frontend.json",
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -0,0 +1,4 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../../../build/configs/tsconfig/vite.json"
}

View File

@@ -0,0 +1,7 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -17,6 +17,8 @@ let
"pnpm-lock.yaml"
"${submodule}/package.json"
"${submodule}/pnpm-lock.yaml"
"${submodule}/codegen-nhost/package.json"
"${submodule}/codegen-nhost/pnpm-lock.yaml"
"${submodule}/react-apollo/package.json"
"${submodule}/react-apollo/pnpm-lock.yaml"
"${submodule}/react-query/package.json"

View File

@@ -1,5 +1,5 @@
{
"name": "demos/react-apollo",
"name": "guides/react-apollo",
"private": true,
"version": "0.0.0",
"type": "module",

View File

@@ -1,5 +1,5 @@
{
"name": "demos/react-query",
"name": "guides/react-query",
"private": true,
"version": "0.0.0",
"type": "module",

View File

@@ -1,5 +1,5 @@
{
"name": "demos/react-urql",
"name": "guides/react-urql",
"private": true,
"version": "0.0.0",
"type": "module",

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

@@ -1,3 +1,9 @@
## [storage@0.10.0] - 2025-11-19
### 🚀 Features
- *(storage)* Added support for images/heic (#3694)
## [storage@0.9.1] - 2025-11-06
### 🐛 Bug Fixes

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);

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