private void AddSoftMask( List <PDFobj> objects, byte[] data, String colorSpace, int bitsPerComponent) { PDFobj obj = new PDFobj(); obj.dict.Add("<<"); obj.dict.Add("/Type"); obj.dict.Add("/XObject"); obj.dict.Add("/Subtype"); obj.dict.Add("/Image"); obj.dict.Add("/Filter"); obj.dict.Add("/FlateDecode"); obj.dict.Add("/Width"); obj.dict.Add(((int)w).ToString()); obj.dict.Add("/Height"); obj.dict.Add(((int)h).ToString()); obj.dict.Add("/ColorSpace"); obj.dict.Add("/" + colorSpace); obj.dict.Add("/BitsPerComponent"); obj.dict.Add(bitsPerComponent.ToString()); obj.dict.Add("/Length"); obj.dict.Add(data.Length.ToString()); obj.dict.Add(">>"); obj.SetStream(data); obj.number = objects.Count + 1; objects.Add(obj); objNumber = obj.number; }
private void AddSoftMask( SortedDictionary <Int32, PDFobj> objects, byte[] data, String colorSpace, int bitsPerComponent) { PDFobj obj = new PDFobj(); List <String> dict = obj.GetDict(); dict.Add("<<"); dict.Add("/Type"); dict.Add("/XObject"); dict.Add("/Subtype"); dict.Add("/Image"); dict.Add("/Filter"); dict.Add("/FlateDecode"); dict.Add("/Width"); dict.Add(((int)w).ToString()); dict.Add("/Height"); dict.Add(((int)h).ToString()); dict.Add("/ColorSpace"); dict.Add("/" + colorSpace); dict.Add("/BitsPerComponent"); dict.Add(bitsPerComponent.ToString()); dict.Add("/Length"); dict.Add(data.Length.ToString()); dict.Add(">>"); obj.SetStream(data); obj.number = MaxKey(objects.Keys) + 1; objects.Add(obj.number, obj); objNumber = obj.number; }
private static void AddToUnicodeCMapObject( SortedDictionary <Int32, PDFobj> objects, Font font) { StringBuilder sb = new StringBuilder(); sb.Append("/CIDInit /ProcSet findresource begin\n"); sb.Append("12 dict begin\n"); sb.Append("begincmap\n"); sb.Append("/CIDSystemInfo <</Registry (Adobe) /Ordering (Identity) /Supplement 0>> def\n"); sb.Append("/CMapName /Adobe-Identity def\n"); sb.Append("/CMapType 2 def\n"); sb.Append("1 begincodespacerange\n"); sb.Append("<0000> <FFFF>\n"); sb.Append("endcodespacerange\n"); List <String> list = new List <String>(); StringBuilder buf = new StringBuilder(); for (int cid = 0; cid <= 0xffff; cid++) { int gid = font.unicodeToGID[cid]; if (gid > 0) { buf.Append('<'); buf.Append(ToHexString(gid)); buf.Append("> <"); buf.Append(ToHexString(cid)); buf.Append(">\n"); list.Add(buf.ToString()); buf.Length = 0; if (list.Count == 100) { WriteListToBuffer(list, sb); } } } if (list.Count > 0) { WriteListToBuffer(list, sb); } sb.Append("endcmap\n"); sb.Append("CMapName currentdict /CMap defineresource pop\n"); sb.Append("end\nend"); PDFobj obj = new PDFobj(); List <String> dict = obj.GetDict(); dict.Add("<<"); dict.Add("/Length"); dict.Add(sb.Length.ToString()); dict.Add(">>"); obj.SetStream((new System.Text.UTF8Encoding()).GetBytes(sb.ToString())); obj.number = MaxKey(objects.Keys) + 1; objects.Add(obj.number, obj); font.SetToUnicodeCMapObjNumber(obj.number); }
/** * Adds new content object before the existing content objects. * The original code was provided by Stefan Ostermann author of ScribMaster and HandWrite Pro. * Additional code to handle PDFs with indirect array of stream objects was written by EDragoev. * * @param content * @param objects */ public void AddPrefixContent(byte[] content, List <PDFobj> objects) { PDFobj obj = new PDFobj(); obj.SetNumber(objects.Count + 1); obj.SetStream(content); objects.Add(obj); String objNumber = obj.number.ToString(); for (int i = 0; i < dict.Count; i++) { if (dict[i].Equals("/Contents")) { i += 1; String token = dict[i]; if (token.Equals("[")) { // Array of content object streams i += 1; dict.Insert(i, "R"); dict.Insert(i, "0"); dict.Insert(i, objNumber); return; } else { // Single content object PDFobj obj2 = objects[Int32.Parse(token) - 1]; if (obj2.data == null && obj2.stream == null) { // This is not a stream object! for (int j = 0; j < obj2.dict.Count; j++) { if (obj2.dict[j].Equals("[")) { j += 1; obj2.dict.Insert(j, "R"); obj2.dict.Insert(j, "0"); obj2.dict.Insert(j, objNumber); return; } } } dict.Insert(i, "["); dict.Insert(i + 4, "]"); i += 1; dict.Insert(i, "R"); dict.Insert(i, "0"); dict.Insert(i, objNumber); return; } } } }
private void GetPdfObjects2(byte[] pdf, PDFobj obj, List <PDFobj> pdfObjects) { string value = obj.GetValue("/Prev"); if (!value.Equals("")) { this.GetPdfObjects2(pdf, this.GetObject(pdf, int.Parse(value)), pdfObjects); } obj.SetStream(pdf, int.Parse(obj.GetValue("/Length"))); Decompressor decompressor = new Decompressor(obj.stream); byte[] decompressedData = decompressor.getDecompressedData(); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; for (int i = 0; i < obj.dict.Count; i++) { string text = obj.dict[i]; if (text.Equals("/Predictor") && obj.dict[i + 1].Equals("12")) { num = 1; } if (text.Equals("/W")) { num2 = int.Parse(obj.dict[i + 2]); num3 = int.Parse(obj.dict[i + 3]); num4 = int.Parse(obj.dict[i + 4]); } } int num5 = num + num2 + num3 + num4; byte[] array = new byte[num5]; for (int j = 0; j < decompressedData.Length; j += num5) { for (int k = 0; k < num5; k++) { byte[] expr_135_cp_0 = array; int expr_135_cp_1 = k; expr_135_cp_0[expr_135_cp_1] += decompressedData[j + k]; } if (array[1] == 1) { int off = this.ToInt(array, num + num2, num3); pdfObjects.Add(this.GetObject(pdf, off, pdf.Length)); } } }
private static void EmbedFontFile( SortedDictionary <Int32, PDFobj> objects, Font font, Stream inputStream) { int metadataObjNumber = AddMetadataObject(objects, font); PDFobj obj = new PDFobj(); List <String> dict = obj.GetDict(); dict.Add("<<"); dict.Add("/Metadata"); dict.Add(metadataObjNumber.ToString()); dict.Add("0"); dict.Add("R"); dict.Add("/Filter"); dict.Add("/FlateDecode"); dict.Add("/Length"); dict.Add(font.compressed_size.ToString()); if (font.cff) { dict.Add("/Subtype"); dict.Add("/CIDFontType0C"); } else { dict.Add("/Length1"); dict.Add(font.uncompressed_size.ToString()); } dict.Add(">>"); MemoryStream buf2 = new MemoryStream(); byte[] buf = new byte[16384]; int len; while ((len = inputStream.Read(buf, 0, buf.Length)) > 0) { buf2.Write(buf, 0, len); } inputStream.Close(); obj.SetStream(buf2.ToArray()); obj.number = MaxKey(objects.Keys) + 1; objects.Add(obj.number, obj); font.fileObjNumber = obj.number; }
private static void EmbedFontFile( List <PDFobj> objects, Font font, Stream inputStream) { int metadataObjNumber = AddMetadataObject(objects, font); PDFobj obj = new PDFobj(); obj.dict.Add("<<"); obj.dict.Add("/Metadata"); obj.dict.Add(metadataObjNumber.ToString()); obj.dict.Add("0"); obj.dict.Add("R"); obj.dict.Add("/Filter"); obj.dict.Add("/FlateDecode"); obj.dict.Add("/Length"); obj.dict.Add(font.compressedSize.ToString()); if (font.cff) { obj.dict.Add("/Subtype"); obj.dict.Add("/CIDFontType0C"); } else { obj.dict.Add("/Length1"); obj.dict.Add(font.uncompressedSize.ToString()); } obj.dict.Add(">>"); MemoryStream buf2 = new MemoryStream(); byte[] buf = new byte[4096]; int len; while ((len = inputStream.Read(buf, 0, buf.Length)) > 0) { buf2.Write(buf, 0, len); } inputStream.Close(); obj.SetStream(buf2.ToArray()); obj.number = objects.Count + 1; objects.Add(obj); font.fileObjNumber = obj.number; }
private static int AddMetadataObject( SortedDictionary <Int32, PDFobj> objects, Font font) { StringBuilder sb = new StringBuilder(); sb.Append("<?xpacket begin='\uFEFF' id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"); sb.Append("<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">\n"); sb.Append("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"); sb.Append("<rdf:Description rdf:about=\"\" xmlns:xmpRights=\"http://ns.adobe.com/xap/1.0/rights/\">\n"); sb.Append("<xmpRights:UsageTerms>\n"); sb.Append("<rdf:Alt>\n"); sb.Append("<rdf:li xml:lang=\"x-default\">\n"); sb.Append(font.info); sb.Append("</rdf:li>\n"); sb.Append("</rdf:Alt>\n"); sb.Append("</xmpRights:UsageTerms>\n"); sb.Append("</rdf:Description>\n"); sb.Append("</rdf:RDF>\n"); sb.Append("</x:xmpmeta>\n"); sb.Append("<?xpacket end=\"w\"?>"); byte[] xml = (new System.Text.UTF8Encoding()).GetBytes(sb.ToString()); // This is the metadata object PDFobj obj = new PDFobj(); List <String> dict = obj.GetDict(); dict.Add("<<"); dict.Add("/Type"); dict.Add("/Metadata"); dict.Add("/Subtype"); dict.Add("/XML"); dict.Add("/Length"); dict.Add(xml.Length.ToString()); dict.Add(">>"); obj.SetStream(xml); obj.number = MaxKey(objects.Keys) + 1; objects.Add(obj.number, obj); return(obj.number); }
public Dictionary <int, PDFobj> Read(Stream inputStream) { List <PDFobj> list = new List <PDFobj>(); MemoryStream memoryStream = new MemoryStream(); int num; while ((num = inputStream.ReadByte()) != -1) { memoryStream.WriteByte((byte)num); } byte[] array = memoryStream.ToArray(); int startXRef = this.GetStartXRef(array); PDFobj pDFobj = this.GetObject(array, startXRef); if (pDFobj.dict[0].Equals("xref")) { this.GetPdfObjects1(array, pDFobj, list); } else { this.GetPdfObjects2(array, pDFobj, list); } Dictionary <int, PDFobj> dictionary = new Dictionary <int, PDFobj>(); for (int i = 0; i < list.Count; i++) { pDFobj = list[i]; pDFobj.number = int.Parse(pDFobj.dict[0]); if (pDFobj.dict.Contains("stream")) { pDFobj.SetStream(array, pDFobj.GetLength(list)); } if (pDFobj.GetValue("/Filter").Equals("/FlateDecode")) { Decompressor decompressor = new Decompressor(pDFobj.stream); pDFobj.data = decompressor.getDecompressedData(); } if (pDFobj.GetValue("/Type").Equals("/ObjStm")) { int num2 = int.Parse(pDFobj.GetValue("/First")); int.Parse(pDFobj.GetValue("/N")); PDFobj @object = this.GetObject(pDFobj.data, 0, num2); for (int j = 0; j < @object.dict.Count; j += 2) { int key = int.Parse(@object.dict[j]); int num3 = int.Parse(@object.dict[j + 1]); int len = pDFobj.data.Length; if (j <= @object.dict.Count - 4) { len = num2 + int.Parse(@object.dict[j + 3]); } PDFobj object2 = this.GetObject(pDFobj.data, num2 + num3, len); object2.dict.Insert(0, "obj"); object2.dict.Insert(0, "0"); object2.dict.Insert(0, key.ToString()); dictionary[key] = object2; } } else { dictionary[pDFobj.number] = pDFobj; } } return(dictionary); }
public Dictionary <Int32, PDFobj> Read(Stream inputStream) { List <PDFobj> objects = new List <PDFobj>(); MemoryStream baos = new MemoryStream(); int ch; while ((ch = inputStream.ReadByte()) != -1) { baos.WriteByte((byte)ch); } byte[] pdf = baos.ToArray(); int xref = GetStartXRef(pdf); PDFobj obj = GetObject(pdf, xref); if (obj.dict[0].Equals("xref")) { GetPdfObjects1(pdf, obj, objects); } else { GetPdfObjects2(pdf, obj, objects); } Dictionary <Int32, PDFobj> pdfObjects = new Dictionary <Int32, PDFobj>(); for (int i = 0; i < objects.Count; i++) { obj = objects[i]; obj.number = Int32.Parse(obj.dict[0]); if (obj.dict.Contains("stream")) { obj.SetStream(pdf, obj.GetLength(objects)); } if (obj.GetValue("/Filter").Equals("/FlateDecode")) { Decompressor decompressor = new Decompressor(obj.stream); obj.data = decompressor.getDecompressedData(); } if (obj.GetValue("/Type").Equals("/ObjStm")) { int first = Int32.Parse(obj.GetValue("/First")); int n = Int32.Parse(obj.GetValue("/N")); PDFobj o2 = GetObject(obj.data, 0, first); for (int j = 0; j < o2.dict.Count; j += 2) { int num = Int32.Parse(o2.dict[j]); int off = Int32.Parse(o2.dict[j + 1]); int end = obj.data.Length; if (j <= o2.dict.Count - 4) { end = first + Int32.Parse(o2.dict[j + 3]); } PDFobj o3 = GetObject(obj.data, first + off, end); o3.dict.Insert(0, "obj"); o3.dict.Insert(0, "0"); o3.dict.Insert(0, num.ToString()); pdfObjects[num] = o3; } } else { pdfObjects[obj.number] = obj; } } return(pdfObjects); }
private void GetPdfObjects2( byte[] pdf, PDFobj obj, List <PDFobj> pdfObjects) { String prev = obj.GetValue("/Prev"); if (!prev.Equals("")) { GetPdfObjects2( pdf, GetObject(pdf, Int32.Parse(prev)), pdfObjects); } obj.SetStream(pdf, Int32.Parse(obj.GetValue("/Length"))); Decompressor decompressor = new Decompressor(obj.stream); byte[] data = decompressor.getDecompressedData(); int p1 = 0; // Predictor byte int f1 = 0; // Field 1 int f2 = 0; // Field 2 int f3 = 0; // Field 3 for (int i = 0; i < obj.dict.Count; i++) { String token = obj.dict[i]; if (token.Equals("/Predictor")) { if (obj.dict[i + 1].Equals("12")) { p1 = 1; } else { // TODO: } } if (token.Equals("/W")) { // "/W [ 1 3 1 ]" f1 = Int32.Parse(obj.dict[i + 2]); f2 = Int32.Parse(obj.dict[i + 3]); f3 = Int32.Parse(obj.dict[i + 4]); } } int n = p1 + f1 + f2 + f3; // Number of bytes per entry byte[] entry = new byte[n]; for (int i = 0; i < data.Length; i += n) { // Apply the 'Up' filter. for (int j = 0; j < n; j++) { entry[j] += data[i + j]; } if (entry[1] == 0x01) { int off = ToInt(entry, p1 + f1, f2); pdfObjects.Add(GetObject(pdf, off, pdf.Length)); } } }
private void GetObjects2( byte[] pdf, PDFobj obj, List<PDFobj> objects) { String prev = obj.GetValue("/Prev"); if (!prev.Equals("")) { GetObjects2( pdf, GetObject(pdf, Int32.Parse(prev)), objects); } obj.SetStream(pdf, Int32.Parse(obj.GetValue("/Length"))); try { Decompressor decompressor = new Decompressor(obj.stream); obj.data = decompressor.GetDecompressedData(); } catch (Exception e) { // Assume no compression. obj.data = obj.stream; } int p1 = 0; // Predictor byte int f1 = 0; // Field 1 int f2 = 0; // Field 2 int f3 = 0; // Field 3 for (int i = 0; i < obj.dict.Count; i++) { String token = obj.dict[i]; if (token.Equals("/Predictor")) { if (obj.dict[i + 1].Equals("12")) { p1 = 1; } } if (token.Equals("/W")) { // "/W [ 1 3 1 ]" f1 = Int32.Parse(obj.dict[i + 2]); f2 = Int32.Parse(obj.dict[i + 3]); f3 = Int32.Parse(obj.dict[i + 4]); } } int n = p1 + f1 + f2 + f3; // Number of bytes per entry byte[] entry = new byte[n]; for (int i = 0; i < obj.data.Length; i += n) { // Apply the 'Up' filter. for (int j = 0; j < n; j++) { entry[j] += obj.data[i + j]; } // Process the entries in a cross-reference stream // Page 51 in PDF32000_2008.pdf if (entry[p1] == 1) { // Type 1 entry PDFobj o2 = GetObject(pdf, ToInt(entry, p1 + f1, f2)); o2.number = Int32.Parse(o2.dict[0]); objects.Add(o2); } } }
private void AddImage( SortedDictionary <Int32, PDFobj> objects, byte[] data, byte[] alpha, int imageType, String colorSpace, int bitsPerComponent) { if (alpha != null) { AddSoftMask(objects, alpha, "DeviceGray", 8); } PDFobj obj = new PDFobj(); List <String> dict = obj.GetDict(); dict.Add("<<"); dict.Add("/Type"); dict.Add("/XObject"); dict.Add("/Subtype"); dict.Add("/Image"); if (imageType == ImageType.JPG) { dict.Add("/Filter"); dict.Add("/DCTDecode"); } else if (imageType == ImageType.PNG || imageType == ImageType.BMP) { dict.Add("/Filter"); dict.Add("/FlateDecode"); if (alpha != null) { dict.Add("/SMask"); dict.Add(objNumber.ToString()); dict.Add("0"); dict.Add("R"); } } dict.Add("/Width"); dict.Add(((int)w).ToString()); dict.Add("/Height"); dict.Add(((int)h).ToString()); dict.Add("/ColorSpace"); dict.Add("/" + colorSpace); dict.Add("/BitsPerComponent"); dict.Add(bitsPerComponent.ToString()); if (colorSpace.Equals("DeviceCMYK")) { // If the image was created with Photoshop - invert the colors: dict.Add("/Decode"); dict.Add("["); dict.Add("1.0"); dict.Add("0.0"); dict.Add("1.0"); dict.Add("0.0"); dict.Add("1.0"); dict.Add("0.0"); dict.Add("1.0"); dict.Add("0.0"); dict.Add("]"); } dict.Add("/Length"); dict.Add(data.Length.ToString()); dict.Add(">>"); obj.SetStream(data); obj.number = MaxKey(objects.Keys) + 1; objects.Add(obj.number, obj); objNumber = obj.number; }
public void AddContent(byte[] content, SortedDictionary <Int32, PDFobj> objects) { PDFobj obj = new PDFobj(); int maxObjNumber = -1; foreach (int number in objects.Keys) { if (number > maxObjNumber) { maxObjNumber = number; } } obj.SetNumber(maxObjNumber + 1); obj.SetStream(content); objects.Add(obj.GetNumber(), obj); int index = -1; bool single = false; for (int i = 0; i < dict.Count; i++) { if (dict[i].Equals("/Contents")) { String str = dict[++i]; if (str.Equals("[")) { for (;;) { str = dict[++i]; if (str.Equals("]")) { index = i; break; } ++i; // 0 ++i; // R } } else { // Single content object index = i; single = true; } break; } } if (single) { dict.Insert(index, "["); dict.Insert(index + 4, "]"); dict.Insert(index + 4, "R"); dict.Insert(index + 4, "0"); dict.Insert(index + 4, obj.number.ToString()); } else { dict.Insert(index, "R"); dict.Insert(index, "0"); dict.Insert(index, obj.number.ToString()); } }
/** * Adds new content object before the existing content objects. * The original code was provided by Stefan Ostermann author of ScribMaster and HandWrite Pro. * Additional code to handle PDFs with indirect array of stream objects was written by EDragoev. * * @param content * @param objects */ public void AddPrefixContent( byte[] content, SortedDictionary <Int32, PDFobj> objects) { PDFobj obj = new PDFobj(); int maxObjNumber = -1; foreach (int number in objects.Keys) { if (number > maxObjNumber) { maxObjNumber = number; } } obj.SetNumber(maxObjNumber + 1); obj.SetStream(content); objects[obj.GetNumber()] = obj; String objNumber = obj.number.ToString(); for (int i = 0; i < dict.Count; i++) { if (dict[i].Equals("/Contents")) { i += 1; String token = dict[i]; if (token.Equals("[")) { // Array of content object streams i += 1; dict.Insert(i, "R"); dict.Insert(i, "0"); dict.Insert(i, objNumber); return; } else { // Single content object PDFobj obj2 = objects[Int32.Parse(token)]; if (obj2.data == null && obj2.stream == null) { // This is not a stream object! for (int j = 0; j < obj2.dict.Count; j++) { if (obj2.dict[j].Equals("[")) { j += 1; obj2.dict.Insert(j, "R"); obj2.dict.Insert(j, "0"); obj2.dict.Insert(j, objNumber); return; } } } dict.Insert(i, "["); dict.Insert(i + 4, "]"); i += 1; dict.Insert(i, "R"); dict.Insert(i, "0"); dict.Insert(i, objNumber); return; } } } }
public void AddContent(byte[] content, SortedDictionary<Int32, PDFobj> objects) { PDFobj obj = new PDFobj(); int maxObjNumber = -1; foreach (int number in objects.Keys) { if (number > maxObjNumber) { maxObjNumber = number; } } obj.SetNumber(maxObjNumber + 1); obj.SetStream(content); objects.Add(obj.GetNumber(), obj); int index = -1; bool single = false; for (int i = 0; i < dict.Count; i++) { if (dict[i].Equals("/Contents")) { String str = dict[++i]; if (str.Equals("[")) { for (;;) { str = dict[++i]; if (str.Equals("]")) { index = i; break; } ++i; // 0 ++i; // R } } else { // Single content object index = i; single = true; } break; } } if (single) { dict.Insert(index, "["); dict.Insert(index + 4, "]"); dict.Insert(index + 4, "R"); dict.Insert(index + 4, "0"); dict.Insert(index + 4, obj.number.ToString()); } else { dict.Insert(index, "R"); dict.Insert(index, "0"); dict.Insert(index, obj.number.ToString()); } }