Cloudinary Blog

Relive the Glory of Japanese Fighting Baseball With faker.js and Cloudinary

Generate Names With faker.js and Convert Them to Graphics With Cloudinary

The year was 1994. South Africa held its first fully representative democratic election, Netscape Navigator became the first commercially successful web browser. Coconuts Japan re-released EA Sports' MLBPA Baseball video game under the perhaps surprising title Fighting Baseball. Unlike MLBPA Baseball, which was licensed by the Major League Baseball (MLB), Fighting Baseball could not infringe on MLB trademarks, reference the National League or American League by name, or adopt actual team or player names.

To get around that limitation, the team invented an entire league's worth of fake American names. That’s thanks to a simple procedure concocted by some clever internet sleuths: Take a player's last name, change a letter or two, and pair that last name with another player's first name, which was occasionally edited in a similar way.

The results were simply beautiful with long-lasting appeal. After all, who wouldn’t want to play baseball with Todd Bonzalez, Bobson Dugnutt, and Sleve McDichael?

That was then; this is now. In the last 25 years, the ability to generate an unending amount of randomness has taken off at top speed, and programmatically producing fake names in a like manner is achievable. Once a list is in hand, it’s a breeze to leverage Cloudinary to turn it into a graphic that fits right into the game.

Even better, we can do all the randomization on the front end and generate images with front-end calls to Cloudinary. The result is a Jamstack app that requires no server management. This post shines a light on the process.

Faking Names With faker.js

First, generate template names with the faker.js JavaScript library, which offers many utilities for spawning fake data: names, dates, addresses, passwords, vehicles, bitcoin addresses. Here, we'll take advantage of faker's name-generating capabilities. See the steps below.

  1. initialize with a locale and a seed to ensure that the results are deterministic based on the URL:

    Copy to clipboard
    const faker = window.faker;
    faker.locale = "en_US";
    // getParameterByName is a utility function retrieving the seed from the URL.
    let seed = parseInt(getParameterByName("seed"));
    if (seed && !isNaN(seed)) {
    faker.seed(seed);
    }
  2. Generate names of 16 characters maximum so that the names would display properly in the image.

    Copy to clipboard
    do {
    firstName = faker.name.firstName(0);
    lastName = faker.name.lastName();
    name = `${firstName} ${lastName}`;
    } while (name.length > 16)
  3. Arbitrarily replace one or two characters of the last name with other characters for a touch of randomness. The scramble function picks the letters and passes them to the validMoves function to determine an appropriate replacement.

    Copy to clipboard
    function validMoves(letter) {
    if (letter.toUpperCase() == "Y") return; // Y is tricky, just don't mess with it.
    const hPreceders = ["c", "s", "t"];
    const consonants = "bdfghjklmnpqrvwxz".split("");
    const vowels = "aeiou".split("");
    let toReturn;
    if (hPreceders.includes(letter.toLowerCase())) {
    return hPreceders;
    } else if (consonants.includes(letter.toLowerCase())) {
    return consonants;
    } else {
    return vowels;
    }
    }

    We always return the same class of letter: H preceder, consonant, or vowel.

  4. Perform a similar replacement on the first name about 20% of the time, matching the apparent trend in Fighting Baseball.

That's it. A new name is now available, and we're ready to generate images.

Generating Images With Cloudinary

Start with

Ruby:
Copy to clipboard
cl_image_tag("bobson.jpg")
PHP v1:
Copy to clipboard
cl_image_tag("bobson.jpg")
PHP v2:
Copy to clipboard
(new ImageTag('bobson.jpg'));
Python:
Copy to clipboard
CloudinaryImage("bobson.jpg").image()
Node.js:
Copy to clipboard
cloudinary.image("bobson.jpg")
Java:
Copy to clipboard
cloudinary.url().imageTag("bobson.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('bobson.jpg').toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("bobson.jpg")
React:
Copy to clipboard
<Image publicId="bobson.jpg" >

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="bobson.jpg" >

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="bobson.jpg" >

</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.BuildImageTag("bobson.jpg")
Android:
Copy to clipboard
MediaManager.get().url().generate("bobson.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().generate("bobson.jpg")!, cloudinary: cloudinary)
and layer on names. Cloudinary's transformation feature for text layers is the perfect tool for the job. We can specify position, font, size, color, and text transformations, along with, of course, the text itself.

Here's the transformation for the first player, Gbant Nolav (originally Grant Nolan):

Copy to clipboard
co_rgb:edeae5,l_text:Press Start 2P_16:GBANT%2520NOLAV/co_rgb:000000,e_shadow:5,x_2,y_2/fl_layer_apply,g_north_west,x_38,y_30

The font Press Start 2P, available on Google Fonts, looks reasonably similar to the original in the game, and Cloudinary supports text overlays with any Google font out of the box. Also added is a black shadow with the e_shadow effect.

Finally, place the text with a northwest gravity, as well as specific x and y coordinates to offset from the corner. Here is the result:

Ruby:
Copy to clipboard
cl_image_tag("bobson.jpg", :transformation=>[
  {:color=>"#edeae5", :overlay=>{:font_family=>"P", :font_size=>16, :text=>"GBANT%2520NOLAV"}},
  {:color=>"#000000", :effect=>"shadow:5", :x=>2, :y=>2},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>38, :y=>30}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("bobson.jpg", array("transformation"=>array(
  array("color"=>"#edeae5", "overlay"=>array("font_family"=>"P", "font_size"=>16, "text"=>"GBANT%2520NOLAV")),
  array("color"=>"#000000", "effect"=>"shadow:5", "x"=>2, "y"=>2),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>38, "y"=>30)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('bobson.jpg'))
  ->overlay(
      Overlay::source(Source::text('GBANT%20NOLAV', (new TextStyle('Press Start 2P', 16)))
        ->textColor(Color::rgb('edeae5'))
        ->transformation((new ImageTransformation())
          ->effect(Effect::shadow()->strength(5)
            ->color(Color::rgb('000000'))
            ->offsetX(2)->offsetY(2))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::northWest()))
        ->offsetX(38)->offsetY(30)
  ));
Python:
Copy to clipboard
CloudinaryImage("bobson.jpg").image(transformation=[
  {'color': "#edeae5", 'overlay': {'font_family': "P", 'font_size': 16, 'text': "GBANT%2520NOLAV"}},
  {'color': "#000000", 'effect': "shadow:5", 'x': 2, 'y': 2},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 38, 'y': 30}
  ])
Node.js:
Copy to clipboard
cloudinary.image("bobson.jpg", {transformation: [
  {color: "#edeae5", overlay: {font_family: "P", font_size: 16, text: "GBANT%2520NOLAV"}},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 30}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .color("#edeae5").overlay(new TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")).chain()
  .color("#000000").effect("shadow:5").x(2).y(2).chain()
  .flags("layer_apply").gravity("north_west").x(38).y(30)).imageTag("bobson.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('bobson.jpg', {transformation: [
  {color: "#edeae5", overlay: new cloudinary.TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 30}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("bobson.jpg", {transformation: [
  {color: "#edeae5", overlay: new cloudinary.TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 30}
  ]})
React:
Copy to clipboard
<Image publicId="bobson.jpg" >
  <Transformation color="#edeae5" overlay={{fontFamily: "P", fontSize: 16, text: "GBANT%2520NOLAV"}} />
  <Transformation color="#000000" effect="shadow:5" x="2" y="2" />
  <Transformation flags="layer_apply" gravity="north_west" x="38" y="30" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="bobson.jpg" >
  <cld-transformation color="#edeae5" :overlay="{fontFamily: 'P', fontSize: 16, text: 'GBANT%2520NOLAV'}" />
  <cld-transformation color="#000000" effect="shadow:5" x="2" y="2" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="38" y="30" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="bobson.jpg" >
  <cl-transformation color="#edeae5" overlay="text:Press%20Start%202P_16:GBANT%2520NOLAV">
  </cl-transformation>
  <cl-transformation color="#000000" effect="shadow:5" x="2" y="2">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="38" y="30">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Color("#edeae5").Overlay(new TextLayer().FontFamily("P").FontSize(16).Text("GBANT%2520NOLAV")).Chain()
  .Color("#000000").Effect("shadow:5").X(2).Y(2).Chain()
  .Flags("layer_apply").Gravity("north_west").X(38).Y(30)).BuildImageTag("bobson.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .color("#edeae5").overlay(new TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")).chain()
  .color("#000000").effect("shadow:5").x(2).y(2).chain()
  .flags("layer_apply").gravity("north_west").x(38).y(30)).generate("bobson.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setColor("#edeae5").setOverlay("text:Press%20Start%202P_16:GBANT%2520NOLAV").chain()
  .setColor("#000000").setEffect("shadow:5").setX(2).setY(2).chain()
  .setFlags("layer_apply").setGravity("north_west").setX(38).setY(30)).generate("bobson.jpg")!, cloudinary: cloudinary)
Board with one name

To add another name, Troy Orl (originally Troy Orn), with a similar transformation:

Copy to clipboard
co_rgb:edeae5,l_text:Press Start 2P_16:TROY%2520ORL/co_rgb:000000,e_shadow:5,x_2,y_2/fl_layer_apply,g_north_west,x_38,y_50

The result:

Ruby:
Copy to clipboard
cl_image_tag("bobson.jpg", :transformation=>[
  {:color=>"#edeae5", :overlay=>{:font_family=>"P", :font_size=>16, :text=>"GBANT%2520NOLAV"}},
  {:color=>"#000000", :effect=>"shadow:5", :x=>2, :y=>2},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>38, :y=>30},
  {:color=>"#edeae5", :overlay=>{:font_family=>"P", :font_size=>16, :text=>"TROY%2520ORL"}},
  {:color=>"#000000", :effect=>"shadow:5", :x=>2, :y=>2},
  {:flags=>"layer_apply", :gravity=>"north_west", :x=>38, :y=>50}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("bobson.jpg", array("transformation"=>array(
  array("color"=>"#edeae5", "overlay"=>array("font_family"=>"P", "font_size"=>16, "text"=>"GBANT%2520NOLAV")),
  array("color"=>"#000000", "effect"=>"shadow:5", "x"=>2, "y"=>2),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>38, "y"=>30),
  array("color"=>"#edeae5", "overlay"=>array("font_family"=>"P", "font_size"=>16, "text"=>"TROY%2520ORL")),
  array("color"=>"#000000", "effect"=>"shadow:5", "x"=>2, "y"=>2),
  array("flags"=>"layer_apply", "gravity"=>"north_west", "x"=>38, "y"=>50)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('bobson.jpg'))
  ->overlay(
      Overlay::source(Source::text('GBANT%20NOLAV', (new TextStyle('Press Start 2P', 16)))
        ->textColor(Color::rgb('edeae5'))
        ->transformation((new ImageTransformation())
          ->effect(Effect::shadow()->strength(5)
            ->color(Color::rgb('000000'))
            ->offsetX(2)->offsetY(2))))
      ->position((new Position())
        ->gravity(Gravity::compass(Compass::northWest()))
        ->offsetX(38)->offsetY(30)))
    ->overlay(
        Overlay::source(Source::text('TROY%20ORL', (new TextStyle('Press Start 2P', 16)))
          ->textColor(Color::rgb('edeae5'))
          ->transformation((new ImageTransformation())
            ->effect(Effect::shadow()->strength(5)
              ->color(Color::rgb('000000'))
              ->offsetX(2)->offsetY(2))))
        ->position((new Position())
          ->gravity(Gravity::compass(Compass::northWest()))
          ->offsetX(38)->offsetY(50)
      
    ));
Python:
Copy to clipboard
CloudinaryImage("bobson.jpg").image(transformation=[
  {'color': "#edeae5", 'overlay': {'font_family': "P", 'font_size': 16, 'text': "GBANT%2520NOLAV"}},
  {'color': "#000000", 'effect': "shadow:5", 'x': 2, 'y': 2},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 38, 'y': 30},
  {'color': "#edeae5", 'overlay': {'font_family': "P", 'font_size': 16, 'text': "TROY%2520ORL"}},
  {'color': "#000000", 'effect': "shadow:5", 'x': 2, 'y': 2},
  {'flags': "layer_apply", 'gravity': "north_west", 'x': 38, 'y': 50}
  ])
Node.js:
Copy to clipboard
cloudinary.image("bobson.jpg", {transformation: [
  {color: "#edeae5", overlay: {font_family: "P", font_size: 16, text: "GBANT%2520NOLAV"}},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 30},
  {color: "#edeae5", overlay: {font_family: "P", font_size: 16, text: "TROY%2520ORL"}},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 50}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .color("#edeae5").overlay(new TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")).chain()
  .color("#000000").effect("shadow:5").x(2).y(2).chain()
  .flags("layer_apply").gravity("north_west").x(38).y(30).chain()
  .color("#edeae5").overlay(new TextLayer().fontFamily("P").fontSize(16).text("TROY%2520ORL")).chain()
  .color("#000000").effect("shadow:5").x(2).y(2).chain()
  .flags("layer_apply").gravity("north_west").x(38).y(50)).imageTag("bobson.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('bobson.jpg', {transformation: [
  {color: "#edeae5", overlay: new cloudinary.TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 30},
  {color: "#edeae5", overlay: new cloudinary.TextLayer().fontFamily("P").fontSize(16).text("TROY%2520ORL")},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 50}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("bobson.jpg", {transformation: [
  {color: "#edeae5", overlay: new cloudinary.TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 30},
  {color: "#edeae5", overlay: new cloudinary.TextLayer().fontFamily("P").fontSize(16).text("TROY%2520ORL")},
  {color: "#000000", effect: "shadow:5", x: 2, y: 2},
  {flags: "layer_apply", gravity: "north_west", x: 38, y: 50}
  ]})
React:
Copy to clipboard
<Image publicId="bobson.jpg" >
  <Transformation color="#edeae5" overlay={{fontFamily: "P", fontSize: 16, text: "GBANT%2520NOLAV"}} />
  <Transformation color="#000000" effect="shadow:5" x="2" y="2" />
  <Transformation flags="layer_apply" gravity="north_west" x="38" y="30" />
  <Transformation color="#edeae5" overlay={{fontFamily: "P", fontSize: 16, text: "TROY%2520ORL"}} />
  <Transformation color="#000000" effect="shadow:5" x="2" y="2" />
  <Transformation flags="layer_apply" gravity="north_west" x="38" y="50" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="bobson.jpg" >
  <cld-transformation color="#edeae5" :overlay="{fontFamily: 'P', fontSize: 16, text: 'GBANT%2520NOLAV'}" />
  <cld-transformation color="#000000" effect="shadow:5" x="2" y="2" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="38" y="30" />
  <cld-transformation color="#edeae5" :overlay="{fontFamily: 'P', fontSize: 16, text: 'TROY%2520ORL'}" />
  <cld-transformation color="#000000" effect="shadow:5" x="2" y="2" />
  <cld-transformation flags="layer_apply" gravity="north_west" x="38" y="50" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="bobson.jpg" >
  <cl-transformation color="#edeae5" overlay="text:Press%20Start%202P_16:GBANT%2520NOLAV">
  </cl-transformation>
  <cl-transformation color="#000000" effect="shadow:5" x="2" y="2">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="38" y="30">
  </cl-transformation>
  <cl-transformation color="#edeae5" overlay="text:Press%20Start%202P_16:TROY%2520ORL">
  </cl-transformation>
  <cl-transformation color="#000000" effect="shadow:5" x="2" y="2">
  </cl-transformation>
  <cl-transformation flags="layer_apply" gravity="north_west" x="38" y="50">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Color("#edeae5").Overlay(new TextLayer().FontFamily("P").FontSize(16).Text("GBANT%2520NOLAV")).Chain()
  .Color("#000000").Effect("shadow:5").X(2).Y(2).Chain()
  .Flags("layer_apply").Gravity("north_west").X(38).Y(30).Chain()
  .Color("#edeae5").Overlay(new TextLayer().FontFamily("P").FontSize(16).Text("TROY%2520ORL")).Chain()
  .Color("#000000").Effect("shadow:5").X(2).Y(2).Chain()
  .Flags("layer_apply").Gravity("north_west").X(38).Y(50)).BuildImageTag("bobson.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .color("#edeae5").overlay(new TextLayer().fontFamily("P").fontSize(16).text("GBANT%2520NOLAV")).chain()
  .color("#000000").effect("shadow:5").x(2).y(2).chain()
  .flags("layer_apply").gravity("north_west").x(38).y(30).chain()
  .color("#edeae5").overlay(new TextLayer().fontFamily("P").fontSize(16).text("TROY%2520ORL")).chain()
  .color("#000000").effect("shadow:5").x(2).y(2).chain()
  .flags("layer_apply").gravity("north_west").x(38).y(50)).generate("bobson.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setColor("#edeae5").setOverlay("text:Press%20Start%202P_16:GBANT%2520NOLAV").chain()
  .setColor("#000000").setEffect("shadow:5").setX(2).setY(2).chain()
  .setFlags("layer_apply").setGravity("north_west").setX(38).setY(30).chain()
  .setColor("#edeae5").setOverlay("text:Press%20Start%202P_16:TROY%2520ORL").chain()
  .setColor("#000000").setEffect("shadow:5").setX(2).setY(2).chain()
  .setFlags("layer_apply").setGravity("north_west").setX(38).setY(50)).generate("bobson.jpg")!, cloudinary: cloudinary)
Board with two names

That’s a tedious task, involving a load of manual work to calculate the text positions. A much more efficient way would be to describe each position as a row and a column, and have Cloudinary do the math. Here’s what to do:

  1. Create a named transformation, bobson_name, with three arguments (col, row, and player) to store the calculation.

    Copy to clipboard
    co_rgb:edeae5,l_text:Press Start 2P_16:$(player)/co_rgb:000000,e_shadow:5,x_2,y_2/fl_layer_apply,g_north_west,x_$col_mul_294_sub_256,y_10_add_$row_mul_20

    A simple substitution takes care of the player name. For col, multiply it by the column width (294 pixels) and then subtract an offset of 256 pixels. For row, multiply it by the row height (20 pixels) and add a 10-pixel further offset.

    The result is a replacement of the two transformations above with the following:

    Copy to clipboard
    $player_!GBANT%20NOLAV!,$col_1,$row_1/t_bobson_name/$player_!TROY%20ORL!,$col_1,$row_2/t_bobson_name/

    Note
    First specify the variables and then invoke the transformation, once per text overlay. Strings are surrounded by instances of !; integers have no special surrounding characters.

  2. Now effortlessly add the remaining players:

Copy to clipboard
$player_!GBANT%20NOLAV!,$col_1,$row_1/t_bobson_name/$player_!TROY%20ORL!,$col_1,$row_2/t_bobson_name/$player_!SCOTT%20JIRVEY!,$col_1,$row_3/t_bobson_name/$player_!TIM%20OBSHIRE!,$col_1,$row_4/t_bobson_name/$player_!JIMMIE%20QEITZON!,$col_1,$row_5/t_bobson_name/$player_!TATH%20PELLICH!,$col_1,$row_6/t_bobson_name/$player_!RANDALL%20KIIKN!,$col_1,$row_7/t_bobson_name/$player_!RAYLOND%20WOKJ!,$col_1,$row_8/t_bobson_name/$player_!PHILIP%20FERQY!,$col_1,$row_9/t_bobson_name/$player_!SIDNEY%20KUVALAS!,$col_1,$row_10/t_bobson_name/$player_!WILBUR%20WISUZK!,$col_1,$row_11/t_bobson_name/$player_!ROMAN%20SHIOLDS!,$col_2,$row_1/t_bobson_name/$player_!GEORGE%20DICKINSUN!,$col_2,$row_2/t_bobson_name/$player_!LOUIS%20STHAEFER!,$col_2,$row_3/t_bobson_name/$player_!DOYLE%20CIRKERY!,$col_2,$row_4/t_bobson_name/$player_!FELIPE%20ZAST!,$col_2,$row_5/t_bobson_name/$player_!BRUCE%20WOYLE!,$col_2,$row_6/t_bobson_name/$player_!CONRAD%20FEHE!,$col_2,$row_7/t_bobson_name/$player_!DARRYL%20KOORE!,$col_2,$row_8/t_bobson_name/$player_!MIGUEL%20SHAMPLIN!,$col_2,$row_9/t_bobson_name/$player_!TIM%20MKANT!,$col_2,$row_10/t_bobson_name/$player_!DANNY%20TANFORD!,$col_2,$row_11/t_bobson_name

The image then looks like this:

Ruby:
Copy to clipboard
cl_image_tag("bobson.jpg", :variables=>[["$player", "!DANNY TANFORD!"], ["$col", "2"], ["$row", "11"]], :transformation=>[
  {:quality=>"auto"},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]},
  {:transformation=>["bobson_name"]}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("bobson.jpg", array("variables"=>array("$player"=>"!DANNY TANFORD!", "$col"=>"2", "$row"=>"11"), "transformation"=>array(
  array("quality"=>"auto"),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name")),
  array("transformation"=>array("bobson_name"))
  )))
PHP v2:
Copy to clipboard
(new ImageTag('bobson.jpg'))
  ->delivery(Delivery::format(Format::auto()))
  ->delivery(Delivery::quality(Quality::auto()))
  ->addVariable(Variable::set('player', 'GBANT NOLAV'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 1))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'TROY ORL'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 2))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'SCOTT JIRVEY'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 3))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'TIM OBSHIRE'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 4))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'JIMMIE QEITZON'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 5))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'TATH PELLICH'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 6))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'RANDALL KIIKN'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 7))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'RAYLOND WOKJ'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 8))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'PHILIP FERQY'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 9))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'SIDNEY KUVALAS'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 10))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'WILBUR WISUZK'))
  ->addVariable(Variable::set('col', 1))
  ->addVariable(Variable::set('row', 11))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'ROMAN SHIOLDS'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 1))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'GEORGE DICKINSUN'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 2))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'LOUIS STHAEFER'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 3))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'DOYLE CIRKERY'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 4))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'FELIPE ZAST'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 5))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'BRUCE WOYLE'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 6))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'CONRAD FEHE'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 7))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'DARRYL KOORE'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 8))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'MIGUEL SHAMPLIN'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 9))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'TIM MKANT'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 10))
  ->namedTransformation(NamedTransformation::name('bobson_name'))
  ->addVariable(Variable::set('player', 'DANNY TANFORD'))
  ->addVariable(Variable::set('col', 2))
  ->addVariable(Variable::set('row', 11))
  ->namedTransformation(NamedTransformation::name('bobson_name'));
Python:
Copy to clipboard
CloudinaryImage("bobson.jpg").image(variables={"$player": "!DANNY TANFORD!", "$col": "2", "$row": "11"}, transformation=[
  {'quality': "auto"},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]},
  {'transformation': ["bobson_name"]}
  ])
Node.js:
Copy to clipboard
cloudinary.image("bobson.jpg", {variables: [["$player", "!DANNY TANFORD!"], ["$col", "2"], ["$row", "11"]], transformation: [
  {quality: "auto"},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
.variables(variable("$player","!DANNY TANFORD!"),variable("$col","2"),variable("$row","11")).chain()
  .quality("auto").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name")).imageTag("bobson.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('bobson.jpg', {variables: [["$player", "!DANNY TANFORD!"], ["$col", "2"], ["$row", "11"]], transformation: [
  {quality: "auto"},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("bobson.jpg", {variables: [["$player", "!DANNY TANFORD!"], ["$col", "2"], ["$row", "11"]], transformation: [
  {quality: "auto"},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]},
  {transformation: ["bobson_name"]}
  ]})
React:
Copy to clipboard
<Image publicId="bobson.jpg" variables={[["$player", "!DANNY TANFORD!"], ["$col", "2"], ["$row", "11"]]}>
  <Transformation quality="auto" />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
  <Transformation transformation={["bobson_name"]} />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="bobson.jpg" :variables="[['$player', '!DANNY TANFORD!'], ['$col', '2'], ['$row', '11']]">
  <cld-transformation quality="auto" />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
  <cld-transformation transformation={["bobson_name"]} />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="bobson.jpg" variables="[['$player', '!DANNY TANFORD!'], ['$col', '2'], ['$row', '11']]">
  <cl-transformation quality="auto">
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
  <cl-transformation transformation={{["bobson_name"]}}>
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Quality("auto").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name").Chain()
  .Named("bobson_name")).BuildImageTag("bobson.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
.variables(variable("$player","!DANNY TANFORD!"),variable("$col","2"),variable("$row","11")).chain()
  .quality("auto").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name").chain()
  .named("bobson_name")).generate("bobson.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setQuality("auto").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name").chain()
  .setNamed("bobson_name")).generate("bobson.jpg")!, cloudinary: cloudinary)
Final image

Our very own Fighting Baseball team is now for real, complete with Scott Jirvey, Louis Sthaefer, and Bruce Woyle. See the live image, which was generated from seed 66219.

To add context, cite a random team name, assisted by faker.js and the pluralize library:

Copy to clipboard
function headerText() {
  return `Meet Your Amazing ${1950 + rand(71)} ${faker.address.city()} ${pluralize(faker.commerce.productName())}!`;
}

Feel free to build your own teams and rosters by clicking Redraft the team! and inspect the source code. Have a blast.

Recent Blog Posts

Get Your Media Moving Faster with Cloudinary’s Media Optimizer

So, your boss comes to you in a panic: he's just heard about Google's Core Web Vitals initiative and needs you to optimize the company website right now! "No problem," you say, hiding your fear that it's not something that can be done overnight. Just taking the first metric, Largest Contentful Paint (LCP), how can you possibly identify all the large elements - most likely images or video posters - of the many hundreds of pages that make up your site? There are already thousands of high-resolution (read massive) media files stored away, which marketing could use any time. How are you going to make sure they're all compressed to a size small enough to be delivered within the threshold? Not to mention all the new images and videos that will be created over time...

Read more
How to Tap Into the Value of User-Generated Content (UGC)

User-generated content (UGC) took off with, first of all, the advent of the internet and, subsequently, social networks. Everyday consumers were given keys to the kingdom, so to speak, so that they, too, could compose and post content, simultaneously engaging with others online. Twitter, Facebook, Instagram, Snapchat, TikTok—the networks through which we can create and publish content have grown exponentially, and brands are becoming aware of the benefits of tapping into the gold mines offered by those networks.

Read more
Identifying Countries by IP Address in Columnar Databases Through SQL

Cloudinary reaps a myriad of open web traffic, from ad networks to e-commerce sites. Our Data Science team is dedicated to analyzing the data for use internally and externally.

A glance at any General Data Protection Regulation (GDPR) article would reveal that—unlike Android device IDs (AID), through which users can reset their web address—keeping user identifiers, such as Internal Protocol (IP) and Media Access Control (MAC) addresses, as well as International Mobile Equipment Identity (IMEI), violates privacy. As a solution, you can discard all privacy identifications or make them visible to users for reset.

Read more
Digital-First Asset Management Explained

As the world changes, so does technology. I don’t need to name more than a handful of antiquated technologies before you nod in agreement: floppy disks, Walkmans, phone booths, VHS tapes, each of which have been phased out or rendered useless by new solutions that meet the same need but much more effectively.

Read more
How to Build Workflows With Cloudinary’s MediaFlows

Many of you who work with the Cloudinary platform have a media-associated workflow for moderation of images, dispatch of notifications with certain data or headers, implementation of activities through add-ons, etc. For most of those cases, Cloudinary would suggest that you take advantage of our webhook notifications and build the workflow with an infrastructure like AWS Lambda. This post describes how to do that with Cloudinary’s MediaFlows a beta product that helps tackle management and operational tasks related to visual media.

Read more