BMP to GD (then to JPG) - 32 bits?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ken

    BMP to GD (then to JPG) - 32 bits?

    I need to convert 32 bit Windows bitmaps to jpgs with PHP.

    I used the function from http://groups.google.com/groups?
    hl=en&lr=&ie=UT F-8&oe=UTF-8&safe=off&selm =a164f4b5.03113 02128.40fb37f4%
    40posting.googl e.com to convert bitmaps to jpgs.

    It works very well for my 24 bit bitmaps, but I cannot figure out how
    to
    get it to work with 32 bits. I tried adding an additional scan line
    and
    the image appears in the correct size, but the colors are way off and
    some of the data is missing. I also tried putting $a in different
    places within the $gd_scan_line string:

    This did not work:

    $b = $scan_line{$j++ };
    $g = $scan_line{$j++ };
    $r = $scan_line{$j++ };
    $a = $scan_line{$j++ };
    $gd_scan_line .= "\x$a$r$g$b ";

    Can anyone help?

    Ken
  • Guest's Avatar

    #2
    Re: BMP to GD (then to JPG) - 32 bits?

    > ...convert bitmaps to jpgs.

    Personally, my solution would be the following:
    a. a command-line application that converts one format to another
    b. file exists (check if the new file was created)
    c. PHP function getimagesize() to get info -

    "Index 2 is a flag indicating the type of the image: 1 = GIF, 2 = JPG, 3 =
    PNG, 4 = SWF, 5 = PSD, 6 = BMP, 7 = TIFF(intel byte order), 8 =
    TIFF(motorola byte order), 9 = JPC, 10 = JP2, 11 = JPX, 12 = JB2, 13 = SWC,
    14 = IFF, 15 = WBMP, 16 = XBM"

    Hope this helps --

    _______________ _______________ ______
    Wil Moore III, MCP | Integrations Specialist


    Comment

    • Chung Leong

      #3
      Re: BMP to GD (then to JPG) - 32 bits?


      "Ken" <hanson_kenneth @yahoo.com> wrote in message
      news:ea8389b0.0 406241003.151b8 cea@posting.goo gle.com...[color=blue]
      > I need to convert 32 bit Windows bitmaps to jpgs with PHP.
      >
      > I used the function from http://groups.google.com/groups?
      > hl=en&lr=&ie=UT F-8&oe=UTF-8&safe=off&selm =a164f4b5.03113 02128.40fb37f4%
      > 40posting.googl e.com to convert bitmaps to jpgs.
      >
      > It works very well for my 24 bit bitmaps, but I cannot figure out how
      > to
      > get it to work with 32 bits. I tried adding an additional scan line
      > and
      > the image appears in the correct size, but the colors are way off and
      > some of the data is missing. I also tried putting $a in different
      > places within the $gd_scan_line string:
      >
      > This did not work:
      >
      > $b = $scan_line{$j++ };
      > $g = $scan_line{$j++ };
      > $r = $scan_line{$j++ };
      > $a = $scan_line{$j++ };
      > $gd_scan_line .= "\x$a$r$g$b ";
      >
      > Can anyone help?
      >
      > Ken[/color]

      You were close. Should have been $gd_scan_line .= "$a$r$g$b". Actually, the
      GD library interprets the alpha value as transparency (255 = fully
      transparent) while Windows sees it as opacity (0 = fully transparent). So we
      actually need to substract $a from 255 to get the correct value.

      Here's the update code. Improved it a bit by avoiding the use of a temporary
      file.

      <?

      function ConvertBMP2GD($ src, $dest = false) {
      if(!($src_f = fopen($src, "rb"))) {
      trigger_error(" Can't open $src", E_WARNING);
      return false;
      }
      if(!($dest_f = fopen($dest, "wb"))) {
      trigger_error(" Can't open $dest", E_WARNING);
      return false;
      }
      $header = unpack("vtype/Vsize/v2reserved/Voffset", fread($src_f, 14));
      $info =
      unpack("Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyr
      es/Vncolor/Vimportant", fread($src_f, 40));

      extract($info);
      extract($header );

      if($type != 0x4D42) { // signature "BM"
      return false;
      }

      $palette_size = $offset - 54;
      $ncolor = $palette_size / 4;
      $gd_header = "";
      // true-color vs. palette
      $gd_header .= ($palette_size == 0) ? "\xFF\xFE" : "\xFF\xFF";
      $gd_header .= pack("n2", $width, $height);
      $gd_header .= ($palette_size == 0) ? "\x01" : "\x00";
      if($palette_siz e) {
      $gd_header .= pack("n", $ncolor);
      }
      // no transparency
      $gd_header .= "\xFF\xFF\xFF\x FF";

      fwrite($dest_f, $gd_header);

      if($palette_siz e) {
      $palette = fread($src_f, $palette_size);
      $gd_palette = "";
      $j = 0;
      while($j < $palette_size) {
      $b = $palette{$j++};
      $g = $palette{$j++};
      $r = $palette{$j++};
      $a = $palette{$j++};
      $gd_palette .= "$r$g$b$a";
      }
      $gd_palette .= str_repeat("\x0 0\x00\x00\x00", 256 - $ncolor);
      fwrite($dest_f, $gd_palette);
      }

      $scan_line_size = (($bits * $width) + 7) >> 3;
      $scan_line_alig n = ($scan_line_siz e & 0x03) ? 4 - ($scan_line_siz e & 0x03)
      : 0;

      for($i = 0, $l = $height - 1; $i < $height; $i++, $l--) {
      // BMP stores scan lines starting from bottom
      fseek($src_f, $offset + (($scan_line_si ze + $scan_line_alig n) * $l));
      $scan_line = fread($src_f, $scan_line_size );
      if($bits == 24) {
      $gd_scan_line = "";
      $j = 0;
      while($j < $scan_line_size ) {
      $b = $scan_line{$j++ };
      $g = $scan_line{$j++ };
      $r = $scan_line{$j++ };
      $gd_scan_line .= "\xFF$r$g$b ";
      }
      }
      else if($bits == 32) {
      $gd_scan_line = "";
      $j = 0;
      while($j < $scan_line_size ) {
      $b = $scan_line{$j++ };
      $g = $scan_line{$j++ };
      $r = $scan_line{$j++ };
      $a = chr(255 - ord($scan_line{ $j++}));
      $gd_scan_line .= "$a$r$g$b";
      }
      }
      else if($bits == 8) {
      $gd_scan_line = $scan_line;
      }
      else if($bits == 4) {
      $gd_scan_line = "";
      $j = 0;
      while($j < $scan_line_size ) {
      $byte = ord($scan_line{ $j++});
      $p1 = chr($byte >> 4);
      $p2 = chr($byte & 0x0F);
      $gd_scan_line .= "$p1$p2";
      } $gd_scan_line = substr($gd_scan _line, 0, $width);
      }
      else if($bits == 1) {
      $gd_scan_line = "";
      $j = 0;
      while($j < $scan_line_size ) {
      $byte = ord($scan_line{ $j++});
      $p1 = chr((int) (($byte & 0x80) != 0));
      $p2 = chr((int) (($byte & 0x40) != 0));
      $p3 = chr((int) (($byte & 0x20) != 0));
      $p4 = chr((int) (($byte & 0x10) != 0));
      $p5 = chr((int) (($byte & 0x08) != 0));
      $p6 = chr((int) (($byte & 0x04) != 0));
      $p7 = chr((int) (($byte & 0x02) != 0));
      $p8 = chr((int) (($byte & 0x01) != 0));
      $gd_scan_line .= "$p1$p2$p3$p4$p 5$p6$p7$p8";
      } $gd_scan_line = substr($gd_scan _line, 0, $width);
      }

      fwrite($dest_f, $gd_scan_line);
      }
      fclose($src_f);
      fclose($dest_f) ;
      return true;
      }


      class MemoryStream {
      var $position;
      var $varname;
      var $buffer;

      function stream_open($pa th, $mode, $options, &$opened_pat h)
      {
      $url = parse_url($path );
      $this->varname = $url["host"];
      $this->position = 0;
      $this->buffer = @$GLOBALS[$this->varname];

      return true;
      }

      function stream_close()
      {
      $GLOBALS[$this->varname] = $this->buffer;
      }

      function stream_read($co unt)
      {
      $ret = substr($this->buffer, $this->position, $count);
      $this->position += strlen($ret);
      return $ret;
      }

      function stream_write($d ata)
      {
      $this->buffer .= $data;
      $this->position += strlen($data);
      return strlen($data);
      }

      function stream_tell()
      {
      return $this->position;
      }

      function stream_eof()
      {
      return $this->position >= strlen($this->buffer);
      }

      function stream_stat() {
      return array( 'size' => strlen($this->buffer) );
      }
      }

      function imagecreatefrom bmp($filename) {
      // use a memory stream instead of a temp file
      // where possible
      if(function_exi sts('stream_wra pper_register')
      && stream_wrapper_ register("mem", "MemoryStream") ) {
      $tmp_name = "mem://GD_TMP_FILE";
      $del_tmp = false;
      }
      else {
      $tmp_name = tempnam("/tmp", "GD");
      $del_tmp = true;
      }
      if(ConvertBMP2G D($filename, $tmp_name)) {
      $img = imagecreatefrom gd($tmp_name);
      if($del_tmp) {
      unlink($tmp_nam e);
      }
      return $img;
      } return false;
      }

      $img = imagecreatefrom bmp("test32bit. bmp");
      imagealphablend ing($img, false);
      imagesavealpha( $img, true);
      imagepng($img, "test.png") ;

      ?>
      <img src="test.png">


      Comment

      • Ken

        #4
        Re: BMP to GD (then to JPG) - 32 bits?

        Thank you! This was a huge help! This worked great after I changed
        the png output to jpg. The png output made a properly sized image,
        but it was filled with all light blue pixels. I switched the output
        to jpg and it looks perfect!

        Here are my changes:

        $img = imagecreatefrom bmp("test32bit. bmp");
        imagealphablend ing($img, false);
        imagesavealpha( $img, true);
        imagejpeg($img, "test.jpg") ;

        Ken



        ?>
        <img src="test.jpg">


        "Chung Leong" <chernyshevsky@ hotmail.com> wrote in message news:<PqOdneKYw Oer60bdRVn-sA@comcast.com> ...[color=blue]
        > "Ken" <hanson_kenneth @yahoo.com> wrote in message
        > news:ea8389b0.0 406241003.151b8 cea@posting.goo gle.com...[color=green]
        > > I need to convert 32 bit Windows bitmaps to jpgs with PHP.
        > >
        > > I used the function from http://groups.google.com/groups?
        > > hl=en&lr=&ie=UT F-8&oe=UTF-8&safe=off&selm =a164f4b5.03113 02128.40fb37f4%
        > > 40posting.googl e.com to convert bitmaps to jpgs.
        > >
        > > It works very well for my 24 bit bitmaps, but I cannot figure out how
        > > to
        > > get it to work with 32 bits. I tried adding an additional scan line
        > > and
        > > the image appears in the correct size, but the colors are way off and
        > > some of the data is missing. I also tried putting $a in different
        > > places within the $gd_scan_line string:
        > >
        > > This did not work:
        > >
        > > $b = $scan_line{$j++ };
        > > $g = $scan_line{$j++ };
        > > $r = $scan_line{$j++ };
        > > $a = $scan_line{$j++ };
        > > $gd_scan_line .= "\x$a$r$g$b ";
        > >
        > > Can anyone help?
        > >
        > > Ken[/color]
        >
        > You were close. Should have been $gd_scan_line .= "$a$r$g$b". Actually, the
        > GD library interprets the alpha value as transparency (255 = fully
        > transparent) while Windows sees it as opacity (0 = fully transparent). So we
        > actually need to substract $a from 255 to get the correct value.
        >
        > Here's the update code. Improved it a bit by avoiding the use of a temporary
        > file.
        >
        > <?
        >
        > function ConvertBMP2GD($ src, $dest = false) {
        > if(!($src_f = fopen($src, "rb"))) {
        > trigger_error(" Can't open $src", E_WARNING);
        > return false;
        > }
        > if(!($dest_f = fopen($dest, "wb"))) {
        > trigger_error(" Can't open $dest", E_WARNING);
        > return false;
        > }
        > $header = unpack("vtype/Vsize/v2reserved/Voffset", fread($src_f, 14));
        > $info =
        > unpack("Vsize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyr
        > es/Vncolor/Vimportant", fread($src_f, 40));
        >
        > extract($info);
        > extract($header );
        >
        > if($type != 0x4D42) { // signature "BM"
        > return false;
        > }
        >
        > $palette_size = $offset - 54;
        > $ncolor = $palette_size / 4;
        > $gd_header = "";
        > // true-color vs. palette
        > $gd_header .= ($palette_size == 0) ? "\xFF\xFE" : "\xFF\xFF";
        > $gd_header .= pack("n2", $width, $height);
        > $gd_header .= ($palette_size == 0) ? "\x01" : "\x00";
        > if($palette_siz e) {
        > $gd_header .= pack("n", $ncolor);
        > }
        > // no transparency
        > $gd_header .= "\xFF\xFF\xFF\x FF";
        >
        > fwrite($dest_f, $gd_header);
        >
        > if($palette_siz e) {
        > $palette = fread($src_f, $palette_size);
        > $gd_palette = "";
        > $j = 0;
        > while($j < $palette_size) {
        > $b = $palette{$j++};
        > $g = $palette{$j++};
        > $r = $palette{$j++};
        > $a = $palette{$j++};
        > $gd_palette .= "$r$g$b$a";
        > }
        > $gd_palette .= str_repeat("\x0 0\x00\x00\x00", 256 - $ncolor);
        > fwrite($dest_f, $gd_palette);
        > }
        >
        > $scan_line_size = (($bits * $width) + 7) >> 3;
        > $scan_line_alig n = ($scan_line_siz e & 0x03) ? 4 - ($scan_line_siz e & 0x03)
        > : 0;
        >
        > for($i = 0, $l = $height - 1; $i < $height; $i++, $l--) {
        > // BMP stores scan lines starting from bottom
        > fseek($src_f, $offset + (($scan_line_si ze + $scan_line_alig n) * $l));
        > $scan_line = fread($src_f, $scan_line_size );
        > if($bits == 24) {
        > $gd_scan_line = "";
        > $j = 0;
        > while($j < $scan_line_size ) {
        > $b = $scan_line{$j++ };
        > $g = $scan_line{$j++ };
        > $r = $scan_line{$j++ };
        > $gd_scan_line .= "\xFF$r$g$b ";
        > }
        > }
        > else if($bits == 32) {
        > $gd_scan_line = "";
        > $j = 0;
        > while($j < $scan_line_size ) {
        > $b = $scan_line{$j++ };
        > $g = $scan_line{$j++ };
        > $r = $scan_line{$j++ };
        > $a = chr(255 - ord($scan_line{ $j++}));
        > $gd_scan_line .= "$a$r$g$b";
        > }
        > }
        > else if($bits == 8) {
        > $gd_scan_line = $scan_line;
        > }
        > else if($bits == 4) {
        > $gd_scan_line = "";
        > $j = 0;
        > while($j < $scan_line_size ) {
        > $byte = ord($scan_line{ $j++});
        > $p1 = chr($byte >> 4);
        > $p2 = chr($byte & 0x0F);
        > $gd_scan_line .= "$p1$p2";
        > } $gd_scan_line = substr($gd_scan _line, 0, $width);
        > }
        > else if($bits == 1) {
        > $gd_scan_line = "";
        > $j = 0;
        > while($j < $scan_line_size ) {
        > $byte = ord($scan_line{ $j++});
        > $p1 = chr((int) (($byte & 0x80) != 0));
        > $p2 = chr((int) (($byte & 0x40) != 0));
        > $p3 = chr((int) (($byte & 0x20) != 0));
        > $p4 = chr((int) (($byte & 0x10) != 0));
        > $p5 = chr((int) (($byte & 0x08) != 0));
        > $p6 = chr((int) (($byte & 0x04) != 0));
        > $p7 = chr((int) (($byte & 0x02) != 0));
        > $p8 = chr((int) (($byte & 0x01) != 0));
        > $gd_scan_line .= "$p1$p2$p3$p4$p 5$p6$p7$p8";
        > } $gd_scan_line = substr($gd_scan _line, 0, $width);
        > }
        >
        > fwrite($dest_f, $gd_scan_line);
        > }
        > fclose($src_f);
        > fclose($dest_f) ;
        > return true;
        > }
        >
        >
        > class MemoryStream {
        > var $position;
        > var $varname;
        > var $buffer;
        >
        > function stream_open($pa th, $mode, $options, &$opened_pat h)
        > {
        > $url = parse_url($path );
        > $this->varname = $url["host"];
        > $this->position = 0;
        > $this->buffer = @$GLOBALS[$this->varname];
        >
        > return true;
        > }
        >
        > function stream_close()
        > {
        > $GLOBALS[$this->varname] = $this->buffer;
        > }
        >
        > function stream_read($co unt)
        > {
        > $ret = substr($this->buffer, $this->position, $count);
        > $this->position += strlen($ret);
        > return $ret;
        > }
        >
        > function stream_write($d ata)
        > {
        > $this->buffer .= $data;
        > $this->position += strlen($data);
        > return strlen($data);
        > }
        >
        > function stream_tell()
        > {
        > return $this->position;
        > }
        >
        > function stream_eof()
        > {
        > return $this->position >= strlen($this->buffer);
        > }
        >
        > function stream_stat() {
        > return array( 'size' => strlen($this->buffer) );
        > }
        > }
        >
        > function imagecreatefrom bmp($filename) {
        > // use a memory stream instead of a temp file
        > // where possible
        > if(function_exi sts('stream_wra pper_register')
        > && stream_wrapper_ register("mem", "MemoryStream") ) {
        > $tmp_name = "mem://GD_TMP_FILE";
        > $del_tmp = false;
        > }
        > else {
        > $tmp_name = tempnam("/tmp", "GD");
        > $del_tmp = true;
        > }
        > if(ConvertBMP2G D($filename, $tmp_name)) {
        > $img = imagecreatefrom gd($tmp_name);
        > if($del_tmp) {
        > unlink($tmp_nam e);
        > }
        > return $img;
        > } return false;
        > }
        >
        > $img = imagecreatefrom bmp("test32bit. bmp");
        > imagealphablend ing($img, false);
        > imagesavealpha( $img, true);
        > imagepng($img, "test.png") ;
        >
        > ?>
        > <img src="test.png">[/color]

        Comment

        Working...