wasinger / htmlpagedom

jQuery-inspired DOM manipulation extension for Symfony's Crawler
MIT License
346 stars 50 forks source link

Images Resize #23

Closed skazhikadyadya closed 7 years ago

skazhikadyadya commented 7 years ago

Hi. Can i dynamically resize images from htmlpagedon?

For example, I can do that:

       $c = new HtmlPageCrawler($oneNews->getContent());
        foreach ($c->filter('img') as $newsImg)
        {
            $newsImg = HtmlPageCrawler::create($newsImg);
            $newsImg->filter('img')->removeAttribute('style');
            $newsImg->filter('img')->removeAttribute('width');
            $newsImg->filter('img')->setAttribute('alt', $oneNews->getTitle());
            $newsImg->filter('img')->addClass('img-responsive img-pim center-block thumbnail');
         ***** CAN I RESIZE IMAGE HERE, USING, LiipImagineBundle or others? *****
        }
        $oneNews->setContent(mb_convert_encoding($c->saveHTML(), 'UTF-8', 'HTML-ENTITIES'));

Thank you.

wasinger commented 7 years ago

While resizing the image has nothing to do with HTML manipulation, of course, you should be able to resize it:

  1. Get the "src" attribute of the image: $imgUrl = $newsImg->attr('src');
  2. From the image URL, get the file path to the real image if it is on your server, or fetch it to a temporary file. This of course depends on your application.
  3. Resize the image, save it and compute the URL of the resized image. For this task I personally use wasinger/adaptimage. It's exactly written for this purpose, but unfortunately the documentation is not up to date.
  4. Once you have the URL of the resized image set the "src" attribute: $newsImg->attr('src', $new_url);. You may want to update the "width" and "height" attributes, too.

Just a hint concerning your code example: if you filter for 'img' tags in the foreach loop, you should not need to filter for 'img' again, and you can chain the manipulation functions. Thus your code would look like so:

foreach ($c->filter('img') as $newsImg)
{
    $newsImg = HtmlPageCrawler::create($newsImg);
    $newsImg->removeAttribute('style')
            ->removeAttribute('width')
            ->setAttribute('alt', $oneNews->getTitle())
            ->addClass('img-responsive img-pim center-block thumbnail');
}
wasinger commented 7 years ago

Here is a simple example for resizing images using wasinger/adaptimage

use Wa72\AdaptImage\ImageFileInfo;
use Wa72\AdaptImage\ImageResizeDefinition;
use Wa72\AdaptImage\ImageResizer;
use Wa72\AdaptImage\Output\OutputPathGeneratorBasedir;

// create an ImageResizer instance using an Imagine instance
// and an OutputPathGeneratorBasedir that will put the generated resized images to a cache dir.
// Typically this will be put into a Symfony service definition.
$imgResizer = new ImageResizer(new \Imagine\Gd\Imagine(), new OutputPathGeneratorBasedir('/path/to/cache_dir'));

// define one or more ImageResizeDefinitions (pre-defined image sizes)
// in this example width is set to 500px
$small = ImageResizeDefinition::create('500');

// Get the ImageFileInfo object from the original image file
$original_image_fileinfo = ImageFileInfo::createFromFile('/path/to/image.jpg');

// Resize the image and get an ImageFileInfo object for the resized image
$resized_image_fileinfo = $imgResizer->resize($small, $original_image_fileinfo, true); // (1)

// now you can get the properties of the resized image:
$resized_images_pathname = $resized_image_fileinfo->getPathname();
$resized_image_width = $resized_image_fileinfo->getWidth();
$resized_image_height = $resized_image_fileinfo->getHeight();
$resized_image_mimetype = $resized_image_fileinfo->getMimetype();

(1) If you don't pass "true" to the $imgResizer->resize function call, you will get the ImageFileInfo object containing the properties of the resized image, but in fact the resized image will not be created. This will greatly improve the performance when this function is used in foreach-loops over all img elements in an HTML page. This way you are able to insert the correct resized image paths and dimensions into the HTML code before the images are actually resized. You must then load all resized images not directly by filesystem URL but via a PHP controller that actually creates the resized image when it is requested.

wasinger commented 7 years ago

Using wasinger/adaptimage, it is also possible to convert the img-Tags in an HTML page to "responsive images" with "srcset" and "sizes" attributes.

Documentation for this is not done yet, but there are lots of comments in the source code, please have a look at the Wa72\AdaptImage\ResponsiveImages\ResponsiveImageHelper class.

The main steps to do would be the following:

  1. Create a MyResponsiveImageRouter class implementing Wa72\AdaptImage\ResponsiveImages\ResponsiveImageRouterInterface. This router class is reponsible for creating URLs for your resized images, and finding the image file in the file system from a given URL. There is no example for it because it highly depends on your application.

  2. Define "Classes" for the responsive images in your application: All images of one class share the same "sizes" attribute, i.e. the have the same size constraints. Typically you could have classes like "header" for header images, "left" for the left column, and "content" for images in the main content column. A header image class could be defined like so:

    
    use Wa72\AdaptImage\ResponsiveImages\ResponsiveImageClass;

$headerclass = new ResponsiveImageClass( 'header', // name [640, 1034, 2068], // available image widths to be generated '(min-width: 1245px) 1034px, (min-width: 1035px) 83vw, (min-width: 768px) 85vw, 100vw', // HTML "sizes" attribute 0, // height constraint 1034 // default image width (for old browsers) );


3. Create a `ResponsiveImageHelper` object:
```php
use Wa72\AdaptImage\ResponsiveImages\ResponsiveImageHelper;

$rih = new ResponsiveImageHelper(
    new MyResponsiveImageRouter(); // Class created in Step 1
    new \Imagine\Gd\Imagine(),
    new OutputPathGeneratorBasedir('/path/to/image_cache_dir')
);

$rih->addClass($headerclass); // add all ResponsiveImageClass instances defined in Step 2
  1. Make the img-Elements in your HTML page responsive (adding the correct 'srcset' and 'sizes' attributes) by calling $rih->makeImgElementResponsive($img, $class). Example:

    $hc = HtmlPageCrawler::create('my.html');
    $images = $hc->filter('img.header'); // find all images with class 'header'
    foreach ($images as $image) {
    $rih->makeImgElementResponsive($image, $headerclass)
    }
  2. Create an image controller action that uses the ResponsiveImageHelper object to create the resized images on request:

    class ImageController extends Controller
    {
    public function imageAction(Request $request, $class, $width, $image)
    {
        $rih = $this->get('app.responsive_image_helper'); // assuming you have registered the ResponsiveImageHelper from step 2 as a symfony service
        $riv = $rih->getResizedImageVersion($image, $class, $width);
        $response = new BinaryFileResponse($riv->getFileinfo());
        $response->isNotModified($request);
        return $response;
    }
    }