# FastImage for Ruby image metadata without full downloads

> FastImage is a Ruby library that determines image dimensions, formats, orientation, and available content length from remote URIs, local files, or readable objects. It parses supported formats directly and avoids dependencies on ImageMagick or FreeImage, though some TIFF files require substantially more data.

**sdsykes/fastimage** — FastImage finds the size or type of an image given its uri by fetching as little as needed

- Repository: https://github.com/sdsykes/fastimage
- Website: http://github.com/sdsykes/fastimage/tree/master
- Stars: 1,382 · Forks: 118
- Language: Ruby
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/sdsykes-fastimage

## Why FastImage avoids transferring complete images

FastImage addresses a narrow but common Ruby application problem: an application needs metadata from an image before it has downloaded the image itself. The dimensions might be needed for an image tag, layout reservation, overlay placement, or another server-side decision. If the asset is remote, downloading the entire file only to read its width and height creates avoidable network and memory costs.

The library targets GIF, JPEG, PNG, TIFF, BMP, ICO, CUR, PSD, SVG, WEBP, and JXL. For common formats, the relevant information is stored near the beginning of the file. JPEG requires a more involved scan of its metadata, but the README still states that FastImage can obtain the size without fetching much of the image. This is metadata inspection rather than image decoding, so FastImage does not need RMagick, which depends on ImageMagick or GraphicsMagick, or ImageScience, which depends on FreeImage.

The intended users are Ruby applications handling images hosted on asset servers, cloud storage, or another remote service. The same interface also accepts local paths and any object that responds to `read`, which makes it applicable when an image is already available through an IO-like object. FastImage is not a replacement for rendering, resizing, color conversion, or validating the visual contents of an image. Its scope is identifying image properties from headers or other available metadata.

## FastImage's URI, file, and IO input flow

FastImage first interprets its input according to URI parsing rules. Anything that cannot be parsed as a URI is treated as a filename and opened with `File#open`. Passing an IO object instead causes the library to read from that object through its `read` method. Data URIs are also recognized, so an encoded image can be inspected without first writing it to disk.

For HTTP inputs, the library follows up to four redirects. Requests can use the `http_proxy` environment setting or an explicit `:proxy` value. A caller can limit the request time with `:timeout`, and servers that require particular request headers can receive them through `:http_header`. These controls matter because image metadata requests still interact with remote systems. They are not metadata-only operations in the sense of making no network request, they are operations designed to fetch only the bytes needed by the format parser.

FastImage returns `nil` when an error prevents a successful result. Passing `:raise_on_failure => true` changes that policy by raising an exception. The examples distinguish fetch failures from images whose dimensions cannot be found, such as a faulty JPEG that raises `FastImage::SizeNotFound` when exception mode is enabled. For JPEG and TIFF files carrying Exif orientation information, an instance can expose the parsed orientation through `orientation`. An instance can also expose the HTTP `content_length` header, although FastImage warns that this field is absent from chunked responses and should not be treated as a universal file-size value.

## Installing FastImage and reading the first remote image

The gem can be installed directly into the current Ruby environment with the command documented by the README. It should report that `fastimage` was installed.

```sh
gem install fastimage
```

In a Bundler-managed application, declare the gem in the `Gemfile`. Bundler then makes it available to the application when dependencies are installed.

```ruby
gem 'fastimage'
```

Require the library and call `FastImage.size` with an image URI. The return value is a two-element array containing width and height. The README's example image is a GIF reported as `[196, 283]`.

```ruby
require 'fastimage'

FastImage.size("https://switchstep.com/images/ios.gif")
# => [196, 283]
```

Use `FastImage.type` when the format is the required property. It returns a symbol such as `:png` rather than a width and height pair.

```ruby
FastImage.type("http://switchstep.com/images/ss_logo.png")
# => :png
```

Local files follow the same metadata API. Because the argument cannot be parsed as a URI, FastImage interprets the string as a filename.

```ruby
FastImage.type("/some/local/file.gif")
# => :gif
```

An already-open IO can be passed directly, avoiding FastImage's filename interpretation path.

```ruby
File.open("/some/local/file.gif", "r") {|io| FastImage.type(io)}
# => :gif
```

The README's compatibility section states that FastImage requires Ruby 1.9.2 or later. Its visible text does not document support for newer Ruby releases beyond that minimum, so compatibility with the application's actual Ruby runtime is an adoption check rather than an assumption.

## Redirects, headers, timeouts, and failure handling

FastImage exposes several options because metadata inspection can encounter the same operational problems as any remote request. Redirects are followed up to four levels, which covers short HTTP redirect chains without allowing the request process to continue indefinitely. The documented timeout is expressed in seconds.

The `:http_header` option can supply a user agent or referrer when a server requires one. This is particularly relevant for image URLs that are not freely retrievable without request metadata. The library can also honor `http_proxy` from the environment or accept a `:proxy` argument for a specific call.

Error handling requires an explicit application decision. The default behavior returns `nil`, which is convenient in code that treats unknown dimensions as optional. It can also hide operational problems if the application does not distinguish a missing image from malformed metadata. Exception mode makes that failure visible.

```ruby
FastImage.size("http://switchstep.com/images/faulty.jpg", :raise_on_failure=>true)
# raises FastImage::SizeNotFound
```

A short timeout can protect a request path from waiting too long, but it may also be too aggressive for a remote server or network path. The README contrasts `0.01` seconds with `2` seconds for a `favicon.ico` example. The former produces `FastImage::ImageFetchFailure` in the documented example, while the latter returns `[16, 16]`.

