Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Direct Conversion of System.Drawing.Image to SFML.Graphics.Image  (Read 6194 times)

0 Members and 1 Guest are viewing this topic.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Ran into this issue little bit ago and seems it is a big pain to get byte[] conversion to work right and also got no clue how to extract the pixel color array of the image.  Yes Image to Byte[] is working but it would be nice if there was a straight conversion saving us a step or two. :)
I have many ideas but need the help of others to find way to make use of them.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Direct Conversion of System.Drawing.Image to SFML.Graphics.Image
« Reply #1 on: April 05, 2014, 09:29:35 am »
Can you show what the corresponding code looks like? This is the kind of conversion that should be really easy to implement, I can't believe Microsoft makes it so painful.
Laurent Gomila - SFML developer

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Direct Conversion of System.Drawing.Image to SFML.Graphics.Image
« Reply #2 on: April 05, 2014, 05:02:42 pm »
Well I've been through 4 versions so far and so bug out under some conditions for some unknown reason.  Other than that here's the code below. :)


Yes it's in C# but it shouldn't be hard to change up. :P
//http://stackoverflow.com/questions/7350679/convert-a-bitmap-into-a-byte-array-in-c
        private static byte[] ImageToByteArray(System.Drawing.Image resourceimage)
        {
            System.Drawing.ImageConverter imgcon = new System.Drawing.ImageConverter();
            return (byte[])imgcon.ConvertTo(resourceimage, typeof(byte[]));
        }

        // Yes Straight up C&P from here:
        //http://social.msdn.microsoft.com/Forums/vstudio/en-US/47c5a003-1d26-4213-9370-fba3aa170c21/fastest-method-to-convert-bitmap-object-to-byte-array?forum=csharpgeneral
        // A Case of either use full quantified names for SFML or C#. >.>
        private static byte[] GetRGBValues(System.Drawing.Bitmap bmp)
        {

            // Lock the bitmap's bits.
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
            System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            int bytes = bmpData.Stride * bmp.Height;
            byte[] rgbValues = new byte[bytes];

            // Copy the RGB values into the array.
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
            bmp.UnlockBits(bmpData);

            return rgbValues;
        }
        //http://www.sitepoint.com/forums/showthread.php?223894-Bitmap-to-byte-array-in-C
        /*private static byte[] StreamImageToByteArray(System.Drawing.Image resourceimage)
        {
            MemoryStream stream = new MemoryStream();
            resourceimage.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
            //Byte[] bytes =
            if (stream != null)
            {
                stream.Close();
            }
            return stream.ToArray();
        }*/

        //http://stackoverflow.com/questions/13602281/converting-bitmap-pixels-as-byte-array-fails
        private static byte[] MarshalImageToByteArray(System.Drawing.Bitmap bmp)
        {
            // Lock the bitmap's bits.  
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
            System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
            byte[] rgbValues = new byte[bytes];

            // Copy the RGB values into the array.
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
            bmp.UnlockBits(bmpData);
            return rgbValues;
        }
 
I have many ideas but need the help of others to find way to make use of them.

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Direct Conversion of System.Drawing.Image to SFML.Graphics.Image
« Reply #3 on: April 06, 2014, 12:30:36 am »
Just found I can use GetPixel to grab the things needed for SFML's Color class.  Going to try a very slow but useful way of changing from one to the other. :P  I'll post it when I'm done. :)
I have many ideas but need the help of others to find way to make use of them.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Direct Conversion of System.Drawing.Image to SFML.Graphics.Image
« Reply #4 on: April 06, 2014, 12:39:52 am »
This is outside the scope of SFML/SFML.NET, anyways it isn't that hard and I just posted 2 working methods in your other thread.  ;)
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

StormWingDelta

  • Sr. Member
  • ****
  • Posts: 365
    • View Profile
Re: Direct Conversion of System.Drawing.Image to SFML.Graphics.Image
« Reply #5 on: April 06, 2014, 03:27:13 am »

Here's both our solutions. :)


Here's My Solution.  Had to flip a few things for some odd reason but it works. :P


        private SFML.Graphics.Image ToSFMLImage(System.Drawing.Bitmap bmp)
        {
            SFML.Graphics.Color[,] sfmlcolorarray = new Color[bmp.Height, bmp.Width];
            SFML.Graphics.Image newimage = null;
            for (int x = 0; x < bmp.Width; x++)
            {
                for (int y = 0; y < bmp.Height; y++)
                {
                    System.Drawing.Color csharpcolor = bmp.GetPixel(x, y);
                    sfmlcolorarray[y,x] = new SFML.Graphics.Color(csharpcolor.R, csharpcolor.G, csharpcolor.B, csharpcolor.A);
                }
            }
            newimage = new SFML.Graphics.Image(sfmlcolorarray);
            return newimage;
        }

        private SFML.Graphics.Texture ToSFMLTexture(System.Drawing.Bitmap bmp)
        {
            return new Texture(ToSFMLImage(bmp));
        }
 
Do what you want with this... it only took me 10 minutes  ;)

Yes the code is messy because I didn't bother to clean it up.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using SFML.Window;
using SFML.Graphics;
using System.IO;

namespace WindowsFormsApplication2
{
    static class Program
    {
       
        static void Main()
        {
            RenderWindow wind = new RenderWindow(new VideoMode(500, 500), "Test");
            wind.SetVerticalSyncEnabled(true);
            Texture tx1 = new Texture("LBB.png");
            Sprite sp1 = new Sprite(tx1) { Scale = new Vector2f(.4f, .4f) };
            var im1 = WindowsFormsApplication2.Properties.Resources.LBB;
            Texture tx2 = CreateTexture1(im1);
            Sprite sp2 = new Sprite(tx2) { Scale = new Vector2f(.4f, .4f), Position = new Vector2f (0, 250) };
            Texture tx3 = CreateTexture2(im1);
            Sprite sp3 = new Sprite(tx3) { Scale = new Vector2f(.4f, .4f), Position = new Vector2f (250,250) };
            while (wind.IsOpen())
            {
                wind.DispatchEvents();
                wind.Clear(SFML.Graphics.Color.White);
                wind.Draw(sp1);
                wind.Draw(sp2);
                wind.Draw(sp3);
                wind.Display();
            }
        }
        static Texture CreateTexture1(Bitmap Im)
        {
            byte[] array = new byte[Im.Width * Im.Height * 4];
            int i = 0;
            for (int y = 0; y < Im.Height; y++)
            {
                for (int x = 0; x < Im.Width; x++)
                {
                    var px = Im.GetPixel(x, y);
                    array[i] = px.R;
                    array[i + 1] = px.G;
                    array[i + 2] = px.B;
                    array[i + 3] = px.A;
                    i += 4;
                }
            }
            var tx = new Texture((uint)Im.Width, (uint)Im.Height);
            tx.Update(array);
            return tx;
        }
        static Texture CreateTexture2(Bitmap Im)
        {
            MemoryStream stm = new MemoryStream();
            Im.Save(stm, System.Drawing.Imaging.ImageFormat.Png);
            return new Texture(stm);
        }
    }
}
 


I have many ideas but need the help of others to find way to make use of them.