PDA

View Full Version : Mys 1.3.4 Dynamically Generated Images Addon


Dinocanid
08-15-2017, 12:51 PM
Before I begin, special thanks to Digital and Hare over at TGL. I couldn't have done this without them! (Link to original discussion) (https://thegaminglist.com/forums/topic/780-rendering-pets-as-layers/)

What this does: This addon will use Imagick (a.k.a ImageMagick) to layer multiple images, compress them into one, and display them wherever you'd like without using AJAX. This can be used for backgrounds, decors, or dynamically generated pets. (Great for breeding sites!) I recommend you read the entire tutorial and then tailor it to fit your needs rather than following along right away.

-Getting the images ready-
As an example, I have my pet's layers saved as separate, transparent png images. Make sure they appear on top of each other properly! Also make sure all of the images are the same size, don't crop them! This can easily be checked in any art/art editing program that allows layers (I use FireAlpaca). Then it's on to the folder structure. You can set in up in the picuploads folder. This is how mine looks:


picuploads

wolf_images

pup

bases
eyes
markings



adult

bases
eyes
markings






-Step 0-
On x10host: Installing Imagick is easy for you. Just navigate to CPanel and find "select PHP version". Click on it and look for the "imagick" plugin (should be in the second column). Check the box, hit save, and you're done! (If you're not on x10, your host might have this too. If not, continue to the second option below)
On XAMPP/Other hosts: Whether you're using a XAMPP server or a host that doesn't allow the above, follow this tutorial: Link (http://ourcodeworld.com/articles/read/349/how-to-install-and-enable-the-imagick-extension-in-xampp-for-windows). If not using XAMMP, make sure you search google on how to install imagick on your host before taking this route! It could be different based on your host.

-Step 1-
Navigate to phpMyAdmin and get some columns set up in owned_adoptables. Use consistent naming conventions! It will make your life 100% easier in the long run I promise you. For the sake of this tutorial, I'm going to use my column names and code as an example. Here are the new columns I made with the names:
http://www.clipular.com/c/6503018441998336.png?k=PPXZVhOSXJVMIAOLqimNRF4EvqI

-Step 2-
Navigate back to the root folder and make a new php file to hold the Imagick code. (I called mine wolfimage.php) Inside, this is how it looks:
<?php
header('Content-type: image/png');
// Lets setup the database.
$mysidia = Registry::get("mysidia");

//A not-so-clean way to get the wid of the parent page
$fullurl = $_SERVER['REQUEST_URI'];
$scrub = explode('/',trim($fullurl,'/'));
$cleanwid = end($scrub);

$pet = $mysidia->db->select("wolves", array(), "wid='$cleanwid'")->fetchObject();
if($pet->age >= 12){
$images = array(
'http://wild-souls.mysidiahost.com/picuploads/den.png',
"http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/bases/" . $pet->base . "base.png",
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $pet->marking4 . '.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $pet->marking3 . '.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $pet->marking2 . '.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $pet->marking1 . '.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/ranks/' . $pet->rank . '.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/eyes/eyes' . $pet->eyes . '.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/shade.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/lineart.png'
);
}
else{
$images = array(
'http://wild-souls.mysidiahost.com/picuploads/den.png',
"http://wild-souls.mysidiahost.com/picuploads/wolf_images/pup/bases/" . $pet->base . "-base-pup.png",
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/pup/markings/' . $pet->marking1 . '-pup.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/pup/eyes/eyes' . $pet->eyes . '-pup.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/pup/shade-pup.png',
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/pup/lineart-pup.png'
);

}
// Remember to order these in reverse, the last element in the array should always be the top layer you will see (usually lineart). All images should be the same dimensions. The first element in the array is [0], not [1]!!!!


// This creates the Imagick class that we will use.
$composed_image = new \Imagick($images);

// Base
if($pet->age >= 12){
$composed_image->setIteratorIndex(2);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(3);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(4);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(5);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(6);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(8);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
}
else{
$composed_image->setIteratorIndex(2);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(4);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
}

// As you see above, by calling setIteratorIndex(), you switch your "working layer" to the layer you wish to modify.
// Now lets flatten it and display it. This creates a new Imagick instance to work with with only one flat image.
$image = $composed_image->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('png');

echo $image->getImageBlob();
?>
-Step 3-
We're just about done! Don't believe me? Next I went to myadoptsview.php (called denview.php for me) and used this to get the image: $document->add(new Comment("<img src ='/wolfimage/{$wid}' height='auto' width='75%'>"));
The size is the full size of my image, and the full http:// is required! It is used in place of $adopt->getImage and instead shows the dynamically generated version. Here are my two lovely generated puppies:
http://www.clipular.com/c/4841643219091456.png?k=_oyfqRKVaxL5zurpBnROg9az4lc
http://www.clipular.com/c/4753780536246272.png?k=J1VlXMVGUKj0olzHDCOB9gvvZk8

-Finale-
-Imagick and relative paths-
Imagick for PHP 5.4 does not like relative paths, so absolute paths are required for it to work. I'm not sure if that's still the case with newer PHP versions.
-Playing with Imagick-
The markings images for my wolves are actually really messy and don't fit inside the lines. I fixed this by using COMPOSITE_DSTIN, which does it for me. (Yay, laziness! The reason the base itself doesn't completely fit in the lines is because I neglected to do so on the image itself, not because of imagick)
To use your own filters, just poke around here and try them out to see which ones you like: Clicky (http://phpimagick.com/Tutorial/composite?compositeExample=Dst_In).
-Backslashes vs. Forwardslashes-
If you use XAMPP/WAMPP like me, you'll have to use double backslashes. If you're operating online, then you use single forwardslashes like any other URL.
-Need help tailoring?-
Just let me know in the comments if things are going wrong. I can help you out with it.

Pear
08-16-2017, 10:36 AM
Wow, this is awesome!! :3 Thanks for doing this.

Hall of Famer
08-17-2017, 02:01 PM
Interesting. Note Imagick is a PECL extension that is not available unless it is installed on the server. MysidiaHost has it since I installed Imagick extension for my server, but good chance on other webhosts like x10hosting you cannot do this. Wont be a problem if you run your VPS or Dedicated server though, you will be able to install Imagick yourself.

Dinocanid
08-17-2017, 02:14 PM
X10 (free version; paid too I'm assuming) offers it along with some other plugins, but it has to be enabled. I'm not sure how it is for other hosts though.

Abronsyth
10-15-2017, 07:09 PM
I wonder how difficult it'd be to devise a generator/designer for users to use a drop-down or such to make custom pets :0

Dinocanid
10-15-2017, 07:27 PM
Actually....
https://orig00.deviantart.net/4cc9/f/2017/245/8/9/wolf_customization__wild_souls_preview__by_hoafan-dbm6nln.gif
I can give info on how to do this if you want. The only problem with my current method is that I can't seem to have the dropdown make the current color the "active" option after submitting. So "black" would always be at the top of the base color dropdown list for example, even if the user chose "red". It'd be great if anyone figured out a way to fix that though.

Abronsyth
10-16-2017, 12:05 PM
Well okay then XD
If you could I would absolutely appreciate it! I love systems like that because you can make it easy for users to purchase custom pets (something I want to implement premium currency for lol) :smile:

Dinocanid
10-16-2017, 01:21 PM
This is what I had on a page called "custompetgenerate.php". It holds the Imagick code:
<?php
class CustompetgenerateController extends AppController{

public function index(){
// Lets setup the database.
$mysidia = Registry::get("mysidia");
$custom_session = $mysidia->db->select("custom", array(), "uid='{$mysidia->user->uid}'")->fetchObject();
// Remember to order these in reverse, the last element in the array should always be the top layer you will see (usually lineart). All images should be the same dimensions.
$images = array(
'http://www.wild-souls.mysidiahost.com/picuploads/den.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/bases/' . $custom_session->base . ' base.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $custom_session->marking1 . '.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $custom_session->marking2 . '.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/markings/' . $custom_session->marking3 . '.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/ranks/' . $custom_session->rank . '.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/noses/' . $custom_session->nose . '.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/eyes/eyes ' . $custom_session->eyes . '.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/shade.png',
'http://www.wild-souls.mysidiahost.com/picuploads/wolf_images/adult/lineart.png'
);

// This creates the Imagick class that we will use.
$composed_image = new \Imagick($images);

//Base
$composed_image->setIteratorIndex(2);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );
$composed_image->setIteratorIndex(8);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );

// As you see above, by calling setIteratorIndex(), you switch your "working layer" to the layer you wish to modify.
// Now lets flatten it and display it. This creates a new Imagick instance to work with only one flat image.
$image = $composed_image->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('png');

header('Content-type: image/png');
echo $image->getImageBlob();
}
}
?>
I made a new table in the database called "custom". The columns there are similar to how I store the markings and stuff in the regular pet generation script. Each user has their own "session", which is a single column in the database that holds the custom information.
It isn't included here, but each user has a row generated when they register on the site; that row has default values to show a "blank" pet.

