donglong1465
2015-06-02 19:27 阅读 121

从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 ?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • dsfgds4215 dsfgds4215 2015-06-03 09:55

    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);
    ?>
    
    点赞 评论 复制链接分享

相关推荐