Graphics Library
================

The external graphics library is a complement to the types in the [standard
library](md:/Library_Reference/Standard_Library/Graphics). It provides the ability to load and save
images from a number of common file formats.

The graphics library is located in the package `graphics`, and entirely implemented in a single
shared library. Since this is an external library, it does not need to be distributed alongside
applications where it is not needed.

The library provides a convenient API for common operations. This API consists of the following
functions:

- [stormname:graphics.loadImage(core.io.IStream)]

  Load an image from a [stormname:core.io.IStream]. The function inspects the first few bytes of the
  image to determine its format. For this reason, the stream needs to support peeking around 10
  bytes from the current location and onwards.

  Throws an [stormname:graphics.ImageLoadError] on failure.

- [stormname:graphics.loadImage(core.io.Url)]

  Wrapper to load a file from an `Url`. Equivalent to calling `loadImage(file.read())`, but checks
  that the file exists before attempting to open it in order to generate better error messages.

- [stormname:graphics.saveImage(graphics.Image, core.io.Url)]

  Save an image to a file. The library uses the extension of the file name to select an appropriate
  decoder and save the file.


The library also provides a more advanced API for more control over the process. This API centers
around the type [stormname:graphics.ImageFormat], which represents an image format. You can then
call the `options` member to create an [stormname:graphics.FormatOptions] instance that lets you
either load a file and inspect the settings used to compress the file, or to set the settings and
then save an image using those.

The library has the following functions for listing image formats:

- [stormname:graphics.supportedImageFormats]

  This function returns an array of all supported image formats. This makes it possible to enumerate
  all currently supported formats, for example to use in a file selection dialog.

- [stormname:graphics.registerImageFormat(graphics.ImageFormat)]

  Allows registering custom image formats with the library so that other parts of the system may use
  them.

- [stormname:graphics.findFormat(core.io.IStream)]

  Select a format that can decompress the image in the stream by inspecting its header. This is what
  `loadImage` described above uses to decompress images.

- [stormname:graphics.findFormat(core.Str)]

  Select a format that is suitable for the file extension (case insensitive) passed to the function.
  This is what `saveImage` above uses.



On Linux, the graphics library uses `libpng` for decoding PNG images, and `libjpegturbo` for JPEG
images. On Windows, the Windows Imaging API is used. BMP, PPM, and ICO use custom implementations that
support the most common image types. For example, this means that compressed BMP formats will not
work.


Loading Icons
-------------

At the moment, the `ico` file format is the only supported format that may contain more than one
image. When an `ico` file is loaded using `loadImage`, the highest resolution version is picked by
default. If you wish to access all versions of the image, use `loadImageSet` instead of `loadImage`
and `loadSet` instead of `load`.

For convenience, the graphics library also provides a
[reader](md://Language_Reference/Storm/Packages_and_Files) for `ico` files. As such, it is possible
to place `ico` files in a package, and the Graphics library will load it for you automatically. The
icon will be placed in the name tree in the form of a function that returns an
[stormname:graphics.ImageSet] that represents the icon. The function will create a copy of the
image, so you are free to modify it if you wish.
