473,241 Members | 1,668 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,241 software developers and data experts.

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

Ken
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
Jul 17 '05 #1
3 5869
> ...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
Jul 17 '05 #2

"Ken" <ha************@yahoo.com> wrote in message
news:ea**************************@posting.google.c om...
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">
Jul 17 '05 #3
Ken
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 = imagecreatefrombmp("test32bit.bmp");
imagealphablending($img, false);
imagesavealpha($img, true);
imagejpeg($img, "test.jpg");

Ken

?>
<img src="test.jpg">
"Chung Leong" <ch***********@hotmail.com> wrote in message news:<Pq********************@comcast.com>...
"Ken" <ha************@yahoo.com> wrote in message
news:ea**************************@posting.google.c om...
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">

Jul 17 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: bettina | last post by:
I look in my DB for a CODE. I find it and now I want to show the jpg corresponding to this CODE in html. Here is my piece of code, however the photo will not be shown.... <?php - - - ...
21
by: Dan V. | last post by:
I have tried a number of things including preloading, but the background image (water tile in header) in IE 6 will not display where other browsers will....
7
by: Joe Barta | last post by:
What is wrong with this jpg... http://www.joebarta.com/bad_jpg/sample.jpg It does not show up in IE or Netscape. It does show up in Opera. It opens up in Irfanview & PSP just fine and without...
2
by: Abby | last post by:
Hi all, I need advice on how to concatenate bits value. I have 2 bytes of Hex value: Byte1 = 0x33 --> 00110011 Byte2 = 0x90 --> 10010000 I want 10 bits value which compose of 2 bits(7th...
4
by: CodeRazor | last post by:
I'm unfamiliar with image manipulation using c#. How can i resize a jpg that currently exists in a file and save it resized as a new file. The examples i've found have been a bit misleading for...
64
by: yossi.kreinin | last post by:
Hi! There is a system where 0x0 is a valid address, but 0xffffffff isn't. How can null pointers be treated by a compiler (besides the typical "solution" of still using 0x0 for "null")? -...
2
by: Daniel Di Vita | last post by:
I have created an ASP.NET page that allows the user to page through a result set. I need to expand on this. On that same page I a filed where the user can type in a search string. When they click...
7
by: oscartheduck | last post by:
Hi folks, I'm trying to alter a program I posted about a few days ago. It creates thumbnail images from master images. Nice and simple. To make sure I can match all variations in spelling of...
2
by: DanWeaver | last post by:
I have been struggling all day with the following: I am trying to mosaic numerous georeferenced jpgs (so that I can reduce the size of the whole lot together lessening edge defects other than...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: stefan129 | last post by:
Hey forum members, I'm exploring options for SSL certificates for multiple domains. Has anyone had experience with multi-domain SSL certificates? Any recommendations on reliable providers or specific...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.