<?php

/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/2_02.txt.                                 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | license@php.net so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Authors: Evgeny Stepanischev <imbolk@gmail.com>                      |
// +----------------------------------------------------------------------+
// Project home page (Russian): http://bolknote.ru/files/monobmp/
//
// $Id$


require_once 'Image/XBM.php';

class 
Image_MonoBMP extends Image_XBM
{
    function 
Image_MonoBMP()
    {
        
parent::Image_XBM();
    }

    
/**
     * Output image to browser or file
     *
     * @param string $filename (optional) filename for output
     * @return bool PEAR_Error or true
     * @access public
     */
    
function output($filename false)
    {
        
$s '';
        
$wx ceil($this->_sx 8);

        
// Prepare image data
        
for ($y $this->_sy 1$y >= 0; --$y) {
            for (
$x 0$x $wx; ++$x) {
                
$s .= chr($this->_bitrev($this->_image[$x][$y]));
            }

            for (; 
$x 4$x++) {
                
$s .= "\0";
            }
        }

        
$size strlen($s);

        
// Prepare subheader
        
$header pack
        
(
            
'VVvvV6',
            
$this->_sx// width
            
$this->_sy// height
            
1,          // planes
            
1,          // bit count
            
0,          // compress
            
$size,      // picture size (bytes)
            
0xB12,      // X pixels per meter
            
0xB12,      // Y pixels per meter
            
0,          // color used (0 mean "all")
            
0           // important colors (all)
        
);

        
$header pack('V'strlen($header) + 4) . $header;

        
// Adding color table (white and black colors)
        
$color "\xFF\xFF\xFF\0\0\0\0\0";

        
// Pack main header
        
$main pack('vvV'000x3E);

        
// Build header and bitmap data
        
$s $main.$header.$color.$s."\0";
        
$s 'BM'.pack('V'strlen($s) + 4) . $s;

        if (
$filename === false) {
            echo 
$s;
        } else {
            if (
$fp fopen($filename'w')) {
                
flock($fpLOCK_EX);

                
fwrite($fp$s);
                
fclose($fp);
            } else {
                return 
PEAR::raiseError('Cannot open file for writing.'5);
            }
        }
        return 
true;
    }

    
/**
     * Create a new image from XBM file or URL
     *
     * @param string $filename XBM file name or URL
     * @return mixed PEAR_error or true for success
     * @access public
     */
    
function createFromFile($filename)
    {
        
$fp fopen($filename'r');
        if (!
is_resource($fp)) {
            return 
PEAR::raiseError('Cannot open file.'4);
        }

        
// Bitmap magick signature
        
$sign fread($fp2);
        if (
$sign <> 'BM') {
            return 
PEAR::raiseError('Invalid BMP file.'5);
        }

        
// Skip header
        
fread($fp16);

        
// Width, height
        
extract(unpack('Vwidth/Vheight/vplanes'fread($fp10)));

        
// Check if bitmap is b/w
        
if ($planes != 1) {
            return 
PEAR::raiseError('Invalid BMP file.'5);
        }

        
// Create blank picture
        
$this->create($width$height);

        
// Skip rest of the header
        
fread($fp34);

        
// Read the picture
        
$sx ceil($width 8);

        
// Fill image by bitmap data
        
for ($y $height 1$y >= 0; --$y) {
            for (
$x 0$x $sx; ++$x) {
                
$this->_image[$x][$y] = $this->_bitrev(ord(fread($fp1)));
            }

            if (
$x 4) {
                
fread($fp$x 4);
            }
        }

        
fclose($fp);
    }

    
/**
     * Bit reverse function
     *
     * @param int $num number for reverse
     * @return int bit reversed number
     * @access private
     */
    
function _bitrev($num)
    {
        for (
$i $r 0$i<8$i++) {
            
$r <<= 1;
            
$r |= $num 1;
            
$num >>= 1;
        }

        return 
$r;
    }
}
?>