Class it:

/**
 * Convert an image to a given size and type (ensures input is an image)
 * @param $p['in']        Input filename (mandatory)
 * @param $p['out']        Output filename (mandatory)
 * @param $p['size']        Width x height of resulting image, e.g. "160x60"
 * @param $p['type']        Output file type, e.g. "jpg"
 * @param $p['types']        Comma separated list of accepted input types, default "bmp,eps,gif,jp2,jpg,png,svg,tif"
 * @param $p['quality']        JPEG quality (0-100), default is 75
 * @param $p['keepalpha']    Don't add option --flatten to preserve alpha channel
 * @param $p['pngcrush']  Use pngcrush for sm
 * @param $p['-opts']        Custom command line options to ImageMagick convert
 * @return Success of convert as true/false
 */
static function imageconvert($p)
{
    if (!((
$imagetype = @exif_imagetype($p['in'])) && ($type image_type_to_extension($imagetypefalse))))
    {
        if (
get_class((object)it_xml::create(it::fopen($p['in'], "r"), array('prefix' => "_imageconvert_"'safety' => 0))) == "_imageconvert_svg")
            
$type "svg"# Accept SVG files if they are valid XML and root tag is svg
        
else
            list(, 
$type) = explode(' 'strtolower(it::exec('identify 2>/dev/null {in}'$p))); # for things like eps
    
}

    
# emulate -auto-orient which is not supported by GM
    
if ($p['-opts']['-auto-orient'])
    {
        
$exif = @exif_read_data($p['in'], 'IFD0');
        switch (
$exif['Orientation'])
        {
            case 
2$p['-opts']['-flop'] = true;  break;
            case 
3$p['-opts']['-rotate'] = 180; break;
            case 
4$p['-opts']['-flip'] = true;  break;
            case 
6$p['-opts']['-rotate'] = 90;  break;
            case 
8$p['-opts']['-rotate'] = 270; break;
        }

        unset(
$p['-opts']['-auto-orient']);
    }

    
$type strtr($type, array("jpeg" => "jpg""tiff" => "tif""ps" => "eps""ept" => "eps"));
    
$p += array('type' => $type'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif"'quality' => 75);
    
$p['-opts'] = array('-thumbnail' => $p['size'], '-quality' => $p['quality']) + (array)$p['-opts'];

    if (!
$p['keepalpha'])
        
$p['-opts'] = array_merge(array('-flatten' => true), $p['-opts']);    # Option -flatten must be first

    
$ultratimeout file_exists("/opt/ultra/bin/ultratimeout") ? "/opt/ultra/bin/ultratimeout 30 " "";

    if (
in_array($typeexplode(','$p['types'])))    # Valid type?
        
$cmdoutput it::exec('( ' $ultratimeout 'gm convert -limit threads 2 2>&1 {-opts} {in} {type}:{out} || echo "SHELL ERROR $?" ) | grep -Ev "( iCCP: | Invalid SOS parameters for sequential JPEG | profile matches .* but writing .* instead | inconsistent chromacities )"'$p);

    if (
$p['pngcrush'] && $p['type'] == "png")
        
it::exec('pngcrush.sh 2>/dev/null {out} {out}.tmp && mv {out}.tmp {out} || rm {out}.tmp'$p);

    return 
$cmdoutput === "";
}