PDFsharp & MigraDoc Foundation
http://forum.pdfsharp.com/

changing text color
http://forum.pdfsharp.com/viewtopic.php?f=2&t=1281
Page 1 of 1

Author:  pirosu [ Thu Jul 29, 2010 1:13 pm ]
Post subject:  changing text color

If I open an exsisting pdf document, can I change the color of part of the text, chosen by me?

Author:  jccapps [ Fri Aug 06, 2010 3:31 pm ]
Post subject:  Re: changing text color

I found a way to do this, but it isn't easy (if you find an easier way please post your solution). What I found is that you'll have to read the text directly from the PdfPage's stream. You then search through the stream line by line looking for the op codes that draw the text and set its color. You will then change the parameters for text's color op code. To find the op codes you are looking for you'll have to look them up from either the PDFSharp source code or the Adobe PDF Spec.

My requirement was to create a program to convert all the RGB vector data in a PDF to CMYK using predefined conversion values. Here is some prototype code I wrote to accomplish this. You might can change it to work for just text:

private void ConvertDocToCMYK()
{
PdfDocument rgbdoc = PdfReader.Open("C:\\pdf\\NebraskaDOR(rgb).pdf", PdfDocumentOpenMode.Modify);
PdfPage rgbpage = rgbdoc.Pages[0];

//get all the internal objects from the pdf
PdfObject[] obj = rgbdoc.Internals.GetAllObjects();

//loop through all of those objects looking for streams
for (int i = 0; i < obj.Length; i++)
{
PdfDictionary dict = (PdfDictionary)obj[i];

//if the object doesn't contain a stream then just skip it
if (dict.Stream != null)
{
//there should also not be a subtype if this stream contains vector data???
object subType = dict.Elements["/Subtype"];
if (subType == null)
{
PdfDictionary.PdfStream stream = dict.Stream;

//decode the stream
bool pass = stream.TryUnfilter();
string temp = stream.ToString();

//look for the op-codes and change values
ParseString(ref temp);

//re encode the dtream
byte[] b = PdfDictionary.PdfStream.RawEncode(temp);

PdfInteger integer = new PdfInteger(b.Length);

//set the old stream to null, do we need to dispose of this some how???
dict.Stream = null;
//set the length of the new stream
dict.Elements["/Length"] = integer;
//create the new stream
dict.CreateStream(b);

//delete the old dictionary from the page
rgbdoc.Internals.RemoveObject(obj[i]);
//add the dictionary we just created
rgbdoc.Internals.AddObject(dict);

}
}
}

rgbdoc.Options.ColorMode = PdfColorMode.Cmyk;
rgbdoc.Save("C:\\pdf\\testconvert.pdf");
}

private void ParseString(ref string stream)
{
string temp;
string r, g, b, c, m, y, k;
int beginIndex, endIndex, lineIndex;
int rBeginIndex, rEndIndex, gBeginIndex, gEndIndex, bBeginIndex, bEndIndex;

//rg is the op code for drawing in RGB, find all instances of this and change to CMYK
while (stream.Contains(" rg"))
{
endIndex = stream.IndexOf(" rg") + 3;

bEndIndex = endIndex - 3;

temp = stream.Substring(0, bEndIndex);

bBeginIndex = temp.LastIndexOf(" ");

b = temp.Substring(bBeginIndex, bEndIndex - bBeginIndex);

gEndIndex = bBeginIndex;
temp = temp.Substring(0, gEndIndex);

gBeginIndex = temp.LastIndexOf(" ");

g = temp.Substring(gBeginIndex, gEndIndex - gBeginIndex);

rEndIndex = gBeginIndex;
temp = temp.Substring(0, rEndIndex);

rBeginIndex = temp.LastIndexOf(" ");
lineIndex = temp.LastIndexOf("\n") + 1;

if (rBeginIndex < lineIndex)
rBeginIndex = lineIndex;

r = temp.Substring(rBeginIndex, rEndIndex - rBeginIndex);

beginIndex = rBeginIndex;

ConvertRGBToCMYK(r, g, b, out c, out m, out y, out k);

stream = stream.Remove(beginIndex, endIndex - beginIndex);

stream = stream.Insert(beginIndex, c + " " + m + " " + y + " " + k + " k");
}

//also check for the capitalized version
while (stream.Contains(" RG"))
{
endIndex = stream.IndexOf(" RG") + 3;

bEndIndex = endIndex - 3;

temp = stream.Substring(0, bEndIndex);

bBeginIndex = temp.LastIndexOf(" ");

b = temp.Substring(bBeginIndex, bEndIndex - bBeginIndex);

gEndIndex = bBeginIndex;
temp = temp.Substring(0, gEndIndex);

gBeginIndex = temp.LastIndexOf(" ");

g = temp.Substring(gBeginIndex, gEndIndex - gBeginIndex);

rEndIndex = gBeginIndex;
temp = temp.Substring(0, rEndIndex);

rBeginIndex = temp.LastIndexOf(" ");
lineIndex = temp.LastIndexOf("\n") + 1;

if (rBeginIndex < lineIndex)
rBeginIndex = lineIndex;

r = temp.Substring(rBeginIndex, rEndIndex - rBeginIndex);

beginIndex = rBeginIndex;

ConvertRGBToCMYK(r, g, b, out c, out m, out y, out k);

stream = stream.Remove(beginIndex, endIndex - beginIndex);

stream = stream.Insert(beginIndex, c + " " + m + " " + y + " " + k + " K");
}

}

This may be over kill for what you are trying to do. Maybe somebody else will chime in with a much easier way of changing the color of just the text.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/