1

Using C# and Visual Studio 2010, how can I make a grayscaled emf from a colored one? Should I enumerate records and change color settings somehow?

As a result I want to have a new emf image.

Dmitriy
  • 11
  • 3
  • You open each image and use this strategy to grayscale a new image and then save it as emf. http://stackoverflow.com/questions/2265910/c-convert-image-to-grayscale – Ted Jul 20 '13 at 18:33
  • Hi Ted, what I want is to get a new emf as a result, not a bitmap. If I use this approach after grayscaling I should convert bitmap to emf and that is not so easy as I know. – Dmitriy Jul 20 '13 at 18:48
  • Ah, and you want to keep it as vector content. This post has some info on working with emfs anyway http://stackoverflow.com/questions/152729/gdi-c-how-to-save-an-image-as-emf – Ted Jul 20 '13 at 18:53
  • This post has some code, but I'm not sure about the language https://forums.embarcadero.com/thread.jspa?threadID=65964 – Ted Jul 20 '13 at 18:58
  • Blast. Despite my efforts, the best I could come up with was that there is no vector export utility for emf using GDI+/C#. Even if you can grayscale the source vector content, you can't save it. From what I have found anyway. – Ted Jul 20 '13 at 19:40
  • Ok, I have tested the answer in at least a simple case and it worked. – Ted Jul 20 '13 at 22:28

1 Answers1

0

Here is an open source emf read/write utility. I don't think it can be done with GDI+ and preserve the vector content. So this hopefully will help you, but I haven't remotely tested all possible emf cases.

https://wmf.codeplex.com/

this works for both wmf and emf formats. We can combine the Oxage.Wmf strategy with the strategy from the other post which essentially re-colors a pen or brush when it is created so that anything drawn with that pen or brush should be gray.

using Oxage.Wmf;
using Oxage.Wmf.Records;
using Oxage.Wmf.Objects;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MetafileTest
{
    public class GrayMap
    {
        public void GrayFile(string sourceFile, string destFile){

            WmfDocument wmf = new WmfDocument();
            wmf.Load(sourceFile);

            foreach (var record in wmf.Records)
            {
                if (record is WmfCreateBrushIndirectRecord)
                {
                    var brush = record as WmfCreateBrushIndirectRecord;
                    brush.Color = Gray(brush.Color);
                }
                else if (record is WmfCreatePenIndirectRecord)
                {
                    var pen = record as WmfCreatePenIndirectRecord;
                    pen.Color = Gray(pen.Color);
                }
                else if (record is WmfCreatePalette) {
                    var pal = record as WmfCreatePalette;
                    foreach (PaletteEntry entry in pal.Palette.PaletteEntries) {
                        Color test = Color.FromArgb(entry.Red, entry.Green, entry.Blue);
                        Color grayTest = Gray(test);
                        entry.Red = grayTest.R;
                        entry.Green = grayTest.G;
                        entry.Blue = grayTest.B;
                    }
                }
            }
            wmf.Save(destFile);

        }

        public Color Gray(Color original) { 
            int r = (int)(original.R*0.2989);
            int g = (int)(original.G*0.5870);
            int b = (int)(original.B*0.1140);
            Color result = Color.FromArgb(r, g, b);
            return result;

        }

    }
}

This was tested with the following super simple case of filling a blue rectangle, so for at least the simple cases this will work. It may not be able to handle all cases, but in such a case you can probably extend the original source to suite your needs since it is open source.

    private void button1_Click(object sender, EventArgs e)
    {
        var wmf = new WmfDocument();
        wmf.Width = 1000;
        wmf.Height = 1000;
        wmf.Format.Unit = 288;
        wmf.AddPolyFillMode(PolyFillMode.WINDING);
        wmf.AddCreateBrushIndirect(Color.Blue, BrushStyle.BS_SOLID);
        wmf.AddSelectObject(0);
        wmf.AddCreatePenIndirect(Color.Black, PenStyle.PS_SOLID, 1);
        wmf.AddSelectObject(1);
        wmf.AddRectangle(100, 100, 800, 800);
        wmf.AddDeleteObject(0);
        wmf.AddDeleteObject(1);
        wmf.Save("D:\\test.emf");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        GrayMap map = new GrayMap();
        map.GrayFile("D:\\test.emf", "D:\\test2.emf");
    }
Ted
  • 3,002
  • 22
  • 19