FastImage also warns callers to sanitize input strings because it attempts to read whatever is supplied. In an application that accepts user-controlled image locations, URI handling and access-control design remain separate concerns that the library does not remove from the application.

## Content length and Exif orientation are separate metadata paths

Image size and transferred resource size are related but distinct concepts in FastImage. `FastImage.size` parses dimensions from image data. The `content_length` reader instead exposes the value supplied by the HTTP `content length` header. In the README example, `FastImage.new("http://switchstep.com/images/ss_logo.png").content_length` returns `4679`.

That header should not be used as the sole source for expected file size because it may be missing when the response uses chunked transfer encoding. It can still be useful when present, especially for assessing transfer size before fetching, but the README does not define it as a reliable measurement in every response mode.

Orientation is another parser feature rather than part of the basic width and height tuple. FastImage reads parsed display orientation from Exif data in JPEG or TIFF files.

```ruby
FastImage.new("http://switchstep.com/images/ExifOrientation3.jpg").orientation
# => 3
```

This distinction matters to applications that render or transform images. Width and height alone do not necessarily describe how an Exif-oriented image should be displayed. FastImage exposes the orientation value, but the README does not claim that the library applies rotation or produces a display-corrected dimension pair.

## TIFF metadata placement limits FastImage's speed advantage

The README's benchmark examples contrast FastImage with `URI.open`, which fetches the complete file. For common image types, the reported gap is large: a JPEG example gives `[9545, 6623]` and shows total times of `0.808131` for the full fetch and `0.162021` for FastImage. A second TIFF example gives `[12805, 10204]` and reports `19.925270` versus `0.100592`.

Those figures are examples from the project's README, not a general performance guarantee. Network location, server behavior, image layout, and Ruby runtime can all change the result. FastImage should therefore be evaluated against the exact asset server and file characteristics involved in an application.

The documented limitation is particularly clear for TIFF. Some TIFF files place metadata far from the start, reducing the amount FastImage can avoid transferring. The README reports a `[22841, 19404]` result with total times of `3.053605` for the full fetch and `2.880414` for FastImage. The conclusion is direct: FastImage's partial-fetch strategy works best when relevant metadata appears early.

The README also points to `image_size` for this case. It describes `image_size` as having an experimental optimization that fetches only the needed HTTP data range. That is a different implementation strategy for remote metadata lookup, particularly relevant to TIFF files with distant metadata. FastImage remains the simpler documented choice for the broad format list and local or IO inputs, but it is not the faster choice for every remote TIFF layout.

## Maintenance, packaging, and adoption boundaries

The repository is not archived, and its last push was on 2026-08-01. The repository has no GitHub releases, so there is no release history here to establish a version cadence. Maintenance status therefore rests on the repository's activity and packaging information rather than a release schedule.

The project is a Ruby gem with an MIT license. The repository includes `fastimage.gemspec`, `Gemfile`, `Rakefile`, library code under `lib/`, and tests under `test/`. The README documents installation through RubyGems or Bundler. It does not document a native extension, external image-decoder dependency, or a deployment service.

The format list is broad, but the actual parsing behavior still needs application-level verification. Malformed files, unsupported variants, delayed metadata, HTTP redirects beyond the documented limit, missing headers, and servers that resist partial reads can all affect results. The library returns `nil` or raises a FastImage exception depending on `raise_on_failure`, so callers must decide how missing dimensions affect layout, caching, and error reporting.

The MIT license permits use and modification under its terms, but this article does not interpret license obligations. Teams integrating the gem should review `MIT-LICENSE` and the packaged gem version as part of their normal dependency review.

## Conclusion

FastImage fits Ruby applications that need image width, height, type, orientation, or HTTP content length without downloading complete files. It is a poor choice when the server cannot provide partial content, when TIFF metadata lies far into the file, or when callers need broader decoding and transformation support. Before adoption, verify behavior against the image formats and server responses used by the application, especially the supported Ruby version, redirect count, timeout handling, and failure paths.

## FAQ

### What does FastImage do in Ruby?

FastImage finds the dimensions or format of an image from a URI, local filename, Data URI, or readable object. It supports GIF, JPEG, PNG, TIFF, BMP, ICO, CUR, PSD, SVG, WEBP, and JXL without requiring RMagick or ImageScience.

### How do I install and use FastImage?

Install it with `gem install fastimage` or add `gem 'fastimage'` to the Gemfile, then require it with `require 'fastimage'`. Call `FastImage.size()` for a width and height array or `FastImage.type()` for a format symbol.

### Does FastImage download the entire image?

No. The README says FastImage fetches as little as needed for the supported formats. Some TIFF files store metadata farther from the beginning, so the reduction in transfer can be much smaller for those files.

### What happens when FastImage cannot read an image?

By default, an error returns `nil`. Passing `:raise_on_failure=>true` requests an exception instead, such as `FastImage::ImageFetchFailure` for a fetch failure or `FastImage::SizeNotFound` when dimensions cannot be found.

## Sources

- [Issues](https://github.com/sdsykes/fastimage/issues)
- [License: MIT](https://github.com/sdsykes/fastimage/blob/master/LICENSE)
- [Project website](http://github.com/sdsykes/fastimage/tree/master)
- [README](https://github.com/sdsykes/fastimage/blob/master/README.md)
- [sdsykes/fastimage on GitHub](https://github.com/sdsykes/fastimage)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sdsykes-fastimage
