Jump to content

Batch import image resizing


Marty Walker
 Share

Recommended Posts

Hello,

I'm using Ryan's super-useful Import Pages from CSV to create a number of pages with fields that includes a multiple cropimage field. In my field settings I've set some limitations on the image dimensions. When I do an import those image dimensions aren't respected (understandably) so I'm wondering, is there's a way to use the API to batch resize the images and save over what's there?

(I'm retrieving each image from a URL so it's not practical to download each one and resize it - there's a few GB of them.)

Thanks for any help.

Link to comment
Share on other sites

Hey Marty, I'll take a stab at this.

There are a few issues as I see things:

The Max Image Dimensions setting: "..... does not affect any images in the system, or images added via the API." but you have noted that already.

From your explanation it sounds like the images are already installed. You could resize everything using the API, but then you'd end up with the original sized one as the main image still, but will the sized variation available - I don't think this would help much.

So if you upload using the API, you'll need to do the resize yourself. Of course the $image->size() method in the PW API will add the .XxY suffix to the filenames.

So I have a couple of scripts for you. This first one allows you to install an image using the API and have it resized to match the Max dimensions settings. This assumes your images field is called "images". I don't think this specifically helps you since you already have the images installed, but I wanted to post this in case it helps someone else. Read below for the next version which I think does what you need.

$cp = $pages->get("/");

$url_to_image = "http://ian.umces.edu/images/ian_banner.png";
$cp->images->add($url_to_image);
$cp->of(false);
$cp->save("images");
        
$pagefile = $cp->images->last();

$imagesfield = $cp->fields->get("name=images");               

$filename = $pagefile->filename; 
$pagefile2 = null;

if($imagesfield->maxWidth && $pagefile->width > $imagesfield->maxWidth) {
    $pagefile2 = $pagefile->width($imagesfield->maxWidth); 
    unlink($pagefile->filename); 
    rename($pagefile2->filename, $pagefile->filename); 
    $pagefile->getImageInfo(true); // force it to reload it's dimensions
}

if($imagesfield->maxHeight && $pagefile->height > $imagesfield->maxHeight) {
    $pagefile2 = $pagefile->height($imagesfield->maxHeight); 
    unlink($pagefile->filename); 
    rename($pagefile2->filename, $pagefile->filename); 
    $pagefile->getImageInfo(true); 
}
 

I think this code should do what you need. Obviously the first line sets the $cp to the home page, so you'll need to adjust as necessary. After that it runs through all the image fields on that page and resizes the images to match the values in the Max Dimensions settings. Let me know how you go with it.

$cp = $pages->get("/");

$cp->of(false); // required for a single image field
foreach($cp->fields as $imagesfield){

   if($imagesfield->type == "FieldtypeImage"){

        foreach($cp->$imagesfield as $pagefile){    

            $filename = $pagefile->filename; 
            $pagefile2 = null;

            if($imagesfield->maxWidth && $pagefile->width > $imagesfield->maxWidth) {
                $pagefile2 = $pagefile->width($imagesfield->maxWidth); 
                unlink($pagefile->filename); 
                rename($pagefile2->filename, $pagefile->filename); 
                $pagefile->getImageInfo(true); // force it to reload it's dimensions
            }

            if($imagesfield->maxHeight && $pagefile->height > $imagesfield->maxHeight) {
                $pagefile2 = $pagefile->height($imagesfield->maxHeight); 
                unlink($pagefile->filename); 
                rename($pagefile2->filename, $pagefile->filename); 
                $pagefile->getImageInfo(true); 
            } 
        
        }
   }
}
 

Both examples are quite verbose and I am sure could be optimized quite a bit, but should get the job done. I did some testing and they both seem to work just fine.

  • Like 3
Link to comment
Share on other sites

Hey Marty, I did a quick test with a CropImage field and so long as you change:

if($imagesfield->type == "FieldtypeImage"){

for

if($imagesfield->type == "FieldtypeImage" || $imagesfield->type == "FieldtypeCropImage"){

it seems to work fine. Of course it will only resize the main image, and not the cropped version.

I haven't tested this with Custom Upload Names yet, but I can't think of any reason why it wouldn't work.

Link to comment
Share on other sites

Thanks for your help with this. Just to be sure I've disabled Custom Upload Names for the moment. I'm trying this on a specific problem page but it's only doing the very first image, creating a new one with a suffix of '0x1600' and not changing the actual dimensions.

Link to comment
Share on other sites

Weird - just to be sure, you are definitely using the second script that I posted above?

I just tested again and it works fine on multiple images in a field.

Could you maybe post the exact code you are using if it differs at all from what I posted and maybe detail out all the settings for your images field. I can't think of what the issue might be at the moment.

Link to comment
Share on other sites

Ok, here is my test. I emptied the Max Dimensions settings and uploaded two images and got this:

post-985-0-12390700-1393782822_thumb.jpg

Then I went and changed the Max Width setting to 50 and left the height blank. Then I ran that script I gave you and then reloaded the page and I see this:

post-985-0-59740400-1393782813_thumb.jpg

That is the behaviour you're looking for - right?

Link to comment
Share on other sites

The only change I made was to target the specific page I was having trouble with - I can't load it in the admin. I'm running this site locally too so I don't know if that helps.

<?
$cp = $pages->get(1157);

$cp->of(false); // required for a single image field
foreach($cp->fields as $imagesfield){

if($imagesfield->type == "FieldtypeImage" || $imagesfield->type == "FieldtypeCropImage"){

        foreach($cp->$imagesfield as $pagefile){    

            $filename = $pagefile->filename; 
            $pagefile2 = null;

            if($imagesfield->maxWidth && $pagefile->width > $imagesfield->maxWidth) {
                $pagefile2 = $pagefile->width($imagesfield->maxWidth); 
                unlink($pagefile->filename); 
                rename($pagefile2->filename, $pagefile->filename); 
                $pagefile->getImageInfo(true); // force it to reload it's dimensions
            }

            if($imagesfield->maxHeight && $pagefile->height > $imagesfield->maxHeight) {
                $pagefile2 = $pagefile->height($imagesfield->maxHeight); 
                unlink($pagefile->filename); 
                rename($pagefile2->filename, $pagefile->filename); 
                $pagefile->getImageInfo(true); 
            } 
        
        }
   }
}
?>

Yes that definately the behaviour I'm looking for. Perhaps it's the CropImage field that the issue. I see you're using the standard image field.

Link to comment
Share on other sites

Here's the same deal with a crop image field.

Before:

post-985-0-30760500-1393783496_thumb.jpg

After:

post-985-0-14825700-1393783492_thumb.jpg

Maybe not terribly helpful sending you screenshots of it working for me though :)

EDIT: I can't imagine why it would matter, but are you running PW 2.4 on this site? I am testing on 2.4.1.

MORE THOUGHTS:

Are the initial images that you're trying to resize named without the dimensions suffix? I assume so, but just checking.

Maybe you could send screenshots of your before and after and also the before and after filenames in the 1157 folder. Might help us figure it out.

Edited by adrian
Link to comment
Share on other sites

As they say on television "it's not you, it's me". My memory limit and max_execution_time on MAMP needed boosting.

With this project I'm hoping to batch import perhaps 350 artists (nearly 4000 images) with Ryan's module so I think I need to work out a way of getting the images smaller beforehand. If I get this job I might need some paid help :)

Thanks very much for your help Adrian.

  • Like 1
Link to comment
Share on other sites

No problem at all. I learned some things along the way :)

Speaking of which, here is a much more concise version of the script using the ImageSizer approach I picked up from Soma at some point:

$cp = $pages->get(1157);

$cp->of(false);
foreach($cp->fields as $imagesfield){
   if($imagesfield->type == "FieldtypeImage" || $imagesfield->type == "FieldtypeCropImage"){
        foreach($cp->$imagesfield as $image){    
            $ImageSizer = new ImageSizer($image->filename);
            $ImageSizer->resize($imagesfield->maxWidth,$imagesfield->maxHeight);    
        }
   }
}

As for the memory issues. If it's just max_execution_time that should be an easy fix. If it is also memory related then you might come up against a barrier, no matter where you set the limit if you have too many images. You might need to do it in batches, which you could automate by simply adding a check to see if the dimensions of the image already match what they are meant to be. That way on each batch you'd skip by those that have already been resized. I think that might be a decent approach, but maybe someone else will chime in on this.

You also might be better off bootstrapping PW from a php file and running that from the command line.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...