 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Ronaldo Souza Guest
|
Posted: Mon Aug 29, 2005 11:44 pm Post subject: Re: Reduce pixel Depth |
|
|
Charles,
| Quote: | Note another poster pointed me to a previous posting, which mentioned
converting the Bitmap to GIF/JPG to reduce colour depth.
Yet this option is out, for I still NEED a bitmap.
|
Try the CreateOptimizedPaletteForSingleBitmap function from the unit
"PaletteLibrary" in the zip below. See the code for it's use.
http://www.efg2.com/Lab/Graphics/Colors/ShowDemoOne.ZIP
Good luck,
Ronaldo
|
|
| Back to top |
|
 |
Charles Hacker Guest
|
Posted: Mon Aug 29, 2005 11:45 pm Post subject: Reduce pixel Depth |
|
|
Hi all,
I am looking to reduce the color/pixel depth of a bitmap for copying.
The standard
BMap.PixelFormat:= pf16Bit;
Clipboard.Assign(Bmap);
Seems to copy the full 32bit color image of the display, (Thus the
bitmaps become massive in memory size).
(Even though the PixelFormat should have made it 16 bit).
So I am wondering how to decrease the pixel depth, so only a small
memory (pf16bit) image is copied to the clipbrd.
Note another poster pointed me to a previous posting, which mentioned
converting the Bitmap to GIF/JPG to reduce colour depth.
Yet this option is out, for I still NEED a bitmap.
|
|
| Back to top |
|
 |
Charles Hacker Guest
|
Posted: Tue Aug 30, 2005 12:18 am Post subject: Re: Reduce pixel Depth |
|
|
Ronaldo Souza wrote:
Yes I have certainly checked EFG's lab, and have seen this.
Although this determines an 'optimised' reduced colour bitmap pallete,
it STILL stores bitmaps in the full 24bit color depth.
Thus I am looking for something which will copy a reduced TBITMAP color
depth (pf16bit) to the clipboard.
(Not the default pf24bit, that it always seems to do).
--
Charles Hacker
Lecturer in Electronics and Computing
School of Engineering
Griffith University - Gold Coast
Australia
|
|
| Back to top |
|
 |
Paul Nicholls Guest
|
|
| Back to top |
|
 |
Ronaldo Souza Guest
|
Posted: Tue Aug 30, 2005 7:26 am Post subject: Re: Reduce pixel Depth |
|
|
Charles,
Try this:
//--------------------------------------------------------------------
uses
GIFImage,ClipBrd;
procedure TForm1.Button1Click(Sender: TObject);
var
BMP1,BMP2 : TBitmap;
MS1,MS2 : TMemoryStream;
DataPtr : Pointer;
DataHandle : THandle;
begin
BMP1 := TBitmap.Create;
try
BMP1.LoadFromFile('Test01.bmp');
if (BMP1.PixelFormat <> pf24Bit)
then BMP1.PixelFormat := pf24Bit;
BMP2 := ReduceColors(BMP1,rmQuantizeWindows,dmNearest,8,0);
try
// Convert BMP to DIB
MS1 := TMemoryStream.Create;
try
BMP2.SaveToStream(MS1);
MS1.Position:= SizeOf(TBitmapFileHeader);
MS2 := TMemoryStream.Create;
try
MS2.CopyFrom(MS1,MS1.Size-SizeOf(TBitmapFileHeader));
// Store DIB file in memory
Datahandle := GlobalAlloc(GMEM_MOVEABLE,MS2.Size);
DataPtr := GlobalLock(Datahandle);
Move(MS2.Memory^,DataPtr^,MS2.Size);
GlobalUnlock(Datahandle);
OpenClipboard(Application.Handle);
EmptyClipboard; //!!!!!!!!!!!!
SetClipboardData(CF_DIB,DataHandle);
CloseClipboard;
finally
MS2.Free;
end;
finally
MS1.Free;
end;
finally
BMP2.Free;
end;
finally
BMP1.Free;
end;
end;
//--------------------------------------------------------------------
HTH,
Ronaldo
|
|
| Back to top |
|
 |
Ronaldo Souza Guest
|
Posted: Tue Aug 30, 2005 7:37 am Post subject: Re: Reduce pixel Depth |
|
|
Charles,
Try this:
//-----------------------------------------------------------------
// Based on code by Bob Villiers
uses
GIFImage,ClipBrd;
procedure TForm1.Button1Click(Sender: TObject);
var
BMP1,BMP2 : TBitmap;
MS1,MS2 : TMemoryStream;
DataPtr : Pointer;
DataHandle : THandle;
begin
BMP1 := TBitmap.Create;
try
BMP1.LoadFromFile('Test01.bmp'); //!!!!!!!!!!!!
BMP2 := ReduceColors(BMP1,rmQuantizeWindows,dmNearest,8,0);
try
// Convert BMP to DIB
MS1 := TMemoryStream.Create;
try
BMP2.SaveToStream(MS1);
MS1.Position:= SizeOf(TBitmapFileHeader);
MS2 := TMemoryStream.Create;
try
MS2.CopyFrom(MS1,MS1.Size-SizeOf(TBitmapFileHeader));
// Store DIB file in memory
DataHandle := GlobalAlloc(GMEM_MOVEABLE,MS2.Size);
DataPtr := GlobalLock(DataHandle);
Move(MS2.Memory^,DataPtr^,MS2.Size);
GlobalUnlock(DataHandle);
OpenClipboard(Application.Handle);
EmptyClipboard; //!!!!!!!!!!!!
SetClipboardData(CF_DIB,DataHandle);
CloseClipboard;
finally
MS2.Free;
end;
finally
MS1.Free;
end;
finally
BMP2.Free;
end;
finally
BMP1.Free;
end;
end;
//-----------------------------------------------------------------
HTH,
Ronaldo
|
|
| Back to top |
|
 |
Jens Gruschel Guest
|
Posted: Tue Aug 30, 2005 8:48 am Post subject: Re: Reduce pixel Depth |
|
|
| Quote: | MS1 := TMemoryStream.Create;
try
BMP2.SaveToStream(MS1);
MS1.Position:= SizeOf(TBitmapFileHeader);
MS2 := TMemoryStream.Create;
try
MS2.CopyFrom(MS1,MS1.Size-SizeOf(TBitmapFileHeader));
// Store DIB file in memory
DataHandle := GlobalAlloc(GMEM_MOVEABLE,MS2.Size);
DataPtr := GlobalLock(DataHandle);
Move(MS2.Memory^,DataPtr^,MS2.Size);
|
Tricky. But can't this be done with one memory stream only? Instead of
copying the data to a second memory stream, you could also use the first
memory stream for your move instruction (add the header offset to the
memory pointer).
Jens
--
Jens Gruschel
http://www.pegtop.net
|
|
| Back to top |
|
 |
Ronaldo Souza Guest
|
Posted: Tue Aug 30, 2005 9:35 am Post subject: Re: Reduce pixel Depth |
|
|
Jens Gruschel wrote:
| Quote: | Tricky. But can't this be done with one memory stream only? Instead of
copying the data to a second memory stream, you could also use the first
memory stream for your move instruction (add the header offset to the
memory pointer).
|
Sure. Thanks!
Ronaldo
//---------------------------------------------------------------------
// Based on code by Bob Villiers
uses
GIFImage,ClipBrd;
procedure TForm1.Button2Click(Sender: TObject);
var
BMP1,BMP2 : TBitmap;
MS : TMemoryStream;
DataPtr : Pointer;
DataHandle : THandle;
szTBMPFHdr : integer;
begin
BMP1 := TBitmap.Create;
try
BMP1.LoadFromFile('Test01.bmp'); //!!!!!!!parm!
if (BMP1.PixelFormat > pf8bit)
then BMP2 := ReduceColors(BMP1,rmQuantizeWindows,dmNearest,8,0)
else begin
BMP2 := TBitmap.Create;
BMP2.Assign(BMP1);
end;
try
// Convert BMP to DIB
MS := TMemoryStream.Create;
try
BMP2.SaveToStream(MS);
szTBMPFHdr := SizeOf(TBitmapFileHeader);
MS.Position:= szTBMPFHdr;
// Store DIB file in memory
DataHandle := GlobalAlloc(GMEM_MOVEABLE,MS.Size-szTBMPFHdr);
DataPtr := GlobalLock(DataHandle);
Move(PByteArray(MS.Memory)^[szTBMPFHdr],DataPtr^,
MS.Size-szTBMPFHdr);
GlobalUnlock(DataHandle);
OpenClipboard(Application.Handle);
EmptyClipboard; //!!!!!!!parm!
SetClipboardData(CF_DIB,DataHandle);
CloseClipboard;
finally
MS.Free;
end;
finally
BMP2.Free;
end;
finally
BMP1.Free;
end;
end;
//---------------------------------------------------------------------
|
|
| Back to top |
|
 |
Joris Van Damme Guest
|
Posted: Tue Aug 30, 2005 5:08 pm Post subject: Re: Reduce pixel Depth |
|
|
Charles Hacker wrote:
| Quote: | I am looking to reduce the color/pixel depth of a bitmap for copying.
The standard
BMap.PixelFormat:= pf16Bit;
Clipboard.Assign(Bmap);
Seems to copy the full 32bit color image of the display, (Thus the
bitmaps become massive in memory size).
(Even though the PixelFormat should have made it 16 bit).
|
The PixelFormat assigning does indeed decrease pixel depth (though not in a
very smart or visually pleasing way). However, what happens next, is that
the VCL dumps a DDB on the clipboard, old-style way that it inherits way
back from Win 3.1 Delphi 1. This way, what ends up on the clipboard, after a
needless as well as undesirable convertion, compares to pf32bit (but isn't
exactly that) if your display depth is 32bit, compares to pf24bit or pf16bit
(but isn't exactly that) if your display depth is 24 or 16 bit, or what ends
up on the clipboard is totally screwed on a system with an 8bit palette
display. In short, it's totally unreliable, and totally useless.
I'm might be a little out of date on how the most recent versions of Delphi
do it, but this is how it is done up to Delphi 6 at least, so I guess if
they haven't changed it by then it probably never will...
What you actually want, is to copy it as DIB. This is the correct and
recommended way ever since Win95, but not the way VCL works. You can thus
copy anything on there, from palette DIB to 32bit DIB, any way, independent
of particular system and display bitdepth. For this purpose, you'll need to
drop down to API level. Google on OpenClipboard and SetClipboardData and
such.
If you want to take it one step further, there's a most excellent mechanism
to force the system to simply make a note of the fact that you're able to
specify what is on the clipboard, without actually setting the clipboard
data right way. This avoids the operation and memory consumption if the
clipboard is never actually used by the user, and can also have great
advantages if the clipboard is actually used, depending on your overall
design. If you're interested in taking things to that level, google on
'delayed clipboard rendering'.
--
Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be/
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html
|
|
| Back to top |
|
 |
Joris Van Damme Guest
|
Posted: Tue Aug 30, 2005 5:09 pm Post subject: Re: Reduce pixel Depth |
|
|
Ronaldo Souza wrote:
| Quote: | BMP1.LoadFromFile('Test01.bmp'); //!!!!!!!!!!!!
|
That's copy 1.
| Quote: | BMP2 := ReduceColors(BMP1,rmQuantizeWindows,dmNearest,8,0);
|
That's another copy, even if this second copy is reduced in color depth and
thus somewhat smaller, depending on whether ReduceColors actually works. (I
don't see it in the code you posted.)
| Quote: | try
// Convert BMP to DIB
MS1 := TMemoryStream.Create;
try
BMP2.SaveToStream(MS1);
|
That's another copy, even if this third copy is not exactly a bitmap in the
DIB sense, it's still yet another memory block to allocate, copy to, etc.
| Quote: | MS1.Position:= SizeOf(TBitmapFileHeader);
MS2 := TMemoryStream.Create;
try
MS2.CopyFrom(MS1,MS1.Size-SizeOf(TBitmapFileHeader));
|
That's another copy, fourth copy now!
| Quote: | // Store DIB file in memory
DataHandle := GlobalAlloc(GMEM_MOVEABLE,MS2.Size);
DataPtr := GlobalLock(DataHandle);
Move(MS2.Memory^,DataPtr^,MS2.Size);
|
That's another copy, fifth copy now!
| Quote: | GlobalUnlock(DataHandle);
OpenClipboard(Application.Handle);
EmptyClipboard; //!!!!!!!!!!!!
SetClipboardData(CF_DIB,DataHandle);
CloseClipboard;
finally
MS2.Free;
end;
finally
MS1.Free;
end;
finally
BMP2.Free;
end;
finally
BMP1.Free;
end;
end;
|
I hope the original bitmap was 'only' a few 100 K, or this is extremely bad.
Of course, if it was only a few 100 K, the original poster wouldn't have
objected to copying it to the clipboard without reducing color.
--
Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be/
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html
|
|
| Back to top |
|
 |
Ronaldo Souza Guest
|
Posted: Tue Aug 30, 2005 10:38 pm Post subject: Re: Reduce pixel Depth |
|
|
Joris,
Thanks for the criticism but perhaps you didn't see my second post after
Jens pointed out I didn't need two MemoryStreams. Besides freeing up
BMP1 right after BMP2 is created, I don't see much to improve. Please
take a look. Any suggestions are welcome.
| Quote: | That's another copy, even if this second copy is reduced in color depth and
thus somewhat smaller, depending on whether ReduceColors actually works. (I
don't see it in the code you posted.)
|
ReduceColors is from Anders Melander/Finn Tolderlund's TGIFImage
(mentioned in a previous post and in the uses clause) and my experience
with it has been great. 8 bits are usually more than enough for my
needs. As a test, I ran a few 1024x768x24 images with lots of unique
colors (239.532 up to 358.615) through this code:
ReduceColors(BMP1,rmQuantizeWindows,dmNearest,8,0);
The size went from 2.359.350 to 787.510 bytes (33% of original size)
*with _minimal_ loss of quality*.
Thanks,
Ronaldo
|
|
| Back to top |
|
 |
Joris Van Damme Guest
|
Posted: Wed Aug 31, 2005 1:18 am Post subject: Re: Reduce pixel Depth |
|
|
Ronaldo Souza wrote:
| Quote: | Thanks for the criticism but perhaps you didn't see my second post
after Jens pointed out I didn't need two MemoryStreams. Besides
freeing up BMP1 right after BMP2 is created, I don't see much to
improve. Please take a look. Any suggestions are welcome.
|
It's easy to improve by not building on from buggy unreliable technology,
but sinking down to the (at least) equally simple API level. See my other
post. Any interface with something that requires you to make four redundant
copies of a bitmap to get this done, or three if you wish, should surely be
considered not an option at all. The Win API level is good, does not require
these redundant copies, allows you to actually copy a DIB in any bitdepth
you like, the recommended way, and is extremely easy to use.
| Quote: | ReduceColors is from Anders Melander/Finn Tolderlund's TGIFImage
(mentioned in a previous post and in the uses clause) and my
experience with it has been great.
|
OK.
--
Joris Van Damme
[email]info (AT) awaresystems (DOT) be[/email]
http://www.awaresystems.be/
Download your free TIFF tag viewer for windows here:
http://www.awaresystems.be/imaging/tiff/astifftagviewer.html
|
|
| Back to top |
|
 |
Charles Hacker Guest
|
Posted: Wed Aug 31, 2005 1:25 am Post subject: Re: Reduce pixel Depth |
|
|
Ronaldo Souza wrote:
| Quote: |
Charles,
Try this:
code snipped
|
Thanks, have not tried the code yet, but that should do.
Note even the 'inefficent code' you gave would work for my purposes.
I actually want to use it for my Electonic Circuit Schematic Drawing
Application.
This app produces two color (black and white) diagrams.
When I generate a bitmap from the display (and make the bitmap pf2bit or
pf8bit), and save it, the bitmap is quite small (~100 kb).
Yet when I copy that same bitmap to clipboard, it always becomes a
16Millon color bitmap, of Megabyte size (~1,000 kb).
So I usually had to paste the large (Megabyte) bitmap to Paintshop,
reduce the colors down in Paintshop, copy that image back to clipoboard,
which then was a resonable (~100kb) size, for imbedding into other apps.
--
Charles Hacker
Lecturer in Electronics and Computing
School of Engineering
Griffith University - Gold Coast
Australia
|
|
| Back to top |
|
 |
Charles Hacker Guest
|
Posted: Wed Aug 31, 2005 1:31 am Post subject: Re: Reduce pixel Depth |
|
|
Joris Van Damme wrote:
| Quote: |
The Win API level is good, does not require
these redundant copies, allows you to actually copy a DIB in any bitdepth
you like, the recommended way, and is extremely easy to use.
|
Okay, so do you have example code for this?
--
Charles Hacker
Lecturer in Electronics and Computing
School of Engineering
Griffith University - Gold Coast
Australia
|
|
| Back to top |
|
 |
Ronaldo Souza Guest
|
Posted: Wed Aug 31, 2005 1:38 am Post subject: Re: Reduce pixel Depth |
|
|
Joris Van Damme wrote:
Sorry to insist but I'm really confused now... :-(
| Quote: | It's easy to improve by not building on from buggy unreliable technology,
but sinking down to the (at least) equally simple API level.
|
What do you mean by "API Level"? The functions you mention in your post
"OpenClipboard, SetClipboardData and such." are exactly what I'm using
(or at least *trying* to learn how to use... )
| Quote: | Any interface with something that requires you to make four redundant
copies of a bitmap to get this done, or three if you wish, should
surely be considered not an option at all.
|
The way I understood it, I need one copy to read the original bitmap;
another for the color reduced bitmap; the memory stream to get a memory
image of the reduced bitmap file and a global memory block to pass to
SetClipboardData. The stream could be avoided if there is a way to get
the info I'm reading from the it (after skipping the header) from a
TBitmap structure. Is this possible?
| Quote: | The Win API level is good, does not require these redundant copies,
allows you to actually copy a DIB in any bitdepth you like, the
recommended way, and is extremely easy to use.
|
Can you give me some pointers to these functions? A little demo would be
even nicer... :-;
Thanks,
Ronaldo
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|