i use imagick, you can see there working flow https://aitextured.com/image_converter/ :
function convertRasterWithImagick(string $src, string $to, array $opts): string {
$im = new Imagick();
$im->readImage($src);
$to = strtolower($to);
if ($to === 'jpg' || $to === 'jpeg') {
$quality = (int)($opts['quality'] ?? 90);
$bgHex = (string)($opts['bg'] ?? '#ffffff');
if ($im->getImageAlphaChannel()) {
[$r,$g,$b] = parseHexColor($bgHex);
$canvas = new Imagick();
$canvas->newImage($im->getImageWidth(), $im->getImageHeight(), new ImagickPixel("rgb($r,$g,$b)"));
$canvas->compositeImage($im, Imagick::COMPOSITE_OVER, 0, 0);
$im->destroy();
$im = $canvas;
}
$im->setImageFormat('jpeg');
$im->setImageCompression(Imagick::COMPRESSION_JPEG);
$im->setImageCompressionQuality($quality);
$tmp = tempnam(sys_get_temp_dir(), 'conv_').'.jpg';
$im->writeImage($tmp);
$im->destroy();
return $tmp;
}
if ($to === 'png') {
$im->setImageFormat('png');
$im->setImageCompression(Imagick::COMPRESSION_ZIP);
$im->setImageCompressionQuality(0);
$tmp = tempnam(sys_get_temp_dir(), 'conv_').'.png';
$im->writeImage($tmp);
$im->destroy();
return $tmp;
}
$im->destroy();
throw new RuntimeException('Unsupported target format for raster: '.$to);
}