문제

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.save 함수를 사용하면 "비공개 유형 'System.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);
        }
도움이 되었습니까?

해결책

좋은 소식. 나는 잠시 동안 다른 일을해야했지만, 이것은 신선한 눈으로 돌아올 수있게 해주었다. 나는 내가 알고있는 것을 결합 할 수 있다는 것을 빨리 깨달았습니다. 이 솔루션이 상을받을 수 있을지 의심하지만 효과가 있습니다. XamlReader를 사용하여 FlowDocument를 텍스트로 랩핑하여 이미지 요소를 유지하지만 이미지 데이터를 잃을 수 있다는 것을 알고 있습니다. 또한 XamlFormat을 사용하여 FlowDocument를 바이너리로 바꿀 수 있다는 것을 알았습니다. 그래서 나는 flowdocument를 취한다는 아이디어를 가지고 있었고, 이미 이미지를 찾기 위해 반복하기 위해 이미 쓴 함수를 사용하여 각 이미지를 가져 와서 기본적으로 복제하고 복제를 새로운 FlowDocument에 넣었습니다. 이제 단일 이미지가 포함 된 새 FlowDocument를 취하고 바이너리로 바꾸고 결과 바이너리를 가져 와서 Base64 문자열로 바꾸고 원래 FlowDocument에서 이미지의 태그 속성에 붙입니다. 이것은 원래 FlowDocument의 이미지 데이터를 텍스트로 유지합니다. 이렇게하면 이미지 데이터 (하위 문자형 형식을 호출)로 FlowDocument를 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());
        }
    }

다른 팁

이미지를 메모리 스트림에 저장하고 해당 스트림을 XML 파일에 씁니다.

메모리 스트림은 바이트 []로 변환합니다.

다음은 내가 이미 만든 두 가지 제안에 대한 샘플 코드입니다. 예제가 작동하지 않으면 페이로드 문제를 조사해야합니다 ...

        // 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