using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Text; namespace FastReport.RichTextParser { internal class RTF_Picture : RTF_CommonRichElement { internal Picture picture = new Picture(); internal long metamapmode; public RTF_Picture() { picture.scalex = 100; picture.scaley = 100; subdata_counter = 1; } internal override RichObject RichObject { get { RichObject rich = new RichObject(); rich.type = RichObject.Type.Picture; rich.picture = picture; rich.size = picture.size; return rich; } } private enum State { PictHeader, BlipImage, BlipMetafile }; private State state = State.PictHeader; int subdata_counter; internal void CreateImage(Stream stream) { switch (state) { case State.PictHeader: throw new NotImplementedException("Image format not supported (yet)"); case State.BlipImage: picture.image = Bitmap.FromStream(stream); picture.width = picture.image.Width; picture.height = picture.image.Height; break; case State.BlipMetafile: #if true //picture.image = new Metafile(stream); picture.image = new Bitmap(stream); if (metamapmode == 8) { picture.width = picture.image.Width; picture.height = picture.image.Height; if (picture.desired_height != 0) picture.height = Twips2Pixels(picture.desired_height); if (picture.desired_width != 0) picture.height = Twips2Pixels(picture.desired_width); } #elif false using (var fileStream = File.Create("my.wmf")) { stream.Seek(0, SeekOrigin.Begin); stream.CopyTo(fileStream); } #else picture.image = new Bitmap(32, 32, PixelFormat.Format32bppArgb); using (Graphics graphics = Graphics.FromImage(picture.image)) { graphics.FillEllipse(Brushes.Brown, new Rectangle(new Point(0, 0), picture.image.Size)); } #endif break; } } private byte CharToHex(char ch) { if (char.IsDigit(ch)) return (byte)(ch - '0'); if (ch >= 'A' && ch <= 'F') return (byte)(10 + ch - 'A'); if (ch >= 'a' && ch <= 'f') return (byte)(10 + ch - 'a'); return 0; } internal bool ParseBlip(RTF_Parser parser, RTF_Header header) { int i, j; int len = parser.Text.Length; byte h = 0, l; byte[] raw_pict = new byte[len >> 1]; for (i = j = 0; i < len; i++) { if ((i & 1) == 0) { h = CharToHex(parser.Text[i]); } else { l = CharToHex(parser.Text[i]); raw_pict[j++] = (byte)((h << 4) | l); } } try { CreateImage(new MemoryStream(raw_pict)); } catch (Exception e) { if (picture.desired_height != 0) picture.height = Twips2Pixels(picture.desired_height); if (picture.desired_width != 0) picture.width = Twips2Pixels(picture.desired_width); picture.image = new Bitmap(picture.width, picture.height); Graphics g = Graphics.FromImage(picture.image); g.DrawString("Unable load bitmap", new Font(FontFamily.GenericMonospace, 10), new SolidBrush(Color.Red), 5, 5); ; g.DrawString(e.Message, new Font(FontFamily.GenericMonospace, 8), new SolidBrush(Color.Red), 5, 20); ; } return false; } internal override bool Parse(RTF_Parser parser, RTF_Header header) { if (parser.Status == ParserStatus.OpenBlock) { subdata_counter++; picture.horizontalAlign = parser.current_paragraph_format.align; } if (parser.Status == ParserStatus.CloseBlock) // if (parser.Status == ParserStatus.OpenBlock) { subdata_counter--; } switch (parser.Control) { case "picw": picture.width = (int)parser.Number; break; case "pich": picture.height = (int)parser.Number; break; case "picscalex": picture.scalex = (int)parser.Number; break; case "picscaley": picture.scaley = (int)parser.Number; break; case "pngblip": state = State.BlipImage; break; case "jpegblip": state = State.BlipImage; break; case "piccropt": picture.crop_top = Twips2Pixels(parser.Number); break; case "piccropl": picture.crop_left = Twips2Pixels(parser.Number); break; case "piccropb": picture.crop_bottom = Twips2Pixels(parser.Number); break; case "piccropr": picture.crop_right = Twips2Pixels(parser.Number); break; case "picprop": picture.picprop = true; break; case "picwgoal": case "picwGoal": picture.desired_width = (int) parser.Number; break; case "pichgoal": case "pichGoal": picture.desired_height = (int)parser.Number; break; case "wmetafile": state = State.BlipMetafile; metamapmode = parser.Number; break; case "emfblip": state = State.BlipMetafile; metamapmode = parser.Number; break; case "bliptag": picture.tag = (int)parser.Number; break; case "blipupi": picture.units_per_inch = (int)parser.Number; break; case "blipuid": ; break; case "": if (parser.Status == ParserStatus.CloseBlock) { if (parser.Text.Length != 0) { if(subdata_counter <= 0) return ParseBlip(parser, header); } } break; case "sp": // Word-2007 shape property break; case "sn": // Word-2007 shape property name break; case "sv": // Word-2007 shape property value break; default: #if DEBUG_RTF throw new NotImplementedException(parser.Control); #else break; #endif } return true; } } }