Osy#betaa language · its runtime Osyrin · a hosted platform
Why Osy#Built for agentsAgents as declarationsWorkflows that waitRuns exactly onceSecure by defaultNothing to mockThe editor is the compilerUI in the languageDocuments are dataOne program

Reference / Storage

Image.Thumbnail, Resize and Convert (a stored image, transformed)

using Osysharp.Images; · FileAsset Image.Thumbnail(FileAsset source, int max) · Image.Resize(source, w, h) · Image.Convert(source, mime)

Three server-side transforms over a stored image, each answering a NEW `FileAsset`: `Thumbnail` fits the image within `max` pixels on its longest side (aspect kept, JPEG), `Resize` makes it exactly `w`×`h` in its own format, `Convert` re-encodes the same pixels to another format. Nothing is generated on upload; you make a variant when you ask for one, and it is stored and quota-counted like any other file. Show one with `Image(fileAsset: variant.Id)`.

preview1 example compiled by CIstoragefilesimagesstdlib

Summary#

Image.* is a standard-library surface, like Http.*, that a capability gates: using Osysharp.Images; is what makes it resolvable, and the capability declares no table of its own because every op consumes a FileAsset and produces one. The result is a new file — grantable, counted against the app's storage quota, and deduplicated by content, so asking twice for the same thumbnail stores it once.

A FileAsset is a ROW and carries no path, so File.Url and File.SignedUrl — whose argument is an app-relative path — cannot address one. To put a variant on a page, give the element the row: Image(fileAsset: thumb.Id). See Showing a picture on a page.

Nothing runs at upload time. A photograph, a chosen file (see upload) or a capture (see camera and microphone) is stored as it arrived; the variant exists the moment your code asks for it, in the same unit of work.

Signature#

using Osysharp.Images;      // gates the surface; the results are Osysharp.Storage.FileAsset, so that capability is in play too

FileAsset small = Image.Thumbnail(source, 128);          // fit within 128 px on the longest side, aspect kept, JPEG
FileAsset exact = Image.Resize(source, 800, 600);        // exactly 800×600, in the source's own format
FileAsset png   = Image.Convert(source, "image/png");    // the same pixels, re-encoded

Description#

The three ops#

OpAnswersFormat
Image.Thumbnail(source, max)the image scaled to fit within max px on its longest side, aspect preservedJPEG
Image.Resize(source, w, h)the image at exactly w×hthe source's
Image.Convert(source, mime)the same pixelsthe mime you name

Each is a call that leaves the function's own process — a server-side transform — so inside a workflow it is its own durable step, the same as any other outside effect.

What can go wrong#

The source must be a stored image with bytes: a missing asset, an empty one, or a file that is not a decodable image throws. The new bytes count against the app's storage quota; when they would exceed it the write is refused with the storage budget's own exception, exactly as an upload would be. Both are ordinary exceptions to catch where the page has something sensible to show instead.

The thumbnail on a list#

The shape every app with an image on a row ends up writing — one function, called when the row is drawn:

using Osysharp.Storage;
using Osysharp.Images;

entity Receipt {
  [Required, MaxLength(140)] string Merchant;
  FileAsset? Photo;
  security { allow read, create, update when IsAuthenticated || IsAnonymous; }
}

FileAsset Thumbnail(FileAsset source) {
  return Image.Thumbnail(source, 128);
}

demo/file-manager is the same one-liner in a whole app (model/functions.osy). What it puts on the page is Image(fileAsset: f.Id, alt: f.Name, w: 30) — a row is a row, whether it is the original or a variant, and the asset's own security decides who is served the bytes: a file that belongs to one person is refused to everyone else without the page doing anything about it.

Examples#

Two variants of one upload, both stored, both addressed by their own id:

FileAsset thumb = Image.Thumbnail(item.Photo, 128);   // in a function — an Image.* op is an effect
FileAsset web   = Image.Resize(item.Photo, 1200, 800);

…and each is shown by its own row, never by a URL the app builds:

Image(fileAsset: item.Thumb.Id, alt: item.Merchant, w: 128)

See also#

Related

Files (addressing something the app stores)

The platform stores a file two ways, and which one you hold decides how you address it. A PATH-keyed file lives at an…

Showing a picture on a page

`Image` is the element that shows a picture, and it addresses one of two ways. `src` takes a URL — for a file in the…

File.Url

Turns an app-relative file path into the public URL a browser can fetch it from — `File.Url("public/x.png")` returns…

File.SignedUrl

Mints a temporary, signed URL that lets an authorized browser fetch a PRIVATE app file — one stored outside `public/` —…

upload

`Upload(onUploaded: Ingest) { … }` is a file picker wearing whatever you put inside it. When someone chooses a file its…

camera and microphone

Take a photograph, record a video, or record audio. `Camera.Start()` asks for the device and `Camera()` shows the…