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

From: Chung Leong (chernyshevsky_at_hotmail.com)
Date: 06/25/04

  • Next message: Matt: "Session variables in IE"
    Date: Thu, 24 Jun 2004 20:45:19 -0400
    
    

    "Ken" <hanson_kenneth@yahoo.com> wrote in message
    news:ea8389b0.0406241003.151b8cea@posting.google.com...
    > 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=UTF-8&oe=UTF-8&safe=off&selm=a164f4b5.0311302128.40fb37f4%
    > 40posting.google.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

    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_size) {
      $gd_header .= pack("n", $ncolor);
     }
     // no transparency
     $gd_header .= "\xFF\xFF\xFF\xFF";

     fwrite($dest_f, $gd_header);

     if($palette_size) {
      $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("\x00\x00\x00\x00", 256 - $ncolor);
      fwrite($dest_f, $gd_palette);
     }

     $scan_line_size = (($bits * $width) + 7) >> 3;
     $scan_line_align = ($scan_line_size & 0x03) ? 4 - ($scan_line_size & 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_size + $scan_line_align) * $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$p5$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($path, $mode, $options, &$opened_path)
        {
            $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($count)
        {
            $ret = substr($this->buffer, $this->position, $count);
            $this->position += strlen($ret);
            return $ret;
        }

        function stream_write($data)
        {
            $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 imagecreatefrombmp($filename) {
     // use a memory stream instead of a temp file
     // where possible
     if(function_exists('stream_wrapper_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(ConvertBMP2GD($filename, $tmp_name)) {
      $img = imagecreatefromgd($tmp_name);
      if($del_tmp) {
     unlink($tmp_name);
      }
      return $img;
     } return false;
    }

    $img = imagecreatefrombmp("test32bit.bmp");
    imagealphablending($img, false);
    imagesavealpha($img, true);
    imagepng($img, "test.png");

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


  • Next message: Matt: "Session variables in IE"

    Relevant Pages

    • BMP to GD (then to JPG) - 32 bits?
      ... I need to convert 32 bit Windows bitmaps to jpgs with PHP. ...
      (comp.lang.php)
    • Re: displaying jpg images on Windows CE 5.0
      ... Bitmaps are easier only in that they are the already in the native format ... Windows uses to represent images. ... JPGs are in a foreign compressed format ...
      (microsoft.public.windowsce.platbuilder)
    • Re: png transparency
      ... transparency is support by the "System" ... by any of the standard controls. ... There is code with which you can draw bitmaps onto other bitmaps and ... given color as transparent color so that the underlaying control ...
      (microsoft.public.dotnet.framework.compactframework)
    • Re: Bilder aus der Desktop-Hintergrund-Auswahl entfernen
      ... indem du nur Bitmaps als Hintergrund ... NoHTMLWallpaper REG_DWORD 0x00000001 ... dass die JPGs vom Ordner Wallpaper nun auch nicht mehr zur Auswahl ...
      (microsoft.public.de.german.windowsxp.sonstiges)
    • Re: Semitransparentes Bitmap zeichnen
      ... eine PNG-Datei? ... Es können alle möglichen Bitmaps sein, ... nur im Speicher erzeugt, JPGs, BMPs, ... ...
      (microsoft.public.de.vc)