Error[8]: Undefined offset: 10, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述我有一个从Web服务检索图像的应用程序.在发送到C#客户端之前,Web服务会将一些元数据嵌入图像中. 这是该方法的一部分.它从Response对象中检索Stream,并从流中创建一个Image.请注意,我正在使用System.Drawing.Image,而不是System.Windows.Controls.Image – 这意味着我不能使用任何ImageSource或BitmapSource. S 我有一个从Web服务检索图像的应用程序.在发送到C#客户端之前,Web服务会将一些元数据嵌入图像中.

这是该方法的一部分.它从Response对象中检索Stream,并从流中创建一个Image.请注意,我正在使用System.Drawing.Image,而不是System.Windows.Controls.Image – 这意味着我不能使用任何ImageSource或BitmapSource.

System.Drawing.Image img = null;using (httpWebResponse response = request.GetResponse() as httpWebResponse){    Stream stream = response.GetResponseStream();    img = System.Drawing.Image.FromStream(stream);    .......}return img;

图像看起来完美无缺,但内嵌有元数据.图像是PNG格式,还有一种方法可以从图像中提取信息.共有六块元数据嵌入. PNG格式(PNG块)描述为here.数据保存在“tEXt”块下.

public static Hashtable GetData(Image image){    Hashtable Metadata = null;    data = new Hashtable();    byte[] imageBytes;    using (MemoryStream stream = new MemoryStream())    {        image.Save(stream,image.RawFormat);        imageBytes = new byte[stream.Length];        imageBytes = stream.ToArray();    }    if (imageBytes.Length <= 8)    {        return null;    }    // SkipPing 8 bytes of PNG header    int pointer = 8;    while (pointer < imageBytes.Length)    {        // read the next chunk        uint chunkSize = GetChunkSize(imageBytes,pointer);        pointer += 4;        string chunkname = GetChunkname(imageBytes,pointer);        pointer += 4;        // chunk data -----        if (chunkname.Equals("tEXt"))        {            byte[] data = new byte[chunkSize];            Array.copy(imageBytes,pointer,data,chunkSize);            StringBuilder stringBuilder = new StringBuilder();            foreach (byte t in data)            {                stringBuilder.Append((char)t);            }            string[] pair = stringBuilder.ToString().Split(new char[] { '
request.headers.Add(httpRequestheader.AcceptCharset,"ISO-8859-1");
' }); Metadata[pair[0]] = pair[1]; } pointer += (int)chunkSize + 4; if (pointer > imageBytes.Length) break; } return data;}private static uint GetChunkSize(byte[] bytes,int pos){ byte[] quad = new byte[4]; for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; } return BitConverter.ToUInt32(quad);}private static string GetChunkname(byte[] bytes,int pos){ StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); } return builder.ToString();}

在windows 7中,检测并提取所有六个元数据.所以简而言之,在windows 7环境中,我设法得到我需要的一切.

当我将它移动到windows 10终端(也尝试windows 8)时,事情变得不同.我只能从图像中提取2个元数据.

因为我的GetData()方法将Image转换为byte [],所以我尝试从Web服务流中提取数据.我将流转换为byte [],并使用相同的技术从byte []中提取元数据.我设法使用这种方法获取所有6个元数据.

所以问题是:有什么变化?它在windows 7中工作得很好,但在windows 8和10中不是这样.我仍然可以收回数据,前提是我不将流转换成图像.在此过程中,元数据丢失.当将流转换为图像时,或将图像转换为byte []时,丢失.作为附注,我已经尝试将byte []转换为字符串.来自流的字节[]的字符串表示与图像中的字节[]不同.使用正确的编码器,我可以看到稍后的字节[]中丢失了4个元数据.

解决方法 元数据tEXt:在ISO / IEC 8859-1中表示

在您提出请求之前,请尝试添加以下内容:

System.Drawing.Image img = null; //accept Charset "ISO-8859-1" request.headers.Add(httpRequestheader.AcceptCharset,"ISO-8859-1");using (httpWebResponse response = request.GetResponse() as httpWebResponse){ Stream stream = response.GetResponseStream(); img = System.Drawing.Image.FromStream(stream);  .......} return img;

所以修改你的代码:

[System.Text.EnCoding]::Default.EnCodingname

只是为了信息,你可以发布windows 7/8/10中的windows EnCodingname是什么

使用powershell命令知道:

// [Obsolete("Use Image.FromStream(stream,useEmbeddedcolorManagement)")]    public static Image FromStream(Stream stream) {         return Image.FromStream(stream,false);    }

编辑:

我查看了DOTNet System.Drawing.Image.FromStream的源代码
并发现声明:

Image.FromStream(stream,true);   or Image.FromStream(stream,true,true);

尝试使用:

public static Image FromStream(  Stream stream,bool useEmbeddedcolorManagement,////true to use color management  information embedded in the data stream; otherwise,false.   bool valIDateImageData //true to valIDate the image data; otherwise,false.  )

有关参数的详细信息:

The file size: 502,888 byte (real size on disk).      win 7         win10        function used 569674        597298      Image.FromStream(stream,true) 597343        597298      Image.FromStream(stream,false)

Image.FromStream Method

编辑2:

我用TEXT数据对PNG图像文件进行了实验:

我开发了一个函数来测量图像的大小(以字节为单位),这是通过函数FromStream()读取的,我在win7 / win10上执行.

下表显示了两个环境中图像的实际大小(以字节为单位):

class MetaReader {    public static Hashtable GetData(string fname)    {        using (fileStream image = new fileStream(fname,fileMode.Open,fileAccess.Read))        {            Hashtable Metadata = new Hashtable();            byte[] imageBytes;            using (var memoryStream = new MemoryStream())            {                image.copyTo(memoryStream);                imageBytes = memoryStream.ToArray();                Console.Writeline(imageBytes.Length);            }            if (imageBytes.Length <= 8)            {                return null;            }            // SkipPing 8 bytes of PNG header            int pointer = 8;            while (pointer < imageBytes.Length)            {                // read the next chunk                uint chunkSize = GetChunkSize(imageBytes,pointer);                pointer += 4;                string chunkname = GetChunkname(imageBytes,pointer);                pointer += 4;                // chunk data -----                if (chunkname.Equals("tEXt"))                {                    byte[] data = new byte[chunkSize];                    Array.copy(imageBytes,chunkSize);                    StringBuilder stringBuilder = new StringBuilder();                    foreach (byte t in data)                    {                        stringBuilder.Append((char)t);                    }                    string[] pair = stringBuilder.ToString().Split(new char[] { '[+++]' });                    Metadata[pair[0]] = pair[1];                    Console.Writeline(Metadata[pair[0]]);                }                pointer += (int)chunkSize + 4;                if (pointer > imageBytes.Length)                    break;            }            return Metadata;        }    }    private static uint GetChunkSize(byte[] bytes,int pos)    {        byte[] quad = new byte[4];        for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; }        return BitConverter.ToUInt32(quad,0);    }    private static string GetChunkname(byte[] bytes,int pos)    {        StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); }        return builder.ToString();    }}

你发现两个环境的大小是不同的,不同于
磁盘中的实际大小.

所以,您期望元数据的位置已更改(但不会丢失,仅重新分配)

我使用十六进制编辑器工具来查看tTEXT块.

tEXT位于第66位(十进制),从文件开始,两者都是一样的!

我使用我自己的元数据读取器功能,结果对于windows 7或windows 10(没有数据丢失)是相同和有效的.

PNG格式的官方网站是:https://www.w3.org/TR/PNG/

结论

Image.FromStream函数不适合读取元数据,图像文件应以原始字节格式读取,而不是以图像格式读取,因为FromStream函数会将原始数据重新分配,以保持图像及其数据不变形(即内部函数在dotnet中).

要按照PNG规范的描述读取元数据,您应该按照规范从描述文件开始读取RAW BYTES中的流.

我建议您使用类库MetadataExtractor来读取元数据,其结果在windows 7和windows 10中都非常准确

您可以从nuget安装库.
install-Package MetadataExtractor

编辑3:建议的解决方案

现在问题解决了,下面的类对win 7,win 8都有效

主要的变化是将图像文件读为原始字节

[+++]

从Web服务读取元数据:

您可以从url加载图像文件作为流,并且即时读取元数据.
此外,您可以创建System.Drawing.Image的实例,并对图像进行处理.
您可以在以下位置找到源代码的完整演示:

Reading Metadata from PNG loaded from Web Stream -TryIt

总结

以上是内存溢出为你收集整理的C#Image.FromStream():在Windows 8/10中运行时丢失元数据全部内容,希望文章能够帮你解决C#Image.FromStream():在Windows 8/10中运行时丢失元数据所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 11, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述我有一个从Web服务检索图像的应用程序.在发送到C#客户端之前,Web服务会将一些元数据嵌入图像中. 这是该方法的一部分.它从Response对象中检索Stream,并从流中创建一个Image.请注意,我正在使用System.Drawing.Image,而不是System.Windows.Controls.Image – 这意味着我不能使用任何ImageSource或BitmapSource. S 我有一个从Web服务检索图像的应用程序.在发送到C#客户端之前,Web服务会将一些元数据嵌入图像中.

这是该方法的一部分.它从Response对象中检索Stream,并从流中创建一个Image.请注意,我正在使用System.Drawing.Image,而不是System.Windows.Controls.Image – 这意味着我不能使用任何ImageSource或BitmapSource.

System.Drawing.Image img = null;using (httpWebResponse response = request.GetResponse() as httpWebResponse){    Stream stream = response.GetResponseStream();    img = System.Drawing.Image.FromStream(stream);    .......}return img;

图像看起来完美无缺,但内嵌有元数据.图像是PNG格式,还有一种方法可以从图像中提取信息.共有六块元数据嵌入. PNG格式(PNG块)描述为here.数据保存在“tEXt”块下.

public static Hashtable GetData(Image image){    Hashtable Metadata = null;    data = new Hashtable();    byte[] imageBytes;    using (MemoryStream stream = new MemoryStream())    {        image.Save(stream,image.RawFormat);        imageBytes = new byte[stream.Length];        imageBytes = stream.ToArray();    }    if (imageBytes.Length <= 8)    {        return null;    }    // SkipPing 8 bytes of PNG header    int pointer = 8;    while (pointer < imageBytes.Length)    {        // read the next chunk        uint chunkSize = GetChunkSize(imageBytes,pointer);        pointer += 4;        string chunkname = GetChunkname(imageBytes,pointer);        pointer += 4;        // chunk data -----        if (chunkname.Equals("tEXt"))        {            byte[] data = new byte[chunkSize];            Array.copy(imageBytes,pointer,data,chunkSize);            StringBuilder stringBuilder = new StringBuilder();            foreach (byte t in data)            {                stringBuilder.Append((char)t);            }            string[] pair = stringBuilder.ToString().Split(new char[] { '
request.headers.Add(httpRequestheader.AcceptCharset,"ISO-8859-1");
' }); Metadata[pair[0]] = pair[1]; } pointer += (int)chunkSize + 4; if (pointer > imageBytes.Length) break; } return data;}private static uint GetChunkSize(byte[] bytes,int pos){ byte[] quad = new byte[4]; for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; } return BitConverter.ToUInt32(quad);}private static string GetChunkname(byte[] bytes,int pos){ StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); } return builder.ToString();}

在windows 7中,检测并提取所有六个元数据.所以简而言之,在windows 7环境中,我设法得到我需要的一切.

当我将它移动到windows 10终端(也尝试windows 8)时,事情变得不同.我只能从图像中提取2个元数据.

因为我的GetData()方法将Image转换为byte [],所以我尝试从Web服务流中提取数据.我将流转换为byte [],并使用相同的技术从byte []中提取元数据.我设法使用这种方法获取所有6个元数据.

所以问题是:有什么变化?它在windows 7中工作得很好,但在windows 8和10中不是这样.我仍然可以收回数据,前提是我不将流转换成图像.在此过程中,元数据丢失.当将流转换为图像时,或将图像转换为byte []时,丢失.作为附注,我已经尝试将byte []转换为字符串.来自流的字节[]的字符串表示与图像中的字节[]不同.使用正确的编码器,我可以看到稍后的字节[]中丢失了4个元数据.

解决方法 元数据tEXt:在ISO / IEC 8859-1中表示

在您提出请求之前,请尝试添加以下内容:

System.Drawing.Image img = null; //accept Charset "ISO-8859-1" request.headers.Add(httpRequestheader.AcceptCharset,"ISO-8859-1");using (httpWebResponse response = request.GetResponse() as httpWebResponse){ Stream stream = response.GetResponseStream(); img = System.Drawing.Image.FromStream(stream);  .......} return img;

所以修改你的代码:

[System.Text.EnCoding]::Default.EnCodingname

只是为了信息,你可以发布windows 7/8/10中的windows EnCodingname是什么

使用powershell命令知道:

// [Obsolete("Use Image.FromStream(stream,useEmbeddedcolorManagement)")]    public static Image FromStream(Stream stream) {         return Image.FromStream(stream,false);    }

编辑:

我查看了DOTNet System.Drawing.Image.FromStream的源代码
并发现声明:

Image.FromStream(stream,true);   or Image.FromStream(stream,true,true);

尝试使用:

public static Image FromStream(  Stream stream,bool useEmbeddedcolorManagement,////true to use color management  information embedded in the data stream; otherwise,false.   bool valIDateImageData //true to valIDate the image data; otherwise,false.  )

有关参数的详细信息:

The file size: 502,888 byte (real size on disk).      win 7         win10        function used 569674        597298      Image.FromStream(stream,true) 597343        597298      Image.FromStream(stream,false)

Image.FromStream Method

编辑2:

我用TEXT数据对PNG图像文件进行了实验:

我开发了一个函数来测量图像的大小(以字节为单位),这是通过函数FromStream()读取的,我在win7 / win10上执行.

下表显示了两个环境中图像的实际大小(以字节为单位):

class MetaReader {    public static Hashtable GetData(string fname)    {        using (fileStream image = new fileStream(fname,fileMode.Open,fileAccess.Read))        {            Hashtable Metadata = new Hashtable();            byte[] imageBytes;            using (var memoryStream = new MemoryStream())            {                image.copyTo(memoryStream);                imageBytes = memoryStream.ToArray();                Console.Writeline(imageBytes.Length);            }            if (imageBytes.Length <= 8)            {                return null;            }            // SkipPing 8 bytes of PNG header            int pointer = 8;            while (pointer < imageBytes.Length)            {                // read the next chunk                uint chunkSize = GetChunkSize(imageBytes,pointer);                pointer += 4;                string chunkname = GetChunkname(imageBytes,pointer);                pointer += 4;                // chunk data -----                if (chunkname.Equals("tEXt"))                {                    byte[] data = new byte[chunkSize];                    Array.copy(imageBytes,chunkSize);                    StringBuilder stringBuilder = new StringBuilder();                    foreach (byte t in data)                    {                        stringBuilder.Append((char)t);                    }                    string[] pair = stringBuilder.ToString().Split(new char[] { '' });                    Metadata[pair[0]] = pair[1];                    Console.Writeline(Metadata[pair[0]]);                }                pointer += (int)chunkSize + 4;                if (pointer > imageBytes.Length)                    break;            }            return Metadata;        }    }    private static uint GetChunkSize(byte[] bytes,int pos)    {        byte[] quad = new byte[4];        for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; }        return BitConverter.ToUInt32(quad,0);    }    private static string GetChunkname(byte[] bytes,int pos)    {        StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); }        return builder.ToString();    }}

你发现两个环境的大小是不同的,不同于
磁盘中的实际大小.

所以,您期望元数据的位置已更改(但不会丢失,仅重新分配)

我使用十六进制编辑器工具来查看tTEXT块.

tEXT位于第66位(十进制),从文件开始,两者都是一样的!

我使用我自己的元数据读取器功能,结果对于windows 7或windows 10(没有数据丢失)是相同和有效的.

PNG格式的官方网站是:https://www.w3.org/TR/PNG/

结论

Image.FromStream函数不适合读取元数据,图像文件应以原始字节格式读取,而不是以图像格式读取,因为FromStream函数会将原始数据重新分配,以保持图像及其数据不变形(即内部函数在dotnet中).

要按照PNG规范的描述读取元数据,您应该按照规范从描述文件开始读取RAW BYTES中的流.

我建议您使用类库MetadataExtractor来读取元数据,其结果在windows 7和windows 10中都非常准确

您可以从nuget安装库.
install-Package MetadataExtractor

编辑3:建议的解决方案

现在问题解决了,下面的类对win 7,win 8都有效

主要的变化是将图像文件读为原始字节

[+++]

从Web服务读取元数据:

您可以从url加载图像文件作为流,并且即时读取元数据.
此外,您可以创建System.Drawing.Image的实例,并对图像进行处理.
您可以在以下位置找到源代码的完整演示:

Reading Metadata from PNG loaded from Web Stream -TryIt

总结

以上是内存溢出为你收集整理的C#Image.FromStream():在Windows 8/10中运行时丢失元数据全部内容,希望文章能够帮你解决C#Image.FromStream():在Windows 8/10中运行时丢失元数据所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
C#Image.FromStream():在Windows 810中运行时丢失元数据_C_内存溢出

C#Image.FromStream():在Windows 810中运行时丢失元数据

C#Image.FromStream():在Windows 810中运行时丢失元数据,第1张

概述我有一个从Web服务检索图像的应用程序.在发送到C#客户端之前,Web服务会将一些元数据嵌入图像中. 这是该方法的一部分.它从Response对象中检索Stream,并从流中创建一个Image.请注意,我正在使用System.Drawing.Image,而不是System.Windows.Controls.Image – 这意味着我不能使用任何ImageSource或BitmapSource. S 我有一个从Web服务检索图像的应用程序.在发送到C#客户端之前,Web服务会将一些元数据嵌入图像中.

这是该方法的一部分.它从Response对象中检索Stream,并从流中创建一个Image.请注意,我正在使用System.Drawing.Image,而不是System.Windows.Controls.Image – 这意味着我不能使用任何ImageSource或BitmapSource.

System.Drawing.Image img = null;using (httpWebResponse response = request.GetResponse() as httpWebResponse){    Stream stream = response.GetResponseStream();    img = System.Drawing.Image.FromStream(stream);    .......}return img;

图像看起来完美无缺,但内嵌有元数据.图像是PNG格式,还有一种方法可以从图像中提取信息.共有六块元数据嵌入. PNG格式(PNG块)描述为here.数据保存在“tEXt”块下.

public static Hashtable GetData(Image image){    Hashtable Metadata = null;    data = new Hashtable();    byte[] imageBytes;    using (MemoryStream stream = new MemoryStream())    {        image.Save(stream,image.RawFormat);        imageBytes = new byte[stream.Length];        imageBytes = stream.ToArray();    }    if (imageBytes.Length <= 8)    {        return null;    }    // SkipPing 8 bytes of PNG header    int pointer = 8;    while (pointer < imageBytes.Length)    {        // read the next chunk        uint chunkSize = GetChunkSize(imageBytes,pointer);        pointer += 4;        string chunkname = GetChunkname(imageBytes,pointer);        pointer += 4;        // chunk data -----        if (chunkname.Equals("tEXt"))        {            byte[] data = new byte[chunkSize];            Array.copy(imageBytes,pointer,data,chunkSize);            StringBuilder stringBuilder = new StringBuilder();            foreach (byte t in data)            {                stringBuilder.Append((char)t);            }            string[] pair = stringBuilder.ToString().Split(new char[] { '
request.headers.Add(httpRequestheader.AcceptCharset,"ISO-8859-1");
' }); Metadata[pair[0]] = pair[1]; } pointer += (int)chunkSize + 4; if (pointer > imageBytes.Length) break; } return data;}private static uint GetChunkSize(byte[] bytes,int pos){ byte[] quad = new byte[4]; for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; } return BitConverter.ToUInt32(quad);}private static string GetChunkname(byte[] bytes,int pos){ StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); } return builder.ToString();}

在windows 7中,检测并提取所有六个元数据.所以简而言之,在windows 7环境中,我设法得到我需要的一切.

当我将它移动到windows 10终端(也尝试windows 8)时,事情变得不同.我只能从图像中提取2个元数据.

因为我的GetData()方法将Image转换为byte [],所以我尝试从Web服务流中提取数据.我将流转换为byte [],并使用相同的技术从byte []中提取元数据.我设法使用这种方法获取所有6个元数据.

所以问题是:有什么变化?它在windows 7中工作得很好,但在windows 8和10中不是这样.我仍然可以收回数据,前提是我不将流转换成图像.在此过程中,元数据丢失.当将流转换为图像时,或将图像转换为byte []时,丢失.作为附注,我已经尝试将byte []转换为字符串.来自流的字节[]的字符串表示与图像中的字节[]不同.使用正确的编码器,我可以看到稍后的字节[]中丢失了4个元数据.

解决方法 元数据tEXt:在ISO / IEC 8859-1中表示

在您提出请求之前,请尝试添加以下内容:

System.Drawing.Image img = null; //accept Charset "ISO-8859-1" request.headers.Add(httpRequestheader.AcceptCharset,"ISO-8859-1");using (httpWebResponse response = request.GetResponse() as httpWebResponse){ Stream stream = response.GetResponseStream(); img = System.Drawing.Image.FromStream(stream);  .......} return img;

所以修改你的代码:

[System.Text.EnCoding]::Default.EnCodingname

只是为了信息,你可以发布windows 7/8/10中的windows EnCodingname是什么

使用powershell命令知道:

// [Obsolete("Use Image.FromStream(stream,useEmbeddedcolorManagement)")]    public static Image FromStream(Stream stream) {         return Image.FromStream(stream,false);    }

编辑:

我查看了DOTNet System.Drawing.Image.FromStream的源代码
并发现声明:

Image.FromStream(stream,true);   or Image.FromStream(stream,true,true);

尝试使用:

public static Image FromStream(  Stream stream,bool useEmbeddedcolorManagement,////true to use color management  information embedded in the data stream; otherwise,false.   bool valIDateImageData //true to valIDate the image data; otherwise,false.  )

有关参数的详细信息:

The file size: 502,888 byte (real size on disk).      win 7         win10        function used 569674        597298      Image.FromStream(stream,true) 597343        597298      Image.FromStream(stream,false)

Image.FromStream Method

编辑2:

我用TEXT数据对PNG图像文件进行了实验:

我开发了一个函数来测量图像的大小(以字节为单位),这是通过函数FromStream()读取的,我在win7 / win10上执行.

下表显示了两个环境中图像的实际大小(以字节为单位):

class MetaReader {    public static Hashtable GetData(string fname)    {        using (fileStream image = new fileStream(fname,fileMode.Open,fileAccess.Read))        {            Hashtable Metadata = new Hashtable();            byte[] imageBytes;            using (var memoryStream = new MemoryStream())            {                image.copyTo(memoryStream);                imageBytes = memoryStream.ToArray();                Console.Writeline(imageBytes.Length);            }            if (imageBytes.Length <= 8)            {                return null;            }            // SkipPing 8 bytes of PNG header            int pointer = 8;            while (pointer < imageBytes.Length)            {                // read the next chunk                uint chunkSize = GetChunkSize(imageBytes,pointer);                pointer += 4;                string chunkname = GetChunkname(imageBytes,pointer);                pointer += 4;                // chunk data -----                if (chunkname.Equals("tEXt"))                {                    byte[] data = new byte[chunkSize];                    Array.copy(imageBytes,chunkSize);                    StringBuilder stringBuilder = new StringBuilder();                    foreach (byte t in data)                    {                        stringBuilder.Append((char)t);                    }                    string[] pair = stringBuilder.ToString().Split(new char[] { '' });                    Metadata[pair[0]] = pair[1];                    Console.Writeline(Metadata[pair[0]]);                }                pointer += (int)chunkSize + 4;                if (pointer > imageBytes.Length)                    break;            }            return Metadata;        }    }    private static uint GetChunkSize(byte[] bytes,int pos)    {        byte[] quad = new byte[4];        for (int i = 0; i < 4; i++) { quad[3 - i] = bytes[pos + i]; }        return BitConverter.ToUInt32(quad,0);    }    private static string GetChunkname(byte[] bytes,int pos)    {        StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { builder.Append((char)bytes[pos + i]); }        return builder.ToString();    }}

你发现两个环境的大小是不同的,不同于
磁盘中的实际大小.

所以,您期望元数据的位置已更改(但不会丢失,仅重新分配)

我使用十六进制编辑器工具来查看tTEXT块.

tEXT位于第66位(十进制),从文件开始,两者都是一样的!

我使用我自己的元数据读取器功能,结果对于windows 7或windows 10(没有数据丢失)是相同和有效的.

PNG格式的官方网站是:https://www.w3.org/TR/PNG/

结论

Image.FromStream函数不适合读取元数据,图像文件应以原始字节格式读取,而不是以图像格式读取,因为FromStream函数会将原始数据重新分配,以保持图像及其数据不变形(即内部函数在dotnet中).

要按照PNG规范的描述读取元数据,您应该按照规范从描述文件开始读取RAW BYTES中的流.

我建议您使用类库MetadataExtractor来读取元数据,其结果在windows 7和windows 10中都非常准确

您可以从nuget安装库.
install-Package MetadataExtractor

编辑3:建议的解决方案

现在问题解决了,下面的类对win 7,win 8都有效

主要的变化是将图像文件读为原始字节

从Web服务读取元数据:

您可以从url加载图像文件作为流,并且即时读取元数据.
此外,您可以创建System.Drawing.Image的实例,并对图像进行处理.
您可以在以下位置找到源代码的完整演示:

Reading Metadata from PNG loaded from Web Stream -TryIt

总结

以上是内存溢出为你收集整理的C#Image.FromStream():在Windows 8/10中运行时丢失元数据全部内容,希望文章能够帮你解决C#Image.FromStream():在Windows 8/10中运行时丢失元数据所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1253042.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存