48

In response to another question, a commenter mentioned an undocumented URI option I was not aware of to flip images horizontally/vertically with the App Engine images service.

The documentation mentions a few basic options:

  • =s0 — fullsize
  • =s640 — longest edge 640px long
  • =s640-c — 640px square

Would be nice to generate a comprehensive list of options, or if someone could provide any more options they know about here to serve as de facto documentation.

Community
  • 1
  • 1
Taylor Hughes
  • 1,963
  • 2
  • 15
  • 14
  • Google does not officially support most of the options listed below. Recently, the [Image API documentation](https://cloud.google.com/appengine/docs/standard/python/images/) was updated with this caveat: ***Important: Only the resize and crop arguments listed above are supported. Using any other arguments might result in breaking failures.*** – Quinn Comendant Jul 11 '19 at 06:04

4 Answers4

102

Between reading some random posts and manually doing some investigative research, I have put together the following list. Please drop any other knowledge in other answers or in comments and I can integrate it here.

Usage Example

We can effect various image transformations by tacking strings onto the end of an App Engine blob-based image URL, following an = character. Options can be combined by separating them with hyphens, eg.:

http://[image-url]=s200-fh-p-b10-c0xFFFF0000

or:

http://[image-url]=s200-r90-cc-c0xFF00FF00-fSoften=1,20,0:

... which have the following effect (documentation below):

As an example of how awesome this is, here's an animated GIF, downsized and inverted:

… which we can then convert into an MP4 video with one extra parameter: click to see MP4 version


SIZE / CROP

  • s640 — generates image 640 pixels on largest dimension
  • s0 — original size image
  • w100 — generates image 100 pixels wide
  • h100 — generates image 100 pixels tall
  • s (without a value) — stretches image to fit dimensions
  • c — crops image to provided dimensions
  • n — same as c, but crops from the center
  • p — smart square crop, attempts cropping to faces
  • pp — alternate smart square crop, does not cut off faces (?)
  • cc — generates a circularly cropped image
  • ci — square crop to smallest of: width, height, or specified =s parameter
  • nu — no-upscaling. Disables resizing an image to larger than its original resolution.

PAN AND ZOOM

  • x, y, z: — pan and zoom a tiled image. These have no effect on an untiled image or without an authorization parameter of some form (see googleartproject.com).

ROTATION

  • fv — flip vertically
  • fh — flip horizontally
  • r{90, 180, 270} — rotates image 90, 180, or 270 degrees clockwise

IMAGE FORMAT

  • rj — forces the resulting image to be JPG
  • rp — forces the resulting image to be PNG
  • rw — forces the resulting image to be WebP
  • rg — forces the resulting image to be GIF

  • v{0,1,2,3}sets image to a different format option (works with JPG and WebP)

Forcing PNG, WebP and GIF outputs can work in combination with circular crops for a transparent background. Forcing JPG can be combined with border color to fill in backgrounds in transparent images.

ANIMATED GIFs

  • rh — generates an MP4 from the input image
  • k — kill animation (generates static image)

MISC.

  • b10 — add a 10px border to image
  • c0xAARRGGBB — set border color, eg. =c0xffff0000 for red
  • d — adds header to cause browser download
  • e7 — set cache-control max-age header on response to 7 days
  • l100 — sets JPEG quality to 100% (1-100)
  • h — responds with an HTML page containing the image
  • g — responds with XML used by Google's pan/zoom

Filters

  • fSoften=1,100,0: - where 100 can go from 0 to 100 to blur the image
  • fVignette=1,100,1.4,0,000000 where 100 controls the size of the gradient and 000000 is RRGGBB of the color of the border shadow
  • fInvert=0,1 inverts the image regardless of the value provided
  • fbw=0,1 makes the image black and white regardless of the value provided

Unknown Parameters

These parameters have been seen in use, but their effect is unknown: no, nd, mv

Caveats

Some options (like =l for JPEG quality) do not seem to generate new images. If you change another option (size, etc.) and change the l value, the quality change should be visible. Some options also don't work well together. This is all undocumented by Google, probably with good reason.

Moreover, it's probably not a good idea to depend on any of these options existing forever. Google could remove most of them without notice at any time.

Community
  • 1
  • 1
Taylor Hughes
  • 1,963
  • 2
  • 15
  • 14
  • Worth noting: Most of these options (outside of =sNNN and -c) do not work in the local GAE environment. So that's a bummer but not surprising. – Taylor Hughes Aug 26 '14 at 21:23
  • Dude! I've been looking all over the place for months (not continously :p) for a way to change the cache-control header. I don't know how you found this but thanks so much! – krishan711 Oct 01 '14 at 09:35
  • 1
    There are a few more parameters I discovered: `rj` — forces the resulting image to be JPG, `rp` — forces the resulting image to be PNG, `rw` — forces the resulting image to be WebP, `rg` — forces the resulting image to be GIF. Forcing PNG, WebP and GIF outputs can work in combination with circular crops for a transparant background. Forcing JPG can be combined with border color to fill in backgrounds in transparent images. – Ambroos Jun 25 '15 at 11:13
  • `fSoften=1,100,0:`; where 100 can go from 0 to 100 to blur the image. Also `fVignette=1,100,1.4,0,000000`; where 100 controls the size of the gradient and 000000 is RRGGBB of the color of the border shadow. – ernestoalejo Jul 03 '15 at 14:00
  • There's a documented `c` parameter that crops the image and should probably be included here. I discovered the operation is not performed from the center of the image but a little bit above it (33%?). There is an undocumented parameter `n` that crops from the center like expected. Both of them are square crops – ernestoalejo Aug 30 '15 at 22:54
  • Can anyone share one sample blob store image url?. I need to experiment with the above parameters. Also will the parameters work with google cloud storage bucket images? – das Feb 18 '17 at 04:47
  • @falsarella I have a google bucket and I can access an image in the bucket using the format: https://storage.googleapis.com/{bucket name}/{image path}. But on trying the image transformation parameters at the end of the url, its not working. For example, I have tried https://storage.googleapis.com/{bucket name}/{image path}=h200. And it shows an error. Please help. – das Feb 18 '17 at 12:01
  • @das I think it won't work unless it's served under a Google App Engine application. – falsarella Feb 18 '17 at 13:27
  • After testing it seems that JPGs that are resized using `s` are automatically compressed at 90% but when `s0` is used, or the number matches the actual width of the image, they're not always being compressed. For example, a 1500x1000 image I was testing was output at 1.3 MB when `s0` and `s1500` where used, but `s1499` output it at 215 KB. So my advice is always use `-l90` or lower for JPGs. – nick Apr 08 '19 at 12:23
  • Is soemthing like this also possible for Google Storage saved images? – xetra11 Apr 18 '22 at 13:18
32

I was browsing through stuff one day, and then I actually found a javascript asset on one of google's pages that had the English variable names and their types! Here's a nicely formatted version I made:

int:  s   ==> Size
int:  w   ==> Width
bool: c   ==> Crop
hex:  c   ==> BorderColor
bool: d   ==> Download
int:  h   ==> Height
bool: s   ==> Stretch
bool: h   ==> Html
bool: p   ==> SmartCrop
bool: pa  ==> PreserveAspectRatio
bool: pd  ==> Pad
bool: pp  ==> SmartCropNoClip
bool: pf  ==> SmartCropUseFace
int:  p   ==> FocalPlane
bool: n   ==> CenterCrop
int:  r   ==> Rotate
bool: r   ==> SkipRefererCheck
bool: fh  ==> HorizontalFlip
bool: fv  ==> VerticalFlip
bool: cc  ==> CircleCrop
bool: ci  ==> ImageCrop
bool: o   ==> Overlay
str:  o   ==> EncodedObjectId
str:  j   ==> EncodedFrameId
int:  x   ==> TileX
int:  y   ==> TileY
int:  z   ==> TileZoom
bool: g   ==> TileGeneration
bool: fg  ==> ForceTileGeneration
bool: ft  ==> ForceTransformation
int:  e   ==> ExpirationTime
str:  f   ==> ImageFilter
bool: k   ==> KillAnimation
int:  k   ==> FocusBlur
bool: u   ==> Unfiltered
bool: ut  ==> UnfilteredWithTransforms
bool: i   ==> IncludeMetadata
bool: ip  ==> IncludePublicMetadata
bool: a   ==> EsPortraitApprovedOnly
int:  a   ==> SelectFrameint
int:  m   ==> VideoFormat
int:  vb  ==> VideoBegin
int:  vl  ==> VideoLength
bool: lf  ==> LooseFaceCrop
bool: mv  ==> MatchVersion
bool: id  ==> ImageDigest
int:  ic  ==> InternalClient
bool: b   ==> BypassTakedown
int:  b   ==> BorderSize
str:  t   ==> Token
str:  nt0 ==> VersionedToken
bool: rw  ==> RequestWebp
bool: rwu ==> RequestWebpUnlessMaybeTransparent
bool: rwa ==> RequestAnimatedWebp
bool: nw  ==> NoWebp
bool: rh  ==> RequestH264
bool: nc  ==> NoCorrectExifOrientation
bool: nd  ==> NoDefaultImage
bool: no  ==> NoOverlay
str:  q   ==> QueryString
bool: ns  ==> NoSilhouette
int:  l   ==> QualityLevel
int:  v   ==> QualityBucket
bool: nu  ==> NoUpscale
bool: rj  ==> RequestJpeg
bool: rp  ==> RequestPng
bool: rg  ==> RequestGif
bool: pg  ==> TilePyramidAsProto
bool: mo  ==> Monogram
bool: al  ==> Autoloop
int:  iv  ==> ImageVersion
int:  pi  ==> PitchDegrees
int:  ya  ==> YawDegrees
int:  ro  ==> RollDegrees
int:  fo  ==> FovDegrees
bool: df  ==> DetectFaces
str:  mm  ==> VideoMultiFormat
bool: sg  ==> StripGoogleData
bool: gd  ==> PreserveGoogleData
bool: fm  ==> ForceMonogram
int:  ba  ==> Badge
int:  br  ==> BorderRadius
hex:  bc  ==> BackgroundColor
hex:  pc  ==> PadColor
hex:  sc  ==> SubstitutionColor
bool: dv  ==> DownloadVideo
bool: md  ==> MonogramDogfood
int:  cp  ==> ColorProfile
bool: sm  ==> StripMetadata
int:  cv  ==> FaceCropVersion

Notes:

  • bool means just add the variable by itself
  • int means number after variable name
  • string means (potentially complex) string after variable name
  • hex means hexidecimal number in format 0x000000 after variable name
  • variables are separated by hyphens (-)
chocolatkey
  • 461
  • 5
  • 6
8

Detailed v option investigation

How I discovered it

I found out the v option really unintentionally!

Someday, while I was investigating the image response headers, I found an attribute etag with value set to v1. Since I haven't seen any v option yet, I just tried adding it to the image url and it worked! Despite the header attribute value probably has nothing to do with the v option, it helped me to accidentally find it.

Investigating how the effect works

First, I've noticed that setting v0 and not setting v resulted in the same response, which indicates that v0 returns the original image with no v option (just like using s0 on the s option would return the original sizing).

Then, I've noticed that setting v1, v2, and v3 progressively returned an image with a smaller content size (weight), and visually it became poorer. Interestingly, setting v4, v5, etc, didn't continue to optimize it.

Investigating what the effect is

Some other day I tested the same parameters on another image, and found that nothing happened. That was interesting: an option that works for an image and doesn't work for another, so I started testing what was the difference between the images. Reviewing the list of parameters, it came to me that it could be the image type, and indeed it was! The first image type I've tried the v option was JPEG, and the second was PNG. So, I could reproduce the same effect by setting the second one with both rj and v3!

Hence, I searched internet about JPEG types, and interestingly I've found some sources (as you can see here, and here) explaining about 3 types of JPEG: Baseline Standard, Baseline Optimized, and Progressive, perfectly fitting the three variations available within the v options!

Investigating when the effect works

I went trying the same v option on other image types, and found that WebP also supported the same kind of customized type, also progressively optimizing the image in weight and quality (but much lesser in quality than JPEG) in the same range between v0 and v3. Unfortunately, I haven't yet found any sources of different WebP types.

Also, it didn't change anything when used on GIFs, but, as the PNG type, you can also combine its options with rj and v3, but you would (of course) lose the GIF animation and quality.

falsarella
  • 12,217
  • 9
  • 69
  • 115
1

As sad as it makes me to tell you, I don't think, unless you are in Google, that this documentation is public-facing :(.

Developers.google.com is FILLED with stuff, but not always comprehensive/easy to find/understand. Until Google builds a public-facing tool, we have to work with what we have.

falsarella
  • 12,217
  • 9
  • 69
  • 115
Patrice
  • 4,641
  • 9
  • 33
  • 43