php – 将32位TGA转换为PNG
我在
this code工作,并考虑到“修复”它为32位的评论,但似乎仍然无法正常工作.我很确定它与
TGA descriptor有关.这将使用位0-3作为alpha通道深度,对于32位总是为8,并且代码没有考虑到这一点.
我试图了解如何使用this C code作为指导将它拼凑在一起,但没有运气. 似乎一旦你考虑到长度为4的像素(根据评论中的补丁),他的dwordize只占4个字节中的3个,第4个字节是我认为的alpha位. 我试过更改功能 function dwordize($str) { $a = ord($str[0]); $b = ord($str[1]); $c = ord($str[2]); return $c*256*256 + $b*256 + $a; } 至 function dwordize($str) { $a = ord($str[0]); $b = ord($str[1]); $c = ord($str[2]); $d = ord($str[3]); return $d*256*256*256 + $c*256*256 + $b*256 + $a; } 哪个没用,然后试了 function dwordize($str) { $a = ord($str[0]); $b = ord($str[1]); $c = ord($str[2]); $d = ord($str[3]); return $c*256*256 + $b*256 + $a + $d*256*256*256; } 所有这些我试图从像RBGA到BGRA的C代码,然后索引都很奇怪.我真的不明白C代码足以将它应用于PHP代码. 我也找到了this site这可能会有所帮助,我现在正在读它,如果我拿出任何东西我会更新. 解决方法
我找到了你的解决方案.在RLE解码函数中需要进行缺少调整以支持32位像素格式:即:AARRGGBB
首先,我们需要按照评论中的建议绕过库的颜色深度检查,因此我们将检查更改为第99行 if ($header['pixel_size'] != 24 && $header['pixel_size'] != 32) { die('Unsupported TGA color depth'); } 然后我们需要更改一些与颜色深度相关的变量.它们中的大多数将用于数据格式化,因此无论颜色深度如何,我们都需要它们具有正确的值. 第104行:$bytes = $header [‘pixel_size’] / 8; 第117行:$size = $header [‘width’] * $header [‘height’] * $bytes; 第154行:$pixels = str_split($data,$bytes); 并删除第153行:$num_bytes = $header [‘pixel_size’] / 8;我们不再需要它了. 然后我们需要rle_decode()函数来知道像素格式的大小,因此当我们调用它时,我们需要传递这个参数,因此我们需要更改以下行: 第141行:$data = rle_decode($data,$size,$bytes); 因此函数原型变为: 第9行:函数rle_decode($data,$datalen,$pixel_size) 现在你可以看到这个函数有多个3个幻数(即:for($j = 0; $j< 3 * $value; $j)在29行). 此外,有时在创建像素时它只会写入3个字节而不是4个字节,所以我们也必须调整它. 所以最后这给了我们以下算法: function rle_decode($data,$pixel_size) { $len = strlen($data); $out = ''; $i = 0; $k = 0; while ($i<$len) { dec_bits(ord($data[$i]),$type,$value); if ($k >= $datalen) { break; } $i++; if ($type == 0) //raw { for ($j=0; $j<$pixel_size*$value; $j++) { $out .= $data[$j+$i]; $k++; } $i += $value*$pixel_size; } else //rle { for ($j=0; $j<$value; $j++) { $out .= $data[$i] . $data[$i+1] . $data[$i+2]; if ($pixel_size == 4) $out .= $data[$i+3]; $k++; } $i += $pixel_size; } } return $out; } 就是这样,你现在可以完美地转换你的TGA图像.我给你完整的tga.php代码,所以你可以直接粘贴它并自己测试它: <?php // Author: de77 // Licence: MIT // First-version: 9.02.2010 // Version: 24.08.2010 // http://de77.com function rle_decode($data,$value); if ($k >= $datalen) { break; } $i++; if ($type == 0) //raw { for ($j=0; $j<$pixel_size*$value; $j++) { $out .= $data[$j+$i]; $k++; } $i += $value*$pixel_size; } else //rle { for ($j=0; $j<$value; $j++) { $out .= $data[$i] . $data[$i+1] . $data[$i+2]; if ($pixel_size == 4) $out .= $data[$i+3]; $k++; } $i += $pixel_size; } } return $out; } function dec_bits($byte,&$type,&$value) { $type = ($byte & 0x80) >> 7; $value = 1 + ($byte & 0x7F); } function getimagesizetga($filename) { $f = fopen($filename,'rb'); $header = fread($f,18); $header = @unpack( "cimage_id_len/ccolor_map_type/cimage_type/vcolor_map_origin/vcolor_map_len/" . "ccolor_map_entry_size/vx_origin/vy_origin/vwidth/vheight/" . "cpixel_size/cdescriptor",$header); fclose($f); $types = array(0,1,2,3,9,10,11,32,33); if (!in_array($header['image_type'],$types)) { return array(0,0); } if ($header['pixel_size'] > 32) { return array(0,0); } return array($header['width'],$header['height'],'tga',$header['pixel_size'],$header['image_type']); } function imagecreatefromtga($filename) { $f = fopen($filename,'rb'); if (!$f) { return false; } $header = fread($f,18); $header = unpack( "cimage_id_len/ccolor_map_type/cimage_type/vcolor_map_origin/vcolor_map_len/" . "ccolor_map_entry_size/vx_origin/vy_origin/vwidth/vheight/" . "cpixel_size/cdescriptor",$header); switch ($header['image_type']) { case 2: echo "Image is not compressedn";//no palette,uncompressed case 10: //no palette,rle break; default: die('Unsupported TGA format'); } if ($header['pixel_size'] != 24 && $header['pixel_size'] != 32) { die('Unsupported TGA color depth'); } $bytes = $header['pixel_size'] / 8; if ($header['image_id_len'] > 0) { $header['image_id'] = fread($f,$header['image_id_len']); } else { $header['image_id'] = ''; } $im = imagecreatetruecolor($header['width'],$header['height']); $size = $header['width'] * $header['height'] * $bytes; //-- check whether this is NEW TGA or not $pos = ftell($f); fseek($f,-26,SEEK_END); $newtga = fread($f,26); if (substr($newtga,8,16) != 'TRUEVISION-XFILE') { $newtga = false; } fseek($f,SEEK_END); $datasize = ftell($f) - $pos; if ($newtga) { $datasize -= 26; } fseek($f,$pos,SEEK_SET); //-- end of check $data = fread($f,$datasize); if ($header['image_type'] == 10) { $data = rle_decode($data,$bytes); } if (bit5($header['descriptor']) == 1) { $reverse = true; } else { $reverse = false; } $i = 0; $pixels = str_split($data,$bytes); //read pixels if ($reverse) { for ($y=0; $y<$header['height']; $y++) { for ($x=0; $x<$header['width']; $x++) { imagesetpixel($im,$x,$y,dwordize($pixels[$i])); $i++; } } } else { for ($y=$header['height']-1; $y>=0; $y--) { for ($x=0; $x<$header['width']; $x++) { imagesetpixel($im,dwordize($pixels[$i])); $i++; } } } fclose($f); return $im; } function dwordize($str) { $a = ord($str[0]); $b = ord($str[1]); $c = ord($str[2]); return $c*256*256 + $b*256 + $a; } function bit5($x) { return ($x & 32) >> 5; } 这是从脚本直接创建的输出PNG图像: 如果你更喜欢直接下载链接而不是粘贴固定代码,我在这里给你完整的php文件:https://www.sendspace.com/file/92uir9 在一天结束时,只需更改tga.php文件,一切都将自动运行. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |