Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

could you make it very understandable?

0 views
Skip to first unread message

robert smith

unread,
Jun 8, 2002, 4:14:35 AM6/8/02
to
I have just one little question that I'd like answered in a manner that a
simple country boy could understand...

Is it impossible, Yes or No, to use GDI+ or any .net languge at all to
create 1bitperpixel images such as TIFF/CCITT Group 4 compression?

On all of the internet there is one (1) example of C# making 8bpp's (to make
GIFs), it's from MS and it 's full of comments to the tune of "it would be
better if you could do ____"

After a lot of searching I have come nearly to the conclusion that
absolutely no one (except one guy who used to work at SGI and who hasn't
updated his ftp area in a decade) can create rasters less than 16bpp. And
no one at all can do it using Microsoft dev tools.

Am I wrong? Is there a code example anywhere?

I really don't mean to sound negative, but is the system.drawing's CCITx
encoder just a red herring?

robert smith
kirkland, wa

John Hornick [MS]

unread,
Jun 11, 2002, 12:01:03 PM6/11/02
to
Hi,


Yes, you can. But before you call Save(), your Bitmap must already be
reduced to 1bpp. Q319061 demonstrates reductions in color depth.

Thanks,
- John
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.
Visit http://www.microsoft.com/security for current information on security.

robert smith

unread,
Jun 13, 2002, 4:44:31 PM6/13/02
to
Now where did that page come from ;-). I know I read an earlier version of
it before (was only in C# and it used unsafes). For VB it's (as always)
CopyMemory to the rescue.

Thanks John. Very appreciated.

Robert

robert smith

unread,
Jun 13, 2002, 7:23:09 PM6/13/02
to
And ya got me all excited ...

but nope, still getting invalid argument exceptions when I try to use the
ccitt4 (or 3) encoder.

Was a valiant effort, John (and I found my printout of the C# article I'd
had before ... your suggestion was the same that I'd tried before after all,
just made nicer in vb-syntax).

Oh, the sample works great .. to get to a 256 gif (and even a "Black And
White" with LZW) but once you try to stick in a CCIT encoder it won't go any
farther.

I was really hoping to dump leadtools .. guess not yet.

Are there any other resources that might have some pointers on this area?
Been waiting for the GDI+ book to come out (backed up to July now), but I
have a feeling it's just going to be showing how to draw curves.

Thanks all the same.

-robert

robert smith

unread,
Jun 13, 2002, 10:35:32 PM6/13/02
to
Jeff Richter said at a .net thing recently that he believed that all "real"
programming could truly be done in .net.

I said "not AI or graphics." We differed on that ... and, how strange, it
seems I was right <g>.

The more I look the more people I see asking for one same thing ... and no
one has the answer. How do you convert a color image to a Black & White
1bppixel and save it with CCITT4 compression?.

Please not another pointer to the same MS page showing how to drop the color
to 256 and save as a gif. No matter what version of that page is used, it
doesn't do it.

I'd love to go back to believing that everything Mr. Richter says is the
100% gospel ... but unless this business issue can be proved doable in C# or
VB.net, I guess he's only 99.9% perfect

;-)

Thanks.

Robert Smith
Kirkland, WA
www.smithvoice.com


John Hornick [MS]

unread,
Jun 18, 2002, 5:19:47 PM6/18/02
to
Hi,


As I said before, you need to convert to 1bpp, then encode in CCITT4. Below
is some (untested) code which proves this concept:


public static Bitmap ConvertTo1bbpIndexed(Bitmap src)
{
return ConvertTo1bbpIndexed(src, 128);
}
public static Bitmap ConvertTo1bbpIndexed(Bitmap src, int luminanceCutOff)
{
int width, height;
Bitmap dest;
Rectangle rect;
BitmapData data;
IntPtr pixels;
uint row, col;

//Collect SOURCE Bitmap info
width = src.Width;
height = src.Height;

//Create the DESTINATION Bitmap
dest = new Bitmap(width, height, PixelFormat.Format1bppIndexed);
dest.SetResolution(src.HorizontalResolution, src.VerticalResolution);

//LOCK the Entire Bitmap & get the pixel pointer
rect = new Rectangle(0, 0, width, height);
data = dest.LockBits(rect, ImageLockMode.WriteOnly,
PixelFormat.Format1bppIndexed);
pixels = data.Scan0;

unsafe
{
Color srcPixel;
byte * pBits, pDestPixel;
byte bMask;
double luminance;

//Init pointer to the Bits
if (data.Stride > 0) pBits = (byte *) pixels.ToPointer();
else pBits = (byte *) pixels.ToPointer() + data.Stride * (height -
1);

//Stride could be negative
uint stride = (uint)Math.Abs(data.Stride);

//Go through all the Pixels in the rectangle
for ( row = 0; row < height; row ++ )
{
for ( col = 0; col < width; col ++ )
{
//Get the Pixel from the SOURCE
srcPixel = src.GetPixel((int)col, (int)row);
//srcPixel = Color.White;

//Move the DESTINATION to the correct Address / Pointer & get Pixel
pDestPixel = pBits + (row * stride) + ((int)(col / 8));

//Determine which Bit Represents this Pixel in 1bpp format
bMask = (byte) (0x0080 >> (int)(col % 8));

//Calculate LUMINANCE to help determine if black or white pixel
luminance = (srcPixel.R * 0.299) + (srcPixel.G * 0.587) + (srcPixel.B
* 0.114);

//Set to Black or White using the Color. Luminance Cut Off
if ( luminance >= luminanceCutOff )
*pDestPixel |= (byte) bMask; // Set Bit to 1 - White
else
*pDestPixel &= (byte) ~ bMask; // Set Bit to 0 - Black
}
}

}
dest.UnlockBits(data);
return dest;
}
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders;
encoders = ImageCodecInfo.GetImageEncoders();
for(j = 0; j < encoders.Length; ++j)
{
if(encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
private bool Save1bppTIFFWithCCITT4( Bitmap bm, string szFileName )
{
EncoderParameters eps = new EncoderParameters(1);
long l = (long)EncoderValue.CompressionCCITT4;
eps.Param[0] = new EncoderParameter( Encoder.Compression, l );
ImageCodecInfo ici = GetEncoderInfo("image/tiff");
bm.Save( szFileName, ici, eps );
return true;
}
private void button2_Click(object sender, System.EventArgs e)
{
Bitmap bm = new Bitmap( "\\images\\jpgs\\baseball.jpg" );
Bitmap bm1bpp = ConvertTo1bbpIndexed(bm);
bm1bpp.Save( "\\images\\tiffs\\baseball1bpp.tif", ImageFormat.Tiff );
Save1bppTIFFWithCCITT4( bm1bpp,
"\\images\\tiffs\\baseball1bppccitt4.tif" );
MessageBox.Show( "Done" );
}


Note that this code, as I suggested in a previous response, is heavily
based on the other articles which convert to 8bpp. But, with a few changes,
it now changes to 1bpp. This code is in C# - you could employ a similar
approach to migrate the VB sample to handle 1bpp.

robert smith

unread,
Jun 24, 2002, 10:12:04 AM6/24/02
to
>
>
> As I said before, you need to convert to 1bpp, then encode in CCITT4.
Below
> is some (untested) code which proves this concept:
>

As I said before John, "Thank you, but it is not working" Perhaps my major
problem is my ignorance and the lack of understanding on how to convert your
Unsafe C# to VB.net (using RtlMovememory) All I get it a black image with
white stripes.

However, you have answered the original question:

I asked if the System.drawing Group 4 Encoder was a Red Herring. And you
have shown that it is. Because your use of Unsafe (and vb.net's having to
use CopyMemory) shows that the framework does not natively support this
encoder.


John Hornick [MS]

unread,
Jun 24, 2002, 11:49:37 AM6/24/02
to
Hi,


That's not a fair characterization of this situation. The framework
certainly supports the encoder, and will happily save your images in
that format, provided you start with a 1bpp image. How you get that
1bpp image is another matter.

You may choose to load it directly from disk. This is a supported
framework-only use, and is a counter-example to your claim that
the encoder is a red herring.

If you want to complain about something, complain that the framework
doesn't allow you to edit 1bpp images (or any indexed format), so
you have to use LockBits() to get at the image bits and manipulate
them yourself if you need to modify the image.

Robert Smith - Kirkland, WA

unread,
Jul 11, 2002, 1:53:38 AM7/11/02
to
>
>
> That's not a fair characterization of this situation. The framework
> certainly supports the encoder, and will happily save your images in
> that format, provided you start with a 1bpp image. How you get that
> 1bpp image is another matter.

I think that you actually do undersand my problem but I guess I'm just
not making myself clear. I will humbly try again: It is exactly that
_other matter_ that I wish to know


>
> You may choose to load it directly from disk. This is a supported
> framework-only use, and is a counter-example to your claim that
> the encoder is a red herring.
>

Ok. To make the developers of the Encoder happy. I will fully admit
that my issue was misunderstood based on a syntax problem. Here: The
encoder probably does what an encoder is supposed to do. But the
issue is getting it to do what is needed in the bigger scope.

> If you want to complain about something, complain that the framework
> doesn't allow you to edit 1bpp images (or any indexed format), so
> you have to use LockBits() to get at the image bits and manipulate
> them yourself if you need to modify the image.
>

Please go back in this thread and the other that you & I were on
previous to this one (on the exact same question).

Here is the end-users' (my) question: How do we convert a non-indexed
image to a 1bpp indexed tiff image, can you show the code in VB.net?
That is the pain, the spec, the need. I would love to use
RTLMoveMemory and LockBits. Really, I would. So we are on the same
wavelength, your last paragraph is my frustration exactly! You, very
nicely, pointed me to a C# example (not the 8bbp one, the 1bbp one)
... and I am asking for someone to assist in getting that same example
to work in VB.net because I personally just can't get it to port - I
admit to being less-than-smart - I'll admit to being a donkey if it
will help me get a look at some VB.net code that can do this ;).

So, now that we are in total agreement and we both understand that
what you suggest I be complaining about is what I have been
complaining about (<g>) can you point to an example of this exact
conversion in VB.net?

Thank you for all of your time, John. We simple users/customers
appreciate all of the effort it takes for you to get to the real issue
behind the befuddled confusion and provide a satisfying solution.

-robert

0 new messages