protected function compressPng(string $file, array $args = []): bool
    {
        if (!$this->c::canCallFunc('exec')) {
            return false;
        }
        $default_args = [
            'min_quality' => 0,
            'max_quality' => 0,
            'output_file' => '',
        ];
        $args += $default_args; // Defaults.

        if (!$file || !is_file($file)) {
            return false; // Not possible.
        }
        $args['min_quality'] = (int) ($args['min_quality'] ?: 60);
        $args['min_quality'] = max(0, min(100, $args['min_quality']));

        $args['max_quality'] = (int) ($args['max_quality'] ?: 90);
        $args['max_quality'] = max($args['min_quality'], min(100, $args['max_quality']));

        $args['output_file'] = (string) $args['output_file'];
        $args['output_file'] = $args['output_file'] ?: $file;

        $output_file_existed_prior = is_file($args['output_file']);

        $esc_file        = $this->c::escShellArg($file);
        $esc_output_file = $this->c::escShellArg($args['output_file']);
        $esc_quality     = $this->c::escShellArg($args['min_quality'].'-'.$args['max_quality']);
        exec('pngquant --skip-if-larger --quality='.$esc_quality.' --force --output='.$esc_output_file.' '.$esc_file, $_, $status);

        if ($status === 0) {
            return true; // Success.
            //
        } elseif (in_array($status, [98, 99], true)) {
            if ($args['output_file'] !== $file) {
                return copy($file, $args['output_file']);
            } else {
                return true;
            } // See `$ man pngquant` for further details.
            // `98` = --skip-if-larger, `99` = --quality min-max.
        } else {
            if (!$output_file_existed_prior && is_file($args['output_file'])) {
                unlink($args['output_file']);
            }
            return false;
        }
    }
protected function compressPng(string $file, array $args = []): bool
    {
        if (!$this->c::canCallFunc('exec')) {
            return false;
        }
        $default_args = [
            'min_quality' => 0,
            'max_quality' => 0,
            'output_file' => '',
        ];
        $args += $default_args; // Defaults.

        if (!$file || !is_file($file)) {
            return false; // Not possible.
        }
        $args['min_quality'] = (int) ($args['min_quality'] ?: 60);
        $args['min_quality'] = max(0, min(100, $args['min_quality']));

        $args['max_quality'] = (int) ($args['max_quality'] ?: 90);
        $args['max_quality'] = max($args['min_quality'], min(100, $args['max_quality']));

        $args['output_file'] = (string) $args['output_file'];
        $args['output_file'] = $args['output_file'] ?: $file;

        $output_file_existed_prior = is_file($args['output_file']);

        $esc_file        = $this->c::escShellArg($file);
        $esc_output_file = $this->c::escShellArg($args['output_file']);
        $esc_quality     = $this->c::escShellArg($args['min_quality'].'-'.$args['max_quality']);
        exec('pngquant --skip-if-larger --quality='.$esc_quality.' --force --output='.$esc_output_file.' '.$esc_file, $_, $status);

        if ($status === 0) {
            return true; // Success.
            //
        } elseif (in_array($status, [98, 99], true)) {
            if ($args['output_file'] !== $file) {
                return copy($file, $args['output_file']);
            } else {
                return true;
            } // See `$ man pngquant` for further details.
            // `98` = --skip-if-larger, `99` = --quality min-max.
        } else {
            if (!$output_file_existed_prior && is_file($args['output_file'])) {
                unlink($args['output_file']);
            }
            return false;
        }
    }
protected function compressPng ( string $ file , array $ args = [ ] ) : bool { if ( ! $ this -> c :: canCallFunc ( 'exec' ) ) { return false ; } $ default_args = [ 'min_quality' => 0 , 'max_quality' => 0 , 'output_file' => '' , ] ; $ args += $ default_args ; // Defaults. if ( ! $ file || ! is_file ( $ file ) ) { return false ; // Not possible. } $ args [ 'min_quality' ] = ( int ) ( $ args [ 'min_quality' ] ? : 60 ) ; $ args [ 'min_quality' ] = max ( 0 , min ( 100 , $ args [ 'min_quality' ] ) ) ; $ args [ 'max_quality' ] = ( int ) ( $ args [ 'max_quality' ] ? : 90 ) ; $ args [ 'max_quality' ] = max ( $ args [ 'min_quality' ] , min ( 100 , $ args [ 'max_quality' ] ) ) ; $ args [ 'output_file' ] = ( string ) $ args [ 'output_file' ] ; $ args [ 'output_file' ] = $ args [ 'output_file' ] ? : $ file ; $ output_file_existed_prior = is_file ( $ args [ 'output_file' ] ) ; $ esc_file = $ this -> c :: escShellArg ( $ file ) ; $ esc_output_file = $ this -> c :: escShellArg ( $ args [ 'output_file' ] ) ; $ esc_quality = $ this -> c :: escShellArg ( $ args [ 'min_quality' ] . '-' . $ args [ 'max_quality' ] ) ; exec ( 'pngquant --skip-if-larger --quality=' . $ esc_quality . ' --force --output=' . $ esc_output_file . ' ' . $ esc_file , $ _ , $ status ) ; if ( $ status === 0 ) { return true ; // Success. // } elseif ( in_array ( $ status , [ 98 , 99 ] , true ) ) { if ( $ args [ 'output_file' ] !== $ file ) { return copy ( $ file , $ args [ 'output_file' ] ) ; } else { return true ; } // See `$ man pngquant` for further details. // `98` = --skip-if-larger, `99` = --quality min-max. } else { if ( ! $ output_file_existed_prior && is_file ( $ args [ 'output_file' ] ) ) { unlink ( $ args [ 'output_file' ] ) ; } return false ; } }
Compress PNG image.

@since 161011 Initial release.

@param string $file PNG file path.
@param array  $args Behavioral args.

@return bool True on success.

@see https://pngquant.org/php.html
Compress PNG image .