Subscriber badges don't load properly

In my efforts to add Twitch badges to my richtextbox console using an RTF conversion method, I’ve managed to get every single badge except subscriber badges to download to memory, convert to byte[], convert byte[] to RTF image and embed into the richtextbox’s SelectedRTF.

The code I’m using to get the badges is as follows:

Assign all badge strings to the appropriate jsonData

using(var webClient = new WebClient()) {
            var channelBadgesURL = string.Format("{0}/badges", WiggleBotSettings.Instance.Broadcaster);
            var webData = webClient.DownloadString(channelBadgesURL);
            var jsonData = JObject.Parse(webData);

            BotClient.StaffBadge = jsonData["staff"]["image"].ToString();
            BotClient.AdminBadge = jsonData["admin"]["image"].ToString();
            BotClient.GlobalModBadge = jsonData["global_mod"]["image"].ToString();
            BotClient.BroadcasterBadge = jsonData["broadcaster"]["image"].ToString();
            BotClient.ModBadge = jsonData["mod"]["image"].ToString();
            BotClient.SubscriberBadge = !jsonData["subscriber"].IsNullOrEmpty() ? jsonData["subscriber"]["image"].ToString() : "";
            BotClient.TurboBadge = jsonData["turbo"]["image"].ToString();

Append the image at the given position in the RichTextBox:


Download the data of the image, slap it in a MemoryStream, and apply it to an Image object

public static void AppendImage(this RichTextBox rtb, string url) {
        var imgBytes = DownloadData(url);

        using(var ms = new MemoryStream(imgBytes)) {
            using(var img = Image.FromStream(ms)) {
                rtb.SelectedRtf = GetEmbedImageString((Bitmap)img);

Get the byte[] of an image from a URL

private static byte[] DownloadData(string url) {
        byte[] downloadedData;

        //Get a data stream from the url
        var req = WebRequest.Create(url);
        var response = req.GetResponse();

        using(var memStream = new MemoryStream()) {
            using(var stream = response.GetResponseStream()) {
                //Download in chunks
                var buffer = new byte[1024];

                //Download to memory
                //Note: adjust the streams here to download directly to the hard drive

                while(true) {
                    //Try to read the data
                    if(stream != null) {
                        var bytesRead = stream.Read(buffer, 0, buffer.Length);

                        if(bytesRead == 0) {

                        //Write the downloaded data
                        memStream.Write(buffer, 0, bytesRead);

                //Convert the downloaded stream to a byte array
                downloadedData = memStream.ToArray();

        return downloadedData;

Get the EmbedImageString that RTF understands in the RichTextBox

public static string GetEmbedImageString(Bitmap image) {
        Metafile metafile;
        float dpiX, dpiY;

        using(var g = Graphics.FromImage(image)) {
            var hDC = g.GetHdc();
            metafile = new Metafile(hDC, EmfType.EmfOnly);

        using(var g = Graphics.FromImage(metafile)) {
            g.DrawImage(image, 0, 0);
            dpiX = g.DpiX;
            dpiY = g.DpiY;

        var hEmf = metafile.GetHenhmetafile();
        var bufferSize = GdipEmfToWmfBits(hEmf, 0, null, MM_ANISOTROPIC,
        var buffer = new byte[bufferSize];
        GdipEmfToWmfBits(hEmf, bufferSize, buffer, MM_ANISOTROPIC, EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
        var hmf = SetMetaFileBitsEx(bufferSize, buffer);
        var tempfile = Path.GetTempFileName();
        CopyMetaFile(hmf, tempfile);

        var stream = new MemoryStream();
        var data = File.ReadAllBytes(tempfile);
        var count = data.Length;
        stream.Write(data, 0, count);

        var sb = new StringBuilder();
        sb.Append(@"\picw" + (int)((image.Width / dpiX) * 2540));
        sb.Append(@"\pich" + (int)((image.Height / dpiY) * 2540));
        sb.Append(@"\picwgoal" + (int)((image.Width / dpiX) * 1440));
        sb.Append(@"\pichgoal" + (int)((image.Height / dpiY) * 1440));
        sb.Append(@" " + BitConverter.ToString(stream.ToArray()).Replace("-", ""));

        return sb.ToString();

Necessary DllImports and flags for GetEmbedImageString to function

    enum EmfToWmfBitsFlags {
        EmfToWmfBitsFlagsDefault = 0x00000000,
        EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
        EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
        EmfToWmfBitsFlagsNoXORClip = 0x00000004

    const int MM_ISOTROPIC = 7;
    const int MM_ANISOTROPIC = 8;

    private static extern uint GdipEmfToWmfBits(IntPtr _hEmf, uint _bufferSize, byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
    private static extern IntPtr SetMetaFileBitsEx(uint _bufferSize, byte[] _buffer);
    private static extern IntPtr CopyMetaFile(IntPtr hWmf, string filename);
    private static extern bool DeleteMetaFile(IntPtr hWmf);
    private static extern bool DeleteEnhMetaFile(IntPtr hEmf);

I believe I’ve provided everything needed to reproduce. If anyone has an idea for why subscriber badges aren’t properly displaying, that would be great!

At around the same time as your post, apparently some subscriber chat badges weren’t working. The tweet seems to be before your post but some channels seemed to still be having the issue even after the tweet.

Issue persists 11h after that tweet.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.