从PHP读取Java Byte

I have a JAVA application who send compressed image over network. Each pixel value is converted into new Byte type. My problem is that I don't know how to correctly decode thos Byte with PHP.

Here is the JAVA compression:

public byte[] CompressedImage(BufferedImage img, int color_type) {
  if ((img.getType() != 2) && (img.getType() != 1)) {
    throw new RuntimeException("Image format not supported");
  }

  int sizeX = img.getWidth();  // 640px
  int sizeY = img.getHeight(); // 80px

  Vector compressedData = new Vector(sizeY * (1 + 3 * sizeX) + 1);
  DataBuffer data = img.getRaster().getDataBuffer();

  int count = 0;
  int nextPix = 0;
  int ptr = 0;
  for (int y = 0; y < sizeY; y++) {
    compressedData.add(new Byte((byte)-128));
    int currPix = data.getElem(ptr++);
    int x = 1;
    do{
      if (x < sizeX) {
        nextPix = data.getElem(ptr++);

        if ((nextPix == currPix) && (count < 63)) { 
          count++;
          continue;
        }
      }

      int color_R = (currPix & 0xFF0000) >> 16;
      int color_G = (currPix & 0xFF00) >> 8;
      int color_B = currPix & 0xFF;

      compressedData.add(new Byte((byte)((color_R & 0xFF) >> 1)));
      compressedData.add(new Byte((byte)((color_G & 0xFF) >> 1)));
      compressedData.add(new Byte((byte)((color_B & 0xFF) >> 1)));

      if (count != 0) {
        compressedData.add(new Byte((byte)(0xFFFFFFC0 | count)));
      }
      count = 0;
      currPix = nextPix;
    } while (x++ < sizeX);
  }

  byte[] result = new byte[compressedData.size()];
  Enumeration e = compressedData.elements();

  int i = 0;
  while (e.hasMoreElements()) {
    result[(i++)] = ((Byte)e.nextElement()).byteValue();
  }
  return result;
}

Using WireShark software I have been able to capture a packet with full image that I stored in a file "scalio.bin"

Now I try to read this scalio.bin file with PHP in order to recreate the image. I know that each -128 value means a new line I know that I should be able to get 4 values: R, G, B and count.

I tried to play with unpack() and sprintf() without real success:

$filename = "scalio.bin";
$handle = fopen($filename, "rb");
$content = fread($handle, filesize($filename));

/* METHOD 1 */
for ($i=0; $i<strlen($content); $i++){
  $v = sprintf("%d", bin2hex($content[$i]));
  if(hexdec($v) == 128) {
    $line++;
  } else {
    $imgArray[$line][] = hexdec($v);
  }
}

echo "<pre>";
print_r($imgArray);
echo "</pre>";

/* METHOD 2 */
$data  = unpack("c*", $content);
foreach($data as $val){
  switch($val){
    case -128:
      $line++;
      break;
    default:
      $imgArray[$line][] = $val;
  }
}

for($i=0; $i<sizeof($imgArray); $i++){
  $imgArray[$i] = array_chunk($imgArray[$i], 4);
}

echo "<pre>";
print_r($imgArray);
echo "</pre>";

I have read that Byte type is limited from -128 to 127 so I expect to get only value from -128 to 127 in my PHP code, but I get only hexadecimal value, or even char, or some large number like 4294967252

I've found that 'count' variable need a XOR to be reverted (i.e somethnig like $val ^ 0xFFFFFFC0 Also R, G, B value need to be shift back like ($val & 0xFF) << 1

Finally my question is: how to decode this .bin file who is plenty of JAVA Byte value from my PHP ?

dongpai2754
dongpai2754 我错过了下面的Java代码,老实说,我看不出它是如何解码的。如果您有一个用Java或其他语言编写的工作解码器,您可能希望从它开始作为基础,如果不是,您应该尝试首先使用您最熟悉的语言编写解码器。
5 年多之前 回复

1个回答

Finally I got it ! However I'm not very happy about performance. Any idea how I could optimize my code ?

<?php
$filename = "scalio.bin";
$handle   = fopen($filename, "rb");
$content = fread($handle, filesize($filename));

$line=-1;
$imgArray=array();

$arr=array("r", "g", "b");
$color=-1;
function getNextColor(){
  global $arr, $color;
  if($color > 1)
    $color = -1;
  $color++;
  return $arr[$color];
}

$pix=-1;
for ($i=0; $i<strlen($content); $i++){
  $buf   = bin2hex($content[$i]);
  $dec   = hexdec($buf);
  $bytes = (($dec+128)%256) -128;

  if($bytes == -128){
    $line++;
    $pix=-1;
  }elseif($bytes < 0){
    $b = substr(decbin($bytes), -8);
    $imgArray[$line][$pix]['count'] = (bindec($b) ^ 0xC0) + 1;
  }else{
    $col = getNextColor();
    $b = ($bytes & 0xFF) << 1;
    if($col == "r")
      $pix++;
    $imgArray[$line][$pix][$col] = $b;
  }
}

$sizeX = 640;
$sizeY = 80;
$gd = imagecreatetruecolor($sizeX, $sizeY);

$imgArrayTrue=array();
foreach($imgArray as $lineIndex=>$line){
  foreach($line as $pixelIndex=>$pixel){
    if( array_key_exists('count', $pixel) ){
      for($x=0; $x<$pixel['count']; $x++){
        $imgArrayTrue[$lineIndex][] = array("r"=>$pixel['r'], "g"=>$pixel['g'], "b"=>$pixel['b']);
      }
    }else{
      $imgArrayTrue[$lineIndex][] = $pixel;
    }
  }
}

foreach($imgArrayTrue as $lineIndex=>$line){
  foreach($line as $pixelIndex=>$pixel){
    $color = imagecolorallocate($gd, $pixel['r'], $pixel['g'], $pixel['b']);
    imagesetpixel($gd, $pixelIndex, $lineIndex, $color);
  }
}

header('Content-Type: image/gif');
imagegif($gd);
?>
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