高级 Win32 图像文件 I/O?

2024-05-22

我想在 Windows C++ 应用程序中将图像文件读入内存。什么是一个相当简单的解决方案,也许类似于 IOS 提供的UIImage?

我希望支持合理数量的文件格式。

我需要为图像处理的位图提供一些低级访问权限。

我在互联网上阅读了很多内容,看起来 Windows DIB 可能是一个合理的内存表示。除此之外,我找不到示例代码来将 JPEG 或 PNG 读取到内存中的 DIB 中。

感谢您的任何建议。


我刚刚检查过LoadImage http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045%28v=vs.85%29.aspx确实支持通过标志从文件加载LR_LOADFROMFILE.

所以这将是我的第一选择。

次要选择,GDI+(请注意,它需要大量摆弄初始化内容才能获得普通的良好质量,并且至少几年前它仍然依赖于min and max macros from <windows.h>)。第三个选择,Windows 映像组件 http://msdn.microsoft.com/en-us/library/windows/desktop/ee719654%28v=vs.85%29.aspx在对该问题的评论中提到。第四个选择,OleLoadPicturePath http://msdn.microsoft.com/en-us/library/windows/desktop/ms678485%28v=vs.85%29.aspx和家人。


Addendum: 正如评论中所指出的LoadImage仅限于加载图像文件的“位图”。在我的系统上,下面的测试程序报告 .bmp 文件加载正常,但 .gif、.png 和 .jpg 文件加载失败。

#undef UNICODE
#define UNICODE
#include <windows.h>

#include <assert.h>         // assert
#include <iostream>         // std::wcout
#include <string>           // std::wstring
using namespace std;

auto get_exe_path()
    -> wstring
{
    int const buffer_size = MAX_PATH;
    wstring result( buffer_size, L'#' );
    int const n_characters = GetModuleFileName( 0, &result[0], buffer_size );
    assert( 0 < n_characters && n_characters < buffer_size );
    result.resize( n_characters );
    return result;
}

auto get_exe_folder_path()
    -> wstring
{
    wstring const exe_path = get_exe_path();
    int const i = exe_path.rfind( L'\\' );
    return exe_path.substr( 0, i + 1 );
}

void test( wstring const& image_name )
{
    wstring const image_file_name = get_exe_folder_path() + image_name;
    wcout << image_file_name << endl;
    HANDLE const image = ::LoadImage(
        0,              // HINSTANCE hinst,
        image_file_name.c_str(),
        IMAGE_BITMAP,
        0, 0,   // int cxDesired, int cyDesired,
        LR_LOADFROMFILE
        );
    wcout << image << endl;
    DeleteObject( image );
}

auto main()
    -> int
{
    test( L"test.bmp" );  wcout << endl;
    test( L"test.png" );  wcout << endl;
    test( L"test.gif" );  wcout << endl;
    test( L"test.jpg" );
}

附录2:为了检查一下,我还测试了 Windows 成像组件功能,它确实可以处理上述所有四种图像类型。下面代码的大部分大小是由于对 COM 的可重用一次写入支持(我只是再次从头开始编写它,所以它有点粗略,只是这里需要的)。不过,此代码不会显示图像或对其执行任何其他操作,而 WIC 也同样复杂......

虽然这段代码有部分 g++ 支持,但我已经用 g++ 对其进行了测试。我记得 g++ 仅支持 Windows API,就像 Windows XP 一样。我不确定 WIC 何时引入(尽管它可以与 Windows XP 一起使用)。

#undef UNICODE
#define UNICODE
#include <windows.h>
#include <wincodec.h>       // IWICImagingFactory

#include <algorithm>        // std::swap
#include <assert.h>         // assert
#include <iostream>         // std::wcout
#include <stdlib.h>         // EXIT_FAILURE, EXIT_SUCCESS
#include <string>           // std::string, std::wstring
#include <utility>          // std::move

#ifndef CPPX_NOEXCEPT
#   if defined( _MSC_VER )
#       define CPPX_NOEXCEPT   throw()
#   else
#       define  CPPX_NOEXCEPT   noexcept
#   endif
#endif

#ifndef CPPX_NORETURN
#   if defined( _MSC_VER )
#       define CPPX_NORETURN   __declspec( noreturn )
#       pragma warning( disable: 4646 )     // "has non-void return type"
#   elif defined( __GNUC__ )
#       define CPPX_NORETURN    __attribute__((noreturn))
#   else
#       define CPPX_NORETURN    [[noreturn]]
#   endif
#endif

namespace cppx {
    using std::string;
    using std::runtime_error;

    auto hopefully( bool const condition )
        CPPX_NOEXCEPT
        -> bool
    { return condition; }

    CPPX_NORETURN
    auto fail( string const& s )
        -> bool
    { throw runtime_error( s ); }
}  // namespace cppx

namespace process {
    using std::wstring;

    auto get_exe_path()
        -> wstring
    {
        int const buffer_size = MAX_PATH;
        wstring result( buffer_size, L'#' );
        int const n_characters = GetModuleFileName( 0, &result[0], buffer_size );
        assert( 0 < n_characters && n_characters < buffer_size );
        result.resize( n_characters );
        return result;
    }

    auto get_exe_folder_path()
        -> wstring
    {
        wstring const exe_path = get_exe_path();
        int const i = exe_path.rfind( L'\\' );
        return exe_path.substr( 0, i + 1 );
    }
}  // namespace process

namespace com {
    using cppx::fail;
    using std::move;

    enum Success { success };

    auto operator>>( HRESULT const hr, Success )
        -> bool
    { return SUCCEEDED( hr ); }

    struct Library
    {
        ~Library()
        { CoUninitialize(); }

        Library()
        { CoInitialize( nullptr ); }
    };

    template< class Interface >
    class Ptr
    {
    private:
        Interface*  p_;

    public:
        auto raw() -> Interface* { return p_; }
        auto operator->() -> Interface* { return p_; }

        void clear() { Ptr null; swap( *this, null ); }

        auto as_value_receiver()
            -> Interface**
        {
            clear();
            return &p_;
        }

        auto as_untyped_value_receiver()
            -> void**
        { return reinterpret_cast<void**>( as_value_receiver() ); }

        friend void swap( Ptr& a, Ptr& b )
            CPPX_NOEXCEPT
        { std::swap( a.p_, b.p_ ); }

        void operator=( Ptr other )
        { swap( *this, other ); }

        void operator=( Ptr&& other )
        {
            Ptr temp( move( other ) );
            swap( temp, *this );
        }

        ~Ptr()
        { if( p_ != nullptr ) { p_->Release(); } }

        explicit Ptr( Interface* p = nullptr )
            CPPX_NOEXCEPT
            : p_( p )
        {}

        Ptr( Ptr const& other )
            : p_( other.p_ )
        { if( p != nullptr ) { p_->AddRef(); } }

        Ptr( Ptr&& other )
            CPPX_NOEXCEPT
            : p_( other.p_ )
        { other.p_ = nullptr; }

        static
        auto create_local( CLSID const& class_id )
            -> Ptr<Interface>
        {
            Ptr<Interface>  result;
            ::CoCreateInstance(
                class_id, nullptr, CLSCTX_INPROC_SERVER,
                __uuidof( Interface ),
                result.as_untyped_value_receiver()
                )
                >> success
                || fail( "CoCreateInstance" );
            return move( result );
        }
    };

}  // namespace com

namespace app {
    using cppx::fail;
    using std::wstring;
    using std::wcout; using std::endl;

    void test( wstring const& image_name )
    {
        wstring const image_file_name =
            process::get_exe_folder_path() + image_name;
        wcout << image_file_name << endl;

        auto                            p_factory   =
            com::Ptr<IWICImagingFactory>::create_local( CLSID_WICImagingFactory );

        com::Ptr< IWICBitmapDecoder>    p_decoder;
        p_factory->CreateDecoderFromFilename(
            image_file_name.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnDemand, // Cache metadata when needed
            p_decoder.as_value_receiver()
            )
            >> com::success
            || fail( "IWICImagingFactory::CreateDecoderFromFilename" );

        com::Ptr<IWICBitmapFrameDecode> p_frame;
        p_decoder->GetFrame( 0, p_frame.as_value_receiver() )
            >> com::success
            || fail( "IWICBitmapFrameDecode::GetFrame");

        UINT w, h;
        p_frame->GetSize( &w, &h )
            >> com::success
            || fail( "IWICBitmapFrameDecode::GetSize" );

        wcout << "(w, h) = (" << w << ", " << h << ")" << endl;
    }

    void cpp_main()
    {
        com::Library const  com_usage;

        test( L"test.bmp" );  wcout << endl;
        test( L"test.png" );  wcout << endl;
        test( L"test.gif" );  wcout << endl;
        test( L"test.jpg" );  wcout << endl;
        test( L"test.bogus" );
    }
}  // namespace app

auto main()
    -> int
{
    using namespace std;
    try
    {
        app::cpp_main();
        return EXIT_SUCCESS;
    }
    catch( exception const& x )
    {
        wcout << "!" << x.what() << endl;
    }
    return EXIT_FAILURE;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高级 Win32 图像文件 I/O? 的相关文章

  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 在 Windows 上不使用 OpenSSL 从 pfx 文件或证书存储中提取私钥

    正如标题所示 我想在不使用 OpenSSL 或任何其他第三方工具的情况下导出我的私钥 如果我需要一个 cer文件或 pfx我可以通过 MMC 或 PowerShell 轻松导出这些文件pkiclient但我找不到获取私钥的方法 https
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • 如何从Windows阻止社交媒体[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我想根据时间阻止我的电脑上的社交媒体 晚上 9 点后屏蔽 上午 11 点后解锁 如家长控制 我尝试过关注但失败了 创建了
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