我正在尝试在 vs2013 中使用 libpng 1.2.10 读取一个 png 文件。我下载了最新的 zlib 并编译了 pnglib,效果很好。现在我正在尝试加载一个文件:
int *w = &width;
int *h = &height;
const char* name = file.c_str();
FILE *png_file = fopen(name, "rb");
if (!png_file)
{
std::cerr << "Could not open " + file << std::endl;
return;
}
unsigned char header[PNG_SIG_BYTES];
fread(header, 1, PNG_SIG_BYTES, png_file);
if (png_sig_cmp(header, 0, PNG_SIG_BYTES))
{
std::cerr << "PNG signature fail " + file << std::endl;
return;
}
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL)
{
std::cerr << "PNG read fail " + file << std::endl;
return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if(!info_ptr)
{
std::cerr << "PNG info fail " + file << std::endl;
return;
}
png_infop end_info = png_create_info_struct(png_ptr);
if(!end_info)
{
std::cerr << "PNG info end fail " + file << std::endl;
return;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
std::cerr << "PNG setjmp fail " + file << std::endl;
return;
}
png_init_io(png_ptr, png_file);
png_set_sig_bytes(png_ptr, PNG_SIG_BYTES);
png_read_info(png_ptr, info_ptr);
*w = png_get_image_width(png_ptr, info_ptr);
*h = png_get_image_height(png_ptr, info_ptr);
png_uint_32 bit_depth, color_type;
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
{
std::cerr << "Grayscale PNG not supported " + file << std::endl;
return;
}
if (bit_depth == 16)
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
else if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
png_set_gray_to_rgb(png_ptr);
}
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
else
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
png_read_update_info(png_ptr, info_ptr);
png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
png_uint_32 numbytes = rowbytes*(height);
png_byte* pixels = (png_byte*)malloc(numbytes);
png_byte** row_ptrs = (png_byte**)malloc((height)* sizeof(png_byte*));
int i;
for (i = 0; i<height; i++)
row_ptrs[i] = pixels + (height - 1 - i)*rowbytes;
png_read_image(png_ptr, row_ptrs);
free(row_ptrs);
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(png_file);
//return (char *)pixels;
Create(*w, *h, 4, pixels, GL_UNSIGNED_BYTE);
不幸的是我得到了
Unhandled exception at 0x77D78E19 (ntdll.dll) in SimpleShader.exe: 0xC0000005: Access violation writing location 0x00000014.
在线
png_read_info(png_ptr, info_ptr);
具体错误发生在这里:
#ifdef PNG_STDIO_SUPPORTED
/* This is the function that does the actual reading of data. If you are
* not reading from a standard C stream, you should create a replacement
* read_data function and use it at run time with png_set_read_fn(), rather
* than changing the library.
*/
void PNGCBAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
png_size_t check;
if (png_ptr == NULL)
return;
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
* instead of an int, which is what fread() actually returns.
*/
check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); // <---------- ERROR HERE
if (check != length)
png_error(png_ptr, "Read Error");
}
#endif
可能是什么问题?
编辑:好的,当我在 Release模式下编译 libpng 和我的项目时它不会崩溃。我需要在 Debug模式下运行我的项目...
最佳答案
这是由于 libpng 和您的项目之间的编译器设置不匹配造成的。特别是 Runtime Library 设置,在 libpng 和您的项目中都必须是 Multi-threaded DLL (/MD)。自述文件指出:
If you don't use the Visual Studio defaults your application must still be built with the default runtime option (/MD). If, for some reason, it is not then your application will crash inside libpng16.dll as soon as libpng tries to read from a file handle you pass in.
避免崩溃和保留调试可能性的最简单方法是复制项目中的“发布”配置并更改一些属性,以便您可以在 Visual Studio 中轻松调试。方法如下:
就是这样,祝你好运!
关于c++ - libpng 在 png_read_info() 上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22774265/
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少
CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我在我正在处理的一些代码中发现了这一点。它旨在解决从磁盘读取key文件的要求。在生产环境中,key文件的内容位于环境变量中。旧代码:key=File.read('path/to/key.pem')新代码:key=File.read('|echo$KEY_VARIABLE')这是如何工作的? 最佳答案 来自IOdocs:Astringstartingwith“|”indicatesasubprocess.Theremainderofthestringfollowingthe“|”isinvokedasaprocesswithappro
我有这个代码File.open(file_name,'r'){|file|file.read}但是Rubocop发出警告:Offenses:Style/SymbolProc:Pass&:readasargumenttoopeninsteadofablock.你是怎么做到的? 最佳答案 我刚刚创建了一个名为“t.txt”的文件,其中包含“Hello,World\n”。我们可以按如下方式阅读。File.open('t.txt','r',&:read)#=>"Hello,World\n"顺便说一下,由于第二个参数的默认值是'r',所以这样
-if!request.path_info.include?'A'%{:id=>'A'}"Text"-else"Text"“文本”写了两次。我怎样才能只写一次并同时检查path_info是否包含“A”? 最佳答案 有两种方法可以做到这一点。使用部分,或使用content_forblock:如果“文本”较长,或者是一个重要的子树,您可以将其提取到一个部分。这会使您的代码变干一点。在给出的示例中,这似乎有点矫枉过正。在这种情况下更好的方法是使用content_forblock,如下所示:-if!request.path_info.inc
我有以下代码,它下载一个文件,然后将文件的内容读入一个变量。使用该变量,它执行一个命令。这个配方不会收敛,因为/root/foo在编译阶段不存在。我可以通过多个聚合和一个来解决这个问题ifFile.exist但我想用一个收敛来完成它。关于如何做到这一点有什么想法吗?execute'download_joiner'docommand"awss3cps3://bucket/foo/root/foo"not_if{::File.exist?('/root/foo')}endpassword=::File.read('/root/foo').chompexecute'join_domain'd