2009-11-30 19 views
6

में चिपकाया गया है मेरे पास एक समृद्ध टेक्स्टबॉक्स है, जिसे मैं डेटाबेस में सहेजने की योजना बना रहा हूं, जिसे उसी समृद्ध टेक्स्टबॉक्स में वापस लोड किया जा सकता है। मुझे यह काम मिल गया है ताकि मैं flowdocument को DataFormats.XamlPackage के रूप में सहेज सकूं, जो छवियों को बचाता है, लेकिन मुद्दा यह है कि पाठ खोजने योग्य नहीं है। DataFormats.Xaml के साथ, मुझे पाठ्यक्रम का पाठ मिला है, लेकिन कोई छवि नहीं है। छवियों को अंतिम उपयोगकर्ता द्वारा चिपकाया जाएगा, न कि एप्लिकेशन के साथ शामिल छवियों।सी # डब्ल्यूपीएफ कन्वर्ट बिटमैप इमेज समृद्ध टेक्स्टबॉक्स में बाइनरी

मैंने XML में टेक्स्ट प्राप्त करने के लिए XamlWriter का उपयोग करने का प्रयास किया, और उसके बाद दस्तावेज़ से छवियों को अलग से पकड़ लिया और उन्हें 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 का उपयोग करता है। यह मुझे बिटमैप छवि से बाइनरी प्राप्त करने की अनुमति देता है, इसे डेटाबेस में संग्रहीत करता है, और इसे बैक अप लोड करता है और उसे फ़्लो डॉक्यूमेंट में वापस प्रदर्शित करता है। प्रारंभिक परीक्षण सफल साबित हुए हैं। परीक्षण उद्देश्यों के लिए मैं अपने डेटाबेस चरण को छोड़ रहा हूं और मूल रूप से बाइनरी बनाकर छवि को डुप्लिकेट कर रहा हूं, फिर बाइनरी ले रहा हूं और इसे एक नई छवि में बदल रहा हूं और इसे फ़्लो डॉक्यूमेंट में जोड़ रहा हूं। एकमात्र मुद्दा यह है कि जब मैं संशोधित फ़्लो डॉक्यूमेंट को आज़माता हूं और लेता हूं और XamlWriter का उपयोग करता हूं। फ़ंक्शन सहेजें, यह नव निर्मित छवि पर "गैर-सार्वजनिक प्रकार को क्रमबद्ध नहीं कर सकता" सिस्टम के साथ त्रुटियां। Windows.Media.Imaging.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); 
     } 
+0

अधिक उपयुक्त कुछ करने के लिए इस पोस्ट का शीर्षक बदलने के लिए चाहते हो सकता है ... ऐसा लगता है तुम सच में कैसे एक छवि वस्तु के कच्चे बाइट्स लेने के लिए और एक XML दस्तावेज में यह स्टोर करने के लिए पूछ रहे हैं ... –

+0

धन्यवाद , अच्छा लगता है, अगर किसी के पास बाइनरी में पूर्ण प्लस छवियों में टेक्स्ट को सहेजने के समान प्रभाव को प्राप्त करने के बारे में अन्य विचार हैं, तो मुझे संभवतः विशिष्ट होने की कोशिश कर रहा था, लेकिन मुझे नहीं लगता कि यह संभव है – JoeSharp

उत्तर

2

अच्छी खबर है। मुझे थोड़ी देर के लिए कुछ और काम करना पड़ा, लेकिन इसने मुझे आंखों की एक नई जोड़ी के साथ वापस आने की अनुमति दी। मुझे जल्दी से एहसास हुआ कि मैं बस जो जोड़ रहा था उसे जोड़ सकता था। मुझे संदेह है कि यह समाधान किसी भी पुरस्कार जीत जाएगा, लेकिन यह काम करता है। मुझे पता है कि मैं FlamDocument को XamlReader का उपयोग कर टेक्स्ट के रूप में लपेट सकता हूं, छवि तत्वों को रखकर छवि डेटा खो रहा हूं। मुझे यह भी पता था कि मैं XamlFormat का उपयोग करके फ़्लो डॉक्यूमेंट को बाइनरी में बदल सकता हूं। तो मुझे फ़्लो डॉक्यूमेंट लेने का विचार था, और एक फ़ंक्शन का उपयोग करके मैंने छवियों को ढूंढने के लिए इसे पहले से लिखने के लिए लिखा था, मैं प्रत्येक छवि लेता हूं, मूल रूप से इसे क्लोन करता हूं और क्लोन को एक नए फ़्लो डॉक्यूमेंट में डाल देता हूं। मैं उस नए फ्लो डॉक्यूमेंट को लेता हूं जिसमें अब एक ही छवि है, इसे बाइनरी में बदल दें, और फिर परिणामस्वरूप बाइनरी लें, इसे बेस 64 स्ट्रिंग में बदलें और इसे मूल फ़्लो डॉक्यूमेंट में छवि की टैग प्रॉपर्टी में चिपकाएं। यह मूल फ़्लो डॉक्यूमेंट में टेक्स्ट डेटा को टेक्स्ट के रूप में रखता है। इस तरह मैं खोज डेटा प्राप्त करने के लिए XamlReader में छवि डेटा (जिसे मैं SUBString प्रारूप कहता हूं) के साथ फ़्लो डॉक्यूमेंट पास कर सकता हूं।जब यह डेटाबेस से बाहर आता है, तो मैं फ्लैड डॉक्यूमेंट को सामान्य के रूप में एक्सएएम से बाहर खींचता हूं, लेकिन फिर प्रत्येक छवि के माध्यम से फिर से चलाता हूं, XamlFormat का उपयोग करके टैग प्रॉपर्टी से डेटा निकालता हूं, और फिर मेरे वास्तविक स्रोत के लिए स्रोत प्रॉपर्टी प्रदान करने के लिए एक और क्लोन छवि बना रहा हूं छवि। मैंने नीचे SUBString प्रारूप प्राप्त करने के लिए कदम प्रदान किए हैं।

/// <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()); 
     } 
    } 
0

अपनी छवि को मेमोरीस्ट्रीम में सहेजें और उस स्ट्रीम को अपनी एक्सएमएल फ़ाइल में लिखें।

मेमोरी स्ट्रीम इसे बाइट [] में परिवर्तित कर देगा।

+1

उत्तर टोनी के लिए धन्यवाद । समस्या यह है कि छवि एक System.Windows.Controls.Image ऑब्जेक्ट है। मैंने पदानुक्रम को नीचे रखा लेकिन बाइट्स को किस वस्तु पर संग्रहीत किया गया था, उसमें नहीं मिला। मैंने बिटमैप इमेज ऑब्जेक्ट को मेमोरी स्ट्रीम में सहेजने की कोशिश की, लेकिन मुझे वापस मिलना एक्सएमएल टैग है। (मेमोरीस्ट्रीम एमएस = नई मेमोरीस्ट्रीम()) { XamlWriter.Save (bi, ms) का उपयोग कर; परिणाम = ms.ToArray(); } – JoeSharp

+0

परिणाम: <बिटमैप छवि बेसयू = "पैक: // पेलोड:, wpf2,/xaml/document.xaml" UriSource = "./ Image1.bmp" कैशऑशन = "ऑनलोड" xmlns = "http: // schemas .microsoft.com/winfx/2006/xaml/प्रस्तुति "/> – JoeSharp

+0

क्या आप पूरा कोड पोस्ट कर सकते हैं? –

0

यहाँ मेरी सुझाव है कि मैं पहले से ही बना दिया है दोनों के लिए नमूना कोड है, बीमार अगर मेरे उदाहरण न काम पेलोड इस मामले को देखना है ...

 // 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; 
    } 
+1

पहला ऐसा काम नहीं कर रहा है। बेसयूरी "पैक: // पेलोड:, wpf2,/Xaml/Document.xaml" है और UriSource "./Image1.bmp" है। उन्हें "पैक: \ payload:, wpf2, \ Xaml \ ./ Image1.bmp" में मिलाकर परिणाम मिलते हैं। मैंने Image1.bmp पथ में डॉट को हटाने का मिश्रण करने का प्रयास किया। यह भी सुनिश्चित नहीं है कि वह बिंदु कहां इंगित कर रहा है। दूसरा समाधान ऐसा लगता है कि यह काम करना शुरू कर देता है, लेकिन तब जब बाइट सरणी वापस आती है, जब मैं इसे एक्सएमएल में जोड़ने की कोशिश करता हूं, तो मैं इसे एसीआई एन्कोडिंग करने की कोशिश करता हूं और मुझे यह त्रुटि मिलती है: '।', हेक्साडेसिमल मान 0x00 , एक अवैध चरित्र है। (प्रश्न में मेरे GetImagesXML() देखें) – JoeSharp

+0

मैं स्ट्रैड प्रॉपर्टी से बहुत परिचित नहीं हूं। मैं इसे बाइट्स में छवि की चौड़ाई जानता हूं, लेकिन क्या आप उस पंक्ति में गणित को संक्षेप में समझा सकते हैं, "+ 7" कहां से आता है? धन्यवाद – JoeSharp

+1

पॉप-अप करने वाली त्रुटि यह है क्योंकि आप बाइट सरणी को अपने ASCII रूप में परिवर्तित करने के लिए ASCII एन्कोडिंग का उपयोग कर रहे हैं, बाइट सरणी को बेस 64 स्ट्रिंग –

संबंधित मुद्दे