2009-10-18 5 views
5

PHP에서 GD 라이브러리를 사용하여 비트 맵 파일을 JPEG로 변환하는 방법을 알아 내려고 노력했습니다.PHP에서 GD 라이브러리를 사용하여 비트 맵 파일을 JPEG로 변환

많은 구현을 시도했지만 아무 것도 작동하지 않는 것 같습니다. 내 고객에게 비트 맵 파일을 사용하지 않아야한다고 말했지만 실제로 솔직하게 JPG로 변환 할 수있는 컴퓨터에 대해서는 충분히 이해하지 못했습니다.

이 서버에서 ImageMagick을 사용할 수 없으며 순수한 GD 솔루션이 필요합니다. 모든 도움을 위해 미리 감사드립니다.

EDIT : 사용되는 비트 맵 이미지가 16 비트이며, 문제가 발생하는 위치 즉

.

나는 좀 .... 내가 작업 한이 기능을 가지고 : 당신이 왼쪽에있는 이미지를 보면

Uploaded Image

:

function ImageCreateFromBMP($filename) { 
    if (! $f1 = fopen($filename,"rb")) return FALSE; 

    $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14)); 
    if ($FILE['file_type'] != 19778) return FALSE; 

    $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'. 
     '/Vcompression/Vsize_bitmap/Vhoriz_resolution'. 
     '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40)); 
    $BMP['colors'] = pow(2,$BMP['bits_per_pixel']); 

    if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset']; 
    $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8; 
    $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']); 
    $BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4); 
    $BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4); 
    $BMP['decal'] = 4-(4*$BMP['decal']); 
    if ($BMP['decal'] == 4) $BMP['decal'] = 0; 

    $PALETTE = array(); 
    if ($BMP['colors'] < 16777216 && $BMP['colors'] != 65536) { 
     $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4)); 
    } 

    $IMG = fread($f1,$BMP['size_bitmap']); 
    $VIDE = chr(0); 

    $res = imagecreatetruecolor($BMP['width'],$BMP['height']); 
    $P = 0; 
    $Y = $BMP['height']-1; 
    while ($Y >= 0) { 
     $X=0; 
     while ($X < $BMP['width']) { 
      if ($BMP['bits_per_pixel'] == 24) 
       $COLOR = unpack("V",substr($IMG,$P,3).$VIDE); 
      elseif ($BMP['bits_per_pixel'] == 16) { 
       $COLOR = unpack("v",substr($IMG,$P,2)); 
       $blue = ($COLOR[1] & 0x001f) << 3; 
       $green = ($COLOR[1] & 0x07e0) >> 3; 
       $red = ($COLOR[1] & 0xf800) >> 8; 
       $COLOR[1] = $red * 65536 + $green * 256 + $blue; 
      } 
      elseif ($BMP['bits_per_pixel'] == 8) { 
       $COLOR = unpack("n",$VIDE.substr($IMG,$P,1)); 
       $COLOR[1] = $PALETTE[$COLOR[1]+1]; 
      } 
      elseif ($BMP['bits_per_pixel'] == 4) { 
       $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1)); 
       if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F); 
       $COLOR[1] = $PALETTE[$COLOR[1]+1]; 
      } 
      elseif ($BMP['bits_per_pixel'] == 1) { 
       $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1)); 
       if  (($P*8)%8 == 0) $COLOR[1] = $COLOR[1]  >>7; 
       elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6; 
       elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5; 
       elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4; 
       elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3; 
       elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2; 
       elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1; 
       elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1); 
       $COLOR[1] = $PALETTE[$COLOR[1]+1]; 
      } 
      else 
       return FALSE; 

      imagesetpixel($res,$X,$Y,$COLOR[1]); 

      $X++; 
      $P += $BMP['bytes_per_pixel']; 
     } 
     $Y--; 
     $P+=$BMP['decal']; 
    } 

    fclose($f1); 
    return $res; 
} 

결과 이미지가 이것이다 결과 이미지가 올바르게 정렬되어 있지 않은 것을 볼 수 있습니다. 작은 조각은 오른쪽에 있습니다. 코드가 어디에서 잘못 되었습니까? 문제는 16 비트 else-if에서 발생합니다.

모든 도움을 주셔서 다시 한 번 감사드립니다.

+0

코드를 확인했는데 문제가없는 것 같습니다. BMP 형식이 예상대로 (54 바이트, 팔레트 데이터 없음, 다음 이미지 데이터)입니까? 이것이 약간의 이국적인 BMP 변종이므로 헤더에이 "이동"오류를 유발하는 추가/더 적은 데이터가있을 수 있습니다. – schnaader

+0

솔직히 말해서 나는 이미지에서 어떤 일이 벌어지고 있는지 정말로 모른다. 사진 중 하나를 이메일로 보낼 수있는 방법이 있다면 사진을보실 수 있습니다 ... 지금 나는이 이미지 파일에 대해 지금보다 더 관심이 있습니다. 내가 연락 할 수있는 이메일은 gmail.com의 dphoebus이며 이미지 중 하나를 회신 해 드리겠습니다. –

답변

10

이 기능을 사용 :

http://www.programmierer-forum.de/function-imagecreatefrombmp-welche-variante-laeuft-t143137.htm

은 16 비트 및 32 비트와 같은 여러 비트 전송률을 지원합니다. 게다가 누락 된 파일 크기, 네거티브 색상 팔레트, 오류 출력, 추가 16 비트 마스크 헤더 (이것은 16 비트의 주요 문제점이었습니다) 및 감소 된 색상 팔레트 (biClrUsed)와 관련된 몇 가지 버그 수정이 포함되어 있습니다. 이 기능은 현재 DOMPDF의 일부이며 완벽하게 주어졌다 :

업데이트 2015 년)

는 당신이 그것을 좋아 바랍니다. 이제 압축 4 및 8 비트를 다루고 중요하지 않은 헤더는 무시하며 특수한 16 비트 565 마스크도 지원합니다.

+0

새 URL : https://github.com/dompdf/dompdf/blob/master/src/Helpers.php#L555 – Tominator

0

imagejpeg 기능은 어떻습니까?

GD에서 BMP 포맷을 지원하는 도움말을

bool imagejpeg (resource $image [, string $filename [, int $quality ]] )

imagejpeg() creates a JPEG file from the given image .

는, 예를 들어 살펴 here 있습니다.

EDIT : 원본 비트 맵 사양에서 지원하지 않는 16 비트 이미지를 지원하지 않습니다. 귀하의 경우, 색상 값을 코딩하는 데 사용되는 비트 패턴을 찾으십시오.

else if ($bits == 16) { 
$gd_scan_line = ""; 
$j = 0; 
while($j < $scan_line_size) { 
$byte1 = $scan_line{$j++}; 
$byte2 = $scan_line{$j++}; 
$b = chr($byte1 >> 3) * (255/31); 
$g = (chr($byte1 & 0x07) + chr($byte2 >> 5)) * (255/63); 
$r = chr($byte2 & 0x1F) * (255/31); 
$gd_scan_line .= "\x00$r$g$b"; 
} 

참고이 코드를 테스트하지 않았다 (I 위의 링크 된 코드에 삽입하시기 바랍니다) 나는 R과 B 5 비트, G 6 비트의 가정 순서는이 솔루션에 BGR입니다 (특히, 나는 0..255로 스케일링에 대해 확신하지 못한다.) 5-6-5 비트 패턴이 사용 되었다면 작동 할 것이다 (물론, 다른 것들과도 작동 할 것이다. 그러나 색상은 틀릴 것이다.).

+0

빠른 답장을 보내 주셔서 감사합니다.하지만 계속해서 같은 문제가 발생합니다. 클라이언트가 사용하는 비트 맵 파일은 16 비트 비트 맵 파일입니다. 내가 발견 한 모든 구현 (24 비트, 8 비트, 4 비트 및 1 비트 비트 맵) –

+0

다시 한번 감사드립니다. 나는이 해결책을 시도했다. 반환 된 결과 파일은 이미지의 전체 길이에 균등하게 간격을 둔 수평의 녹색 선이있는 단색 검정 이미지였습니다. –

0

GD는 기본적으로 BMP를 지원하지 않지만 약간 큰 이미지 검색은 imagecreatefrombmp() 함수의 fewuserlandimplementations을 제공합니다.

나는 그들을 시험하지는 않았지만, 적어도 그들 중 하나가 당신을 위해 일할 것이라고 확신합니다. 내 머리 위로 떨어져

+0

다시 한번 감사드립니다. 나는 그들 모두를 시험해 보았다. 다시 테스트 할 때 제출되는 비트 맵은 16 비트 파일임을 알 수 있습니다. 16 비트 이미지는 이러한 구현에서 설명되지 않습니다. –

0

는 :

function convert_to_jpeg($input_path, $output_path) 
{ 
    $image = imagecreatefromstring(file_get_contents($input_path)); 
    imagejpeg($image, $output_path); 
    imagedestroy($image); 
} 

즉 JPEG 파일을 어떤 형식 GD 입력으로 처리 할 수 ​​걸릴 출력됩니다. 여러분이 사용하고있는 GD의 버전을 모르지만, 내 .bmp 파일을 완벽하게 처리하고 이전 근무한 회사에서 사용했던 버전도 완벽하게 처리했습니다. (Mac OS X 10에서.6 및 CentOS 5)

편집 : 분실 한 imagedestroy! 아야!

+0

16 비트 BMP 파일에서도 작동 할 수 있기를 바랍니다 ... 가장 빠르고 우아한 솔루션입니다. – schnaader

+0

도와 주셔서 감사합니다. 나는 이것을 시도하고이 오류가 발생했습니다 : imagecreatefromstring() [function.imagecreatefromstring] : 데이터가 인식 된 형식이 아닙니다. 이것은 내 클라이언트가 사용하고있는 16 비트 비트 맵 때문일 수 있습니다. –

+0

필자는 16 비트 이미지를 보지 못했지만, 24 비트 및 RLE 인코딩 이미지조차도 정상적으로 작동하는 것으로 보입니다. – Kris

관련 문제