I was able to solve it using the following code:
function my_handle_upload ( $params )
{
$filePath = $params['file'];
if ( (!is_wp_error($params)) && file_exists($filePath) && in_array($params['type'], array('image/png','image/gif','image/jpeg')))
{
$quality = 90;
list($largeWidth, $largeHeight) = array( get_option( 'large_size_w' ), get_option( 'large_size_h' ) );
list($oldWidth, $oldHeight) = getimagesize( $filePath );
list($newWidth, $newHeight) = wp_constrain_dimensions( $oldWidth, $oldHeight, $largeWidth, $largeHeight );
$resizeImageResult = image_resize( $filePath, $newWidth, $newHeight, false, null, null, $quality);
unlink( $filePath );
if ( !is_wp_error( $resizeImageResult ) )
{
$newFilePath = $resizeImageResult;
rename( $newFilePath, $filePath );
}
else
{
$params = wp_handle_upload_error
(
$filePath,
$resizeImageResult->get_error_message()
);
}
}
return $params;
}
add_filter( 'wp_handle_upload', 'my_handle_upload' );
The original file was 3,3Mb after it was uploaded, with large dimensions set to 2048×2048, it took only 375Kb on the server (about 90% reduction!)