473,396 Members | 2,089 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,396 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 5879
> ...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: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.