Image gallery data from filename

Hi,

I have a brand site that I need to offer access to lots of images, icons etc and download them, each filename follows this format: Category_Desc_Code_Size.jpg

I have created a gallery using the foreach loop for the files in a folder, this works fine. But I want to be able to at the very least automatically provide links to download each of the three sizes of the same image:

Category_Desc_Code**_small**.jpg
Category_Desc_Code**_meduim**.jpg
Category_Desc_Code**_large**.jpg

Is there a way to get the information from the parts of the file name if they are always consistently in the same place? Would also like to get the unique code to display on the page.

I was hoping to just add the files and not have to edit text files or use the panel, so it was automated. Any help greatly appreciated

Thanks

What is the filename of the image you use in the gallery?

They vary but an example is:
renewables_airsourceinstall_PG1283945713_small.jpg
renewables_airsourceinstall_PG1283945713_medium.jpg
renewables_airsourceinstall_PG1283945713_large.jpg

I only want to use _small for gallery/thumb and then provide download links to the _medium and _large versions (not displayed on the page)

You can get the other versions via the first part of the filename of the file you actually output on the page, i.e. use PHP string methods to cut of the last part _small from the filename, then filter the rest of the files by that string.

Thanks for the pointer but my php skills are not that great… need to learn more!

$file->name() gives you the filename without the extension, e.g

 $filename     = 'renewables_airsourceinstall_PG1283945713_small';
 $baseFilename = substr($filename, 0, -6); 
 echo $baseFilename; // renewables_airsourceinstall_PG1283945713

// then we filter all images to get those that start with the basefilename
$filteredFiles = $page->images()->filterBy('filename', '*=', $baseFilename);

Thanks for your help… It’s now very close to be working as needed:

I’ve made some changes to try to get this working, with the following problems I can’t seem to know how to fix, please do you have ideas?

  1. For test purposes 9 image files in gallery folder, but this includes the different sizes (_s _m _l) so on the page I only want to display 3 eg the _s suffixed ones. It currently displays all 9.
  2. $filename variable is being displayed on the webpage, I need this to be hidden

Here’s my code with comments:

     <ul class="album-gallery">
        <?php foreach ($gallery as $image): ?>
        <?=
          // Needs to be not specific to any one image but each '_s' image in a folder
          // How do I stop this variable image name displaying on the page?
          $filename     = $image->name();
          // echo $baseFilename; // Each file in folder minus last 2 chars eg. _s _m _l
          $baseFilename = substr($filename, 0, -2);

          // Filter all images to get those in current folder basefilename
          $filteredFiles = $page->images()->filterBy('filename', '*=', $baseFilename);
        ?>
        <li>
          <a href="<?= $image->url() ?>" data-lightbox>
            <figure class="img" style="--w:<?= $image->width() ?>;--h:<?= $image->height() ?>">
              <!-- Need to load only those with the suffix of '_s' (small) -->
              <img src="<?= $page->url(); ?>/<?= $baseFilename; ?>_s.jpg">
            </figure>
          </a>
            <div class="gallery_links">
              <!-- Links to the 3 sizes using $page url and $baseFilename -->
              <a href="<?= $page->url(); ?>/<?= $baseFilename; ?>_s.jpg">Small</a> |
              <a href="<?= $page->url(); ?>/<?= $baseFilename; ?>_m.jpg">Medium</a> |
              <a href="<?= $page->url(); ?>/<?= $baseFilename; ?>_l.jpg">Large</a>
            </div>
        </li>
        <?php endforeach ?>
      </ul>

You are echoing it, replace short echo statement with <?php

Your images should be filtered here

<?php
// all images that end in `_s`
$gallery = $page->images()->filterBy('name', '$=', '_s');

That worked a treat! Thank you :grinning:

Sorry to be cheeky… could you shed some light on how I would now find the unique code for each image so I can display it underneath.

Tried variations of below, with no luck:

// Find string text CODE in file name to display under each image
// imagecategoryname_imagefiledesc_CODE1789179819_s.jpg
// Need to get all characters between CODE & _ these vary in length

$findFilenameCodeStart = str_starts_with('CODE', '');
$findFilenameCodeFinish = str_ends_with('_', '');

$filteredFilesCode = $page->images()->filterBy('filename', 'between', $findFilenameCodeStart+$findFilenameCodeFinish);

echo $filteredFilesCode;

Do you mean this part of the filename?

Yes, I thought if I added the text CODE at the start of this then it would be easy to identify. As that part of the filename varies in terms of letters prefix and characters length. So it could be PHS12345678910 or PG1234567 or PAS123456789 or iStock781789197 etc.

Ok, then we have to get the part between the two last underscores.

Yes, so tried this but it only seems to except a numerical value eg. [5, 10] I get an error with either of the below:

$filteredFilesCode = $page->images()->filterBy('filename', 'between', ['_', '_']);
echo $filteredFilesCode;

or

$filteredFilesCode = $page->images()->filterBy('filename', 'between', [_, _]);
echo $filteredFilesCode;

I can easily change all the file names to only include underscores around the the unique code PG1283945713 so an example file name would be:

renewables-airsourceinstall_PG1283945713_s.jpg

You don’t want to filter files, you wanted to get the code inside the loop, right?

<?php
$gallery = $page->images()->filterBy('name', '$=', '_s');

foreach($gallery as $image) {
  // assuming a filename like renewables-airsourceinstall_PG1283945713_s.jpg
  echo Str::split($image->name(), '_')[1];
}

That worked perfectly! Thank you… I’m completely new to Kirby so really appreciate the help. I’m very impressed with Kirby so far and it’s support :+1:

I’ll add all the working commented code here shortly for anyone else.

1 Like