<?php
class CustompetView extends View{

public function index(){
$mysidia = Registry::get("mysidia");
$mysidia = Registry::get("mysidia");
$document = $this->document;
$custom_session = $mysidia->db->select("custom", array(), "uid='{$mysidia->user->uid}'")->fetchObject();
$document->setTitle("Create your Character");

//The width and height must be the same as the image size!
$document->add(new Comment("
<div style='display:flex; align-items:center; justify-content:center;'>
<iframe src='/custompetgenerate' style='border:none; overflow:hidden; width:800px; height:700px;'></iframe>
</div>
"));
$document->add(new Comment("
<form action='custompet' method='post'>
<div class ='form-group'>
<label for='base'>Base Color:</label>
<select class='form-control' id='base' name='base'>
<option>black</option>
<option>black phase</option>
<option>blue</option>
<option>chocolate</option>
<option>clay</option>
<option>cream</option>
<option>dark chocolate</option>
<option>dark cream</option>
<option>dark grey</option>
<option>dark red</option>
<option>faded black</option>
<option>faded blue</option>
<option>faded gold</option>
<option>gold</option>
<option>grey</option>
<option>isabella</option>
<option>ivy</option>
<option>light cream</option>
<option>light grey</option>
<option>moss</option>
<option>off-white</option>
<option>red</option>
<option>saffron</option>
<option>sand</option>
<option>white</option>
</select>
<label for='eyes'>Eye Color:</label>
<select class='form-control' id='eyes' name='eyes'>
<option>blue</option>
<option>gold</option>
<option>green</option>
<option>red</option>
<option>violet</option>
</select>
</div>
<label for='nose'>Nose Color:</label>
<select class='form-control' id='nose' name='nose'>
<option>black butterfly</option>
<option>black</option>
<option>blue</option>
<option>dudley</option>
<option>liver butterfly</option>
<option>liver</option>
<option>pink</option>

</select>
Marking 1: <select class='form-control' id='marking1' name='marking1'>
<option>empty</option>
<option>agouti</option>
<option>black overfur</option>
<option>brown overfur</option>
<option>harlequin</option>
<option>irish</option>
<option>piebald</option>
<option>red points</option>
<option>snowflake</option>
<option>tan eyes</option>
<option>urajiro</option>
<option>white socks</option>
<option>white tips</option>
<option>white trim</option>
<option>white underfur</option>
</select>
<p><p>
<input type='submit'>
</form>
"));

if ($_SERVER["REQUEST_METHOD"] == "POST") {
$base = $_REQUEST['base'];
$eyes = $_REQUEST['eyes'];
$mark1 = $_REQUEST['marking1'];
$nose = $_REQUEST['nose'];
$mysidia->db->update("custom", array("base" => $base, "eyes" => $eyes, "marking1" => $mark1, "nose" => $nose), "uid = '{$mysidia->user->uid}'");

}

}
}
?>
This is where the interface is. (custompet.php was basically the same as blank.php, so it wasn't worth posting here.) Each time the user clicks "submit", their dropdown selections are saved to the database and the image updates to reflect what they chose. The way this is set up, the user's customization is "saved" and it will remain the same if they leave the page and come back. With some tweaking, it should be possible to add another button saves the customization as an actual adoptable.

Abronsyth
10-16-2017, 04:27 PM
Thank you!!

So knowing how it saves in the database I think I can fix the drop-down selection problem.

What needs to be done is modify the first (aka default) option to reflect what the user has listed in the database. It'll look sort of like this I think:
<option selected>{$selectedbase}</option>
<option>black</option>
<option>brown</option>
<option>...and so on...</option>

First we'd need to define $selected, which is easy enough;
$selectedbase = $mysidia->db->select("custom", array("base"), "uid='{$mysidia->user->uid}'")->fetchColumn();

I haven't tested it at all yet, haha, but I do think that it'd work along those lines!

And thank you again, Dinocanid!!!

gwynmil
11-06-2017, 10:39 AM
OK, finally giving this a try (feeling slightly more confident than last week, though the breeding script edits will still be offloaded to you, haha. I'm afraid to touch that stuff yet).

edit: never mind, figured out first issue. Reading that TGL thread was very helpful.

Still getting a blank image though. Syntax error maybe? I removed the composite_dstin bit 'cause that command isn't needed here.

<?php
class GriffimageController extends AppController{

public function index(){

$mysidia = Registry::get("mysidia");

$fullurl = $_SERVER['HTTP_REFERER'];
$cleanaid = end(explode('/',trim($fullurl,'/')));

$pet = $mysidia->db->select("owned_adoptables", array(), "aid='$cleanaid'")->fetchObject();

$images = array(
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/legs/' . $pet->legs . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/outer2/' . $pet->outer2 . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/outer1/' . $pet->outer1 . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/inner2/' . $pet->inner2 . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/inner1/' . $pet->inner1 . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/hind/' . $pet->hind . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/fore/' . $pet->fore . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/horns/' . $pet->horns . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/beak/' . $pet->beak . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/eyes/' . $pet->eyes . '.png',
'http://griffusion.elementfx.com/picuploads/griffimages/' . $pet->type . '/' . $pet->gender . '/' . $pet->currentlevel . '/line.png'
);

$composed_image = new \Imagick($images);

$image = $composed_image->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('png');

header('Content-type: image/png');
echo $image->getImageBlob();
}
}
?>
Example body part url: http://griffusion.elementfx.com/picuploads/griffimages/BasicGriff/f/5/fore/blue.png
Linearts are in the level folder: http://griffusion.elementfx.com/picuploads/griffimages/Minoanish/f/5/line.png

Sorry for the constant questions, haha. You've been amazingly helpful lately.

Dinocanid
11-06-2017, 12:39 PM
You're right on both! You need to set the iterator index on whatever layer you want to use commands/filters on. For example, you set the index to 1 and apply stuff to that, then you would set the index to 2...etc.
Wolves is the same as owned_adoptables too, I just made a custom table since I use a custom class and stuff.

If it's still showing a blank image, do your image names have spaces in them? It's weird, but on some hosts they can't have any spaces (that's what I just found out about mysidiahost). Some hosts do, while others don't, so it's something to try.

gwynmil
11-06-2017, 01:44 PM
Awesome, thanks!

Every folder and image name is a single word (black, white, tan, blue, inner1 etc). The body part names match the DB columns exactly. Imagick is enabled. I'm lost. ^^'

Earlier I naively thought you'd need access to the x10hosting cpanel to do anything for us, but just realised FTP could be used to poke around, to an extent. If it would help here, I can send you details for that?

(and if you feel like it, maybe do the other mods while you're in there... my paypal is ready lol. I'm just not sure which tasks will require DB access. Guess I'll send you a PM in a few minutes and you can decide.)

edit: oh, another thing that must be asked. How does this script work on pages with multiple creatures? Like the main myadopts page, breeding, user profiles. I'm guessing it doesn't. So we would need to save each griffin's image (or at least a thumbnail-sized version) into a folder somehow, to fetch from... or is there another way?

Dinocanid
11-06-2017, 02:30 PM
You can send me FTP details and I can see what I can do ^^ (It's also waaay more secure, some people just send their login details)
You're right about it not working on pages that show multiple creatures at once, but you could save each generated image; the only thing is that I can see that taking up a whole lot of disk space in the long run. I haven't looked into saving the images with imagick specifically, but I'm sure it can be done if you're willing to go that route.

gwynmil
11-07-2017, 02:32 PM
... OK, I kept trying to send the message last night and now tonight, but it gives an error. Not the first time Mysidia forum has done this. :hmmm:
So the list is posted for you here (http://griffusion.elementfx.com/forum/showthread.php?tid=5), and I'm not sure how to securely send the FTP info. Sorry about this. ^^'

Dinocanid
11-07-2017, 07:13 PM
It's fine! I just sent you an email.

Dinocanid
12-17-2017, 04:07 PM
I updated the code. Now it should work fine as an image by using:
<img src='/yourfilename/{$adoptIDevariable}'>
So for example, I can now use it like this:
<img src ='/wolfimage/{$wid}' height='auto' width='75%'>
This also resolves scaling issues, so no more ugly scroll bars on your images, and it allows you to display more than one generated image (like on the myadopts index). The only thing is that half of the images most likely fail to load if many are shown on one page.

Abronsyth
12-25-2017, 10:16 AM
!! Excite !! :colonu:

Okay so I am just hoping you could help me understand this;
$composed_image->setIteratorIndex(2);
$composed_image->compositeImage( new \Imagick($images[1]), \Imagick::COMPOSITE_DSTIN, 0, 0 );

So here, this is a section that constrains the layer "2" to be only visible within layer "1," right?

Then for the layer labels, is it descending from top-down? So for you example is this layer "2"?
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/shade.png'

With this being layer "1"?
'http://wild-souls.mysidiahost.com/picuploads/wolf_images/adult/lineart.png'

I have multiple linearts I'll be using for each level, so I want to make it easier on myself by just having the base/marking layers big enough to cover all linearts, but then of course not have them go outside of the lineart.

Thank you, and happy holidays!

Dinocanid
12-25-2017, 02:11 PM
1. Yep! So layer 2 would appear within layer 1
2. It ascends from top to down. So the first in the array is 0, the second would be layer 1, etc. In short, the items in the bottom of the array appear on top of the items in the top of the array, if that makes sense.

Abronsyth
12-27-2017, 10:15 PM
Alright, that absolutely answers my questions! Thanks!

(Trying to use this to create a geno/pheno system...it's...tedious lol)

SyntaxError73
03-11-2018, 09:57 PM
How would I tailor the script to allow multiple different species of breedable animals?


Let's say I wanted to make a site where the user could breed snakes and lizards.. and I wanted to use the random image generator. If a user bred two snakes together, how would the script know not to put a lizard marking on the new baby snake, and only use snake images?

I really love this idea, I sometimes think too hard about the logic though...

Dinocanid
03-12-2018, 05:49 PM
You could use variables in the image url, so it fetches the proper species type. For example:
'http://YOURSITE.com/picuploads/pet_images/{$pet->type}/markings/somemarking.png',

You could create two separate folders for snakes and lizards, but the subfolder names would remain the same. If you don't want to mix up markings by naming them the same thing in both directories, you could label them "snake-stripes1.png" and "lizard-stripes1.png", then you can do this:
'http://YOURSITE.com/picuploads/pet_images/{$pet->type}/markings/' . $pet->type . '-stripes1.png'.png',

If you want to go further and grab a different marking based on the level of a pet (assuming it has a baby stage, etc.), then you can replace "$pet->age" with "$pet->currentlevel", and then change the if statement accordingly. So:
if($pet->currentlevel >= 1){
//image array for baby pets goes here...
}

SyntaxError73
03-12-2018, 07:51 PM
You could use variables in the image url, so it fetches the proper species type. For example:


You could create two separate folders for snakes and lizards, but the subfolder names would remain the same. If you don't want to mix up markings by naming them the same thing in both directories, you could label them "snake-stripes1.png" and "lizard-stripes1.png", then you can do this:
'http://YOURSITE.com/picuploads/pet_images/{$pet->type}/markings/' . $pet->type . '-stripes1.png'.png',

If you want to go further and grab a different marking based on the level of a pet (assuming it has a baby stage, etc.), then you can replace "$pet->age" with "$pet->currentlevel", and then change the if statement accordingly. So:
if($pet->currentlevel >= 1){
//image array for baby pets goes here...
}


Yes thank you! this will help a lot, since I am Planning on making marking sets for babies too, and of course multiple species types.