Monochrome GIFs in VB?

S

surturz

This article is helpful in creating 1bpp (Monochrome) GIFs using GDI+
http://support.microsoft.com/kb/319061

However, I'm using VB 2005 and am having trouble copying the pixels across.

The C code I'm having trouble converting follows:

unsafe
{
// Get the pointer to the image bits.
// This is the unsafe operation.
byte * pBits;
if (bitmapData.Stride > 0)
pBits = (byte *)pixels.ToPointer();
else
// If the Stide is negative, Scan0 points to the last
// scanline in the buffer. To normalize the loop, obtain
// a pointer to the front of the buffer that is located
// (Height-1) scanlines previous.
pBits = (byte *)pixels.ToPointer() + bitmapData.Stride*(Height-1);
uint stride = (uint)Math.Abs(bitmapData.Stride);

for ( uint row = 0; row < Height; ++row )
{
for ( uint col = 0; col < Width; ++col )
{
// Map palette indexes for a gray scale.
// If you use some other technique to color convert,
// put your favorite color reduction algorithm here.
Color pixel; // The source pixel.

// The destination pixel.
// The pointer to the color index byte of the
// destination; this real pointer causes this
// code to be considered unsafe.
byte * p8bppPixel = pBits + row*stride + col;

pixel = BmpCopy.GetPixel((int)col, (int)row);

// Use luminance/chrominance conversion to get grayscale.
// Basically, turn the image into black and white TV.
// Do not calculate Cr or Cb because you
// discard the color anyway.
// Y = Red * 0.299 + Green * 0.587 + Blue * 0.114

// This expression is best as integer math for performance,
// however, because GetPixel listed earlier is the slowest
// part of this loop, the expression is left as
// floating point for clarity.

double luminance = (pixel.R *0.299) +
(pixel.G *0.587) +
(pixel.B *0.114);

// Gray scale is an intensity map from black to white.
// Compute the index to the grayscale entry that
// approximates the luminance, and then round the index.
// Also, constrain the index choices by the number of
// colors to do, and then set that pixel's index to the
// byte value.
*p8bppPixel = (byte)(luminance * (nColors-1)/255 +0.5);

} /* end loop for col */
} /* end loop for row */
} /* end unsafe */

// To commit the changes, unlock the portion of the bitmap.
bitmap.UnlockBits(bitmapData);
 
J

Jeffrey Tan[MSFT]

Hi Surturz,

VB.net language does not support unsafe coding. This is a main language
level difference between C# and VB.net.

The simplest workaround for this issue is first creating a C# library
project and paste these C# unsafe code and expose these methods from the C#
library. Then, in your VB.net project, you may just add reference to this
C# library and call this C# helper method. This should be pretty easy
workaround.

Another more complex solution is translating all these unsafe code in
VB.net language through COM interop technology. This is error-prone and
needs a lot of memory type marshaling. Anyway, if you have special reason
to go through this approach, please feel free to tell me, I will
collaborate with my COM interop colleage to help you on it. Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

surturz

Thanks Jeffrey and Herfried.

I don't want to have a multi-language solution, so adding a C# component is
out of the question, as is using COM Interop.

The link Herfried provided seems to work, but is too slow for my needs.

I've decided to bite the bullet and write a simple GIF encoder that supports
a 1bpp colour table. Hopefully that will work, although copying the
high-colour pixels might still be slow. Maybe converting to 8bpp using the VB
codec then reducing from 8bpp to 1bpp will be quick.

-David St
 
T

Tom Shelton

Thanks Jeffrey and Herfried.

I don't want to have a multi-language solution, so adding a C# component is
out of the question, as is using COM Interop.

Why? Really, at runtime it's all the same anyway.
The link Herfried provided seems to work, but is too slow for my needs.

I've decided to bite the bullet and write a simple GIF encoder that supports
a 1bpp colour table. Hopefully that will work, although copying the
high-colour pixels might still be slow. Maybe converting to 8bpp using the VB
codec then reducing from 8bpp to 1bpp will be quick.

And that is simpler then just putting hte C# code in a class library?
Not trying to bust your chops or anything, but I doubt it will speed
things up much...
 
S

SurturZ

If I implement a GIF Encoder, it will be code that does a particular job.

The other solutions in this thread are all hacks to get around the fact that
the built-in GIF codec that ships with GDI+ does not adequately export 1bpp
GIF files. Not that I am against hacks, but they need to be quick and
painless to implement if they are to be useful.
 
J

Jeffrey Tan[MSFT]

Hi David,

Sorry, I am not sure if I understand you completely. As I understand, you
wanted to translate the C# code in that KB article into VB.net.

Then, can you tell me why you cannot afford the cross-language solution as
I suggested? All .Net code will compile into the same type of IL code, and
they have good inter-language operability. Actually, this is the easy
approach to go. If you have any special concern regarding it, please feel
free to tell me, thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

SurturZ

Sorry, I am not sure if I understand you completely. As I understand, you
wanted to translate the C# code in that KB article into VB.net.

Then, can you tell me why you cannot afford the cross-language solution as
I suggested? All .Net code will compile into the same type of IL code, and
they have good inter-language operability. Actually, this is the easy
approach to go. If you have any special concern regarding it, please feel
free to tell me, thanks.

Because I am a solo VB programmer and have no desire to maintain a mixed
language codebase. I'm so deeply into hack territory that any more black
magic will mean the app will not be able to be maintained by me in six months
time, let alone anyone else. I also don't like the idea of using unsafe code
(if I wanted to fiddle around with marshalling and pointers, I'd program in
C).

The actual problem is that we have a third-party database application that
stores documents as RTF files via MS Word 2002. We need to scan incoming
correspondence, and the app doesn't support any file format other than RTF.

RTF files are big. Really big. You might think a JPG file on maximum quality
is big, but that's just peanuts compared to RTFs. When MS Word 2002 stores an
image inside an RTF file, it firstly converts each byte in the image to a
two-byte hex code. It then also stores two copies of the image - the native
image (converted to a format that is acceptable to RTF) and a preview image
in WMF format. You can turn off the preview image with a registry hack, but
in my case, the DB app uses the preview WMF.

So when we scan a document, and insert it into a RTF file, it generally
consumes 4MB per page. I can get this down to 500KB per page if I could
change the image to a 1 bit-per-pixel (1 bpp) GIF.

Unfortunately, the scanner software does not output GIF. So I thought I
would write an app that converts the JPG images to 1bpp GIF first.
Unfortunately the GIF codec that ships with Windows/VB (no idea where it
comes from) does not support 1bpp adequately.

So, now I'm re-inventing the wheel and writing a GIF encoder. It may take
some time, sure, but since GIF is a 20+ year old format, it's not that hard,
and I am assured that my code will actually work when I'm finished, survive
upgrades to the OS, and be easy to maintain in the long run. Also I won't be
exposing myself to the memory corruption risks that unsafe code brings.

(A very few days, like today, I envy those open-source guys. I'd be happy to
add 1bpp support to the Microsoft GIF codec, since it would be quicker than
writing a whole encoder. Alas.).
 
J

Jeffrey Tan[MSFT]

Hi David,

Thank you for the detailed feedback.

Yes, I see your concern due to the complex scenario.

Due to the complexitiy nature of this issue, if you meet any further
problem regarding it, I would recommend you to contact Microsoft CSS
directly to support this issue. The Microsoft Support Professional will
provide more reliable and professional support with you. They will even
collaborate with the GDI/GDI+ team to resolve your issue.

When you wanted to this approach, you can contact Microsoft Product Support
by contacting us at 1-(800)936-5800 or by choosing one of the options
listed at:
http://www.microsoft.com/services/microsoftservices/srv_support.mspx

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top