简体   繁体   中英

Image Manipulation c#

I have the following code which takes an array of bytes which i generated and writes them out to this bitmap. If i set the pixel format to Format4bppIndexed, then i get a readable image repeating width wise 4 times, if i set it to Format1bppIndexed(which is the correct setting) then i get one big unreadable image.

The image was a decoded Jbig2 image , i know the bytes are correct i can't seem to figure out how to get it into a 1bpp readable format.

Does anyone have any advice on that matter

        Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format1bppIndexed);

        //Create a BitmapData and Lock all pixels to be written           
        BitmapData bmpData = bitmap.LockBits(
                             new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                             ImageLockMode.WriteOnly, bitmap.PixelFormat);

        //Copy the data from the byte array into BitmapData.Scan0
        Marshal.Copy(newarray, 0, bmpData.Scan0, newarray.Length);
        //Unlock the pixels
        bitmap.UnlockBits(bmpData);

The following may work although, if I remember correctly, Stride sometimes has an effect and a simple block-copy won't suffice (line by line must be used instead).

Bitmap bitmap = new Bitmap(
    width, 
    height, 
    System.Drawing.PixelFormat.Format16bppGrayScale
    );

To handle the Stride you'd want:

    BitmapData^ data = bitmap->LockBits(oSize, 
        ImageLockMode::ReadOnly, bitmap->PixelFormat);
    try {
        unsigned char *pData = (unsigned char *)data->Scan0.ToPointer();

        for( int x = 0; x < bmpImage->Width; ++x )
        {
            for( int y = 0; y < bmpImage->Height; ++y )
            {
                // Note: Stride is data width of scan line rounded up
                //       to 4 byte boundary.  
                // Requires use of Stride, not (width * pixelWidth)
                int ps = y*bmpImage->Width*(nBitsPerPixel / 8)
                         + x * (nBitsPerPixel / 8);
                int p = y * data->Stride + x * (nBitsPerPixel / 8);
                Byte lo = newarray[ps + 1];
                Byte hi = newarray[ps + 0];
                pData[p + 1] = lo;
                pData[p + 0] = hi;
            }
        }
    } finally {
        bmpImage->UnlockBits(data);
    }

Note: This was written in C++/CLI. Let me know if you need C# equivalents for any of the operations here. (Also, I pulled it from a read from bitmap rather than a write to bitmap so it may yet be a bit rough, but should hopefully give you the idea...)

I figured this out Although i'm still not sure why it should matter.

Based on this stackoverflow posting How can I load the raw data of a 48bpp image into a Bitmap?

I used the WPF classes instead of the GDI and wrote the code like this

var bitmap = new WriteableBitmap(width, height, 96, 96,           System.Windows.Media.PixelFormats.BlackWhite, null);
bitmap.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), newarray, stride, 0);     
MemoryStream stream3 = new MemoryStream();
var encoder = new TiffBitmapEncoder ();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream3);

This correctly creates the image.

If anyone has any insight into why this might be the case please comment below

The port which now mostly works(lots of cleanup code) was based on a java implementation of JPedal Big2 Decoder to .NET. If anyone knows anyone interested send them here https://github.com/devteamexpress/JBig2Decoder.NET

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM