سؤال

لقد حصلت على richtextbox ، أنا على خطة إنقاذ إلى قاعدة البيانات التي يمكن تحميلها مرة أخرى في نفس richtextbox.لقد حصلت على هذا العمل بحيث لا يمكن حفظ flowdocument كما DataFormats.XamlPackage الذي يحفظ الصور, ولكن القضية هي أن النص ليس للبحث.مع DataFormats.Xaml لدي النص بالطبع, ولكن لا الصور.الصور سيتم لصق في من قبل المستخدم النهائي ، وليس الصور المضمنة مع التطبيق.

حاولت استخدام XamlWriter للحصول على النص في XML ثم انتزاع الصور من وثيقة على حدة وإدراجها الثنائية في XML, ولكن أنا لا يمكن أن يبدو للعثور على وسيلة للحصول على الصور الثنائية...

هل من أحد لديه أفكار حول كيفية الحصول على الصور في ثنائي منفصل عن النص ؟

شكرا مقدما!

GetImageByteArray() هو أين المشكلة.

كود:

private void SaveXML()
{
            TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
            FlowDocument flowDocument = richTextBox.Document;
using (StringWriter stringwriter = new StringWriter())
                {
                    using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter))
                    {
                        XamlWriter.Save(flowDocument, writer );
                    }

                    testRTF t = new testRTF();
                    t.RtfText = new byte[0];
                    t.RtfXML = GetImagesXML(flowDocument);
                    t.RtfFullText = stringwriter.ToString();
                    //save t to database
                }
                richTextBox.Document.Blocks.Clear();
}


private string GetImagesXML(FlowDocument flowDocument)
        {

            using (StringWriter stringwriter = new StringWriter())
            {
                using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter))
                {

                    Type inlineType;
                    InlineUIContainer uic;
                    System.Windows.Controls.Image replacementImage;
                    byte[] bytes;
                    System.Text.ASCIIEncoding enc;

                    //loop through replacing images in the flowdoc with the byte versions
                    foreach (Block b in flowDocument.Blocks)
                    {
                        foreach (Inline i in ((Paragraph)b).Inlines)
                        {
                            inlineType = i.GetType();

                            if (inlineType == typeof(Run))
                            {
                                //The inline is TEXT!!!
                            }
                            else if (inlineType == typeof(InlineUIContainer))
                            {
                                //The inline has an object, likely an IMAGE!!!
                                uic = ((InlineUIContainer)i);

                                //if it is an image
                                if (uic.Child.GetType() == typeof(System.Windows.Controls.Image))
                                {
                                    //grab the image
                                    replacementImage = (System.Windows.Controls.Image)uic.Child;

                                    //get its byte array
                                    bytes = GetImageByteArray((BitmapImage)replacementImage.Source);
                                    //write the element
                                    writer.WriteStartElement("Image");
                                    //put the bytes into the tag
                                    enc = new System.Text.ASCIIEncoding();
                                    writer.WriteString(enc.GetString(bytes));
                                    //close the element
                                    writer.WriteEndElement();
                                }
                            }
                        }
                    }
                }

                return stringwriter.ToString();
            }
        }


//This function is where the problem is, i need a way to get the byte array
        private byte[] GetImageByteArray(BitmapImage bi)
        {
            byte[] result = new byte[0];
                    using (MemoryStream ms = new MemoryStream())
                    {
                        XamlWriter.Save(bi, ms);
                        //result = new byte[ms.Length];
                        result = ms.ToArray();
                    }
            return result;
}

التحديث

أعتقد أنني قد وجدت الحل الذي سوف أنشر أدناه.ويستخدم BmpBitmapEncoder و BmpBitmapDecoder.هذا يسمح لي للحصول على الثنائية من صورة نقطية, تخزين قاعدة البيانات و تحميل إعادته وعرض الحق في العودة إلى FlowDocument.الفحوصات الأولية أثبتت نجاحها.لأغراض الاختبار أنا وتجاوز قاعدة البيانات الخاصة بي الخطوة الأساس تكرار الصورة من خلال خلق الثنائية ، ثم أخذ الثنائية ويحولها إلى صورة جديدة وإضافتها إلى FlowDocument.القضية الوحيدة هي أنني عندما تحاول تعديل FlowDocument واستخدام XamlWriter.حفظ وظيفة, ومن الأخطاء التي تم إنشاؤها حديثا صورة مع "لا يمكن إجراء تسلسل غير العامة من النوع 'System.يقوم نظام ويندوز.وسائل الاعلام.التصوير.BitmapFrameDecode".وهذا سوف يستغرق بعض مزيد من التحقيق.يجب أن تترك وحدها الآن على الرغم.

private void SaveXML()
        {
            TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
            FlowDocument flowDocument = richTextBox.Document;

            string s = GetImagesXML(flowDocument);//temp
            LoadImagesIntoXML(s);

                using (StringWriter stringwriter = new StringWriter())
                {
                    using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter))
                    {
                        XamlWriter.Save(flowDocument, writer );//Throws error here
                    }

                }
}

private string GetImagesXML(FlowDocument flowDocument)
        {
            string s= "";

            using (StringWriter stringwriter = new StringWriter())
            {


                    Type inlineType;
                    InlineUIContainer uic;
                    System.Windows.Controls.Image replacementImage;
                    byte[] bytes;
                    BitmapImage bi;

                    //loop through replacing images in the flowdoc with the byte versions
                    foreach (Block b in flowDocument.Blocks)
                    {
                        foreach (Inline i in ((Paragraph)b).Inlines)
                        {
                            inlineType = i.GetType();

                            if (inlineType == typeof(Run))
                            {
                                //The inline is TEXT!!!
                            }
                            else if (inlineType == typeof(InlineUIContainer))
                            {
                                //The inline has an object, likely an IMAGE!!!
                                uic = ((InlineUIContainer)i);

                                //if it is an image
                                if (uic.Child.GetType() == typeof(System.Windows.Controls.Image))
                                {
                                    //grab the image
                                    replacementImage = (System.Windows.Controls.Image)uic.Child;
                                    bi = (BitmapImage)replacementImage.Source;

                                    //get its byte array
                                    bytes = GetImageByteArray(bi);

                                    s = Convert.ToBase64String(bytes);//temp
                                }
                            }
                        }
                    }

                return s;
            }
        }

private byte[] GetImageByteArray(BitmapImage src)
        {
                MemoryStream stream = new MemoryStream();
                BmpBitmapEncoder encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create((BitmapSource)src));
                encoder.Save(stream);
                stream.Flush();
            return stream.ToArray();
        }


private void LoadImagesIntoXML(string xml)
        {


            byte[] imageArr = Convert.FromBase64String(xml);
System.Windows.Controls.Image img = new System.Windows.Controls.Image()

MemoryStream stream = new MemoryStream(imageArr);
            BmpBitmapDecoder decoder = new BmpBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default);
            img.Source = decoder.Frames[0];
            img.Stretch = Stretch.None;

Paragraph p = new Paragraph();
            p.Inlines.Add(img);
            richTextBox.Document.Blocks.Add(p);
        }
هل كانت مفيدة؟

المحلول

أخبار جيدة.علي أن أعمل على شيء آخر لفترة من الوقت, ولكن هذا ما سمح لي أن أعود مع زوج جديد من العيون.أدركت بسرعة أن أنا فقط يمكن الجمع بين ما عرفته كان العامل.أشك في هذا الحل سوف يفوز أي جوائز ، لكنه يعمل.وأنا أعلم أنني يمكن أن التفاف FlowDocument كما نص باستخدام XamlReader ، والحفاظ على عناصر الصورة ولكن فقدان بيانات الصورة.أنا أيضا أعرف أنني يمكن أن تتحول FlowDocument إلى ثنائي باستخدام XamlFormat.إذا كان لدي فكرة أخذ FlowDocument ، باستخدام وظيفة كتبت بالفعل للتنقل من خلال ذلك إلى العثور على الصور ، أود أن أغتنم كل صورة ، أساسا استنساخ ووضعها استنساخ جديد FlowDocument.أنا أعتبر أن الجديد FlowDocument الآن يحتوي على صورة واحدة ، وتحويلها إلى الثنائية ، ومن ثم اتخاذ الناتجة الثنائية ، وتحويلها إلى base64 سلسلة والتمسك بها في الوسم الملكية من الصورة الأصلية FlowDocument.هذا يحافظ بيانات الصورة الأصلية FlowDocument كنص.هذه الطريقة لا يمكن أن تمر FlowDocument مع بيانات الصورة (الذي أسميه فرعية Format) في XamlReader للحصول على نص يمكن البحث فيه.عندما يخرج من قاعدة البيانات ، أنا سحب FlowDocument من Xaml بشكل طبيعي, ولكن بعد ذلك من خلال تكرار كل صورة ، واستخراج البيانات من بطاقة المنشأة باستخدام XamlFormat ثم خلق آخر استنساخ صورة لتوفير مصدر الملكية بالنسبة لي الصورة الفعلية.قدمت الخطوات للوصول الى فرعية الشكل أدناه.

/// <summary>
    /// Returns a FlowDocument in SearchableText UI Binary (SUB)String format.
    /// </summary>
    /// <param name="flowDocument">The FlowDocument containing images/UI formats to be converted</param>
    /// <returns>Returns a string representation of the FlowDocument with images in base64 string in image tag property</returns>
    private string ConvertFlowDocumentToSUBStringFormat(FlowDocument flowDocument)
    {
        //take the flow document and change all of its images into a base64 string
        FlowDocument fd = TransformImagesTo64(flowDocument);

        //apply the XamlWriter to the newly transformed flowdocument
        using (StringWriter stringwriter = new StringWriter())
        {
            using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter))
            {
                XamlWriter.Save(flowDocument, writer);
            }
            return stringwriter.ToString();
        }
    }

    /// <summary>
    /// Returns a FlowDocument with images in base64 stored in their own tag property
    /// </summary>
    /// <param name="flowDocument">The FlowDocument containing images/UI formats to be converted</param>
    /// <returns>Returns a FlowDocument with images in base 64 string in image tag property</returns>
    private FlowDocument TransformImagesTo64(FlowDocument flowDocument)
    {
        FlowDocument img_flowDocument;
        Paragraph img_paragraph;
        InlineUIContainer img_inline;
        System.Windows.Controls.Image newImage;
        Type inlineType;
        InlineUIContainer uic;
        System.Windows.Controls.Image replacementImage;

        //loop through replacing images in the flowdoc with the base64 versions
        foreach (Block b in flowDocument.Blocks)
        {
            //loop through inlines looking for images
            foreach (Inline i in ((Paragraph)b).Inlines)
            {
                inlineType = i.GetType();

                /*if (inlineType == typeof(Run))
                {
                    //The inline is TEXT!!! $$$$$ Kept in case needed $$$$$
                }
                else */if (inlineType == typeof(InlineUIContainer))
                {
                    //The inline has an object, likely an IMAGE!!!
                    uic = ((InlineUIContainer)i);

                    //if it is an image
                    if (uic.Child.GetType() == typeof(System.Windows.Controls.Image))
                    {
                        //grab the image
                        replacementImage = (System.Windows.Controls.Image)uic.Child;

                        //create a new image to be used to get base64
                        newImage = new System.Windows.Controls.Image();
                        //clone the image from the image in the flowdocument
                        newImage.Source = replacementImage.Source;

                        //create necessary objects to obtain a flowdocument in XamlFormat to get base 64 from
                        img_inline = new InlineUIContainer(newImage);
                        img_paragraph = new Paragraph(img_inline);
                        img_flowDocument = new FlowDocument(img_paragraph);

                        //Get the base 64 version of the XamlFormat binary
                        replacementImage.Tag = TransformImageTo64String(img_flowDocument);
                    }
                }
            }
        }
        return flowDocument;
    }

    /// <summary>
    /// Takes a FlowDocument containing a SINGLE Image, and converts to base 64 using XamlFormat
    /// </summary>
    /// <param name="flowDocument">The FlowDocument containing a SINGLE Image</param>
    /// <returns>Returns base 64 representation of image</returns>
    private string TransformImageTo64String(FlowDocument flowDocument)
    {
        TextRange documentTextRange = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd);
        using (MemoryStream ms = new MemoryStream())
        {
            documentTextRange.Save(ms, DataFormats.XamlPackage);
            ms.Position = 0;
            return Convert.ToBase64String(ms.ToArray());
        }
    }

نصائح أخرى

حفظ الصور الخاصة بك إلى MemoryStream لكتابة هذا التيار إلى ملف XML.

الذاكرة تيار سيتم تحويلها إلى Byte[].

هنا هو نموذج التعليمة البرمجية لكل من الاقتراحات التي قدمت بالفعل, المرضى يجب أن ننظر إلى الحمولة مسألة لو الأمثلة لا تعمل...

        // get raw bytes from BitmapImage using BaseUri and SourceUri
    private byte[] GetImageByteArray(BitmapImage bi)
    {
        byte[] result = new byte[0];
        string strImagePath = Path.Combine(Path.GetDirectoryName(bi.BaseUri.OriginalString), bi.UriSource.OriginalString);
        byte[] fileBuffer;
        using (FileStream fileStream = new FileStream(strImagePath, FileMode.Open))
        {
            fileBuffer = new byte[fileStream.Length];
            fileStream.Write(fileBuffer, 0, (int)fileStream.Length);
        }
        using (MemoryStream ms = new MemoryStream(fileBuffer))
        {
            XamlWriter.Save(bi, ms);
            //result = new byte[ms.Length];
            result = ms.ToArray();
        }
        return result;
    }
    // get raw bytes from BitmapImage using BitmapImage.CopyPixels
    private byte[] GetImageByteArray(BitmapSource bi)
    {
        int rawStride = (bi.PixelWidth * bi.Format.BitsPerPixel + 7) / 8;
        byte[] result = new byte[rawStride * bi.PixelHeight];
        bi.CopyPixels(result, rawStride, 0);
        return result;
    }
    private BitmapSource GetImageFromByteArray(byte[] pixelInfo, int height, int width)
    {
        PixelFormat pf = PixelFormats.Bgr32;
        int stride = (width * pf.BitsPerPixel + 7) / 8;
        BitmapSource image = BitmapSource.Create(width, height, 96, 96, pf, null, pixelInfo, stride);
        return image;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top