Elysia Tools

在一个清晰的工作台里浏览工具、案例、可视化和主题指南。

热门分类

专题

语言
ZHDERUPTENFRES

Elysia Tools

导航

C++

Windows C++ 图像处理示例

Windows C++ 图像处理示例,包括读取/保存图像、调整大小和使用Windows Imaging Component进行格式转换

案例

这个案例集合中的条目

代码cpp中等

图像读取和保存

使用Windows Imaging Component从文件加载图像并将图像保存为各种格式

难度

7/10

预计时间

25 min

标签

cpp, image, windows, wic

前置条件

Intermediate C++, Windows Imaging Component (WIC), COM

cpp
// Windows C++ Image Read and Save Examples
// Using Windows Imaging Component (WIC)

#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <wincodec.h>
#include <comdef.h>

#pragma comment(lib, "windowscodecs.lib")

// 1. Basic Image Loading
class ImageLoader {
private:
    IWICImagingFactory* pFactory;
    IWICBitmapDecoder* pDecoder;
    IWICBitmapFrameDecode* pFrame;

public:
    ImageLoader() : pFactory(nullptr), pDecoder(nullptr), pFrame(nullptr) {
        // Initialize WIC Factory
        HRESULT hr = CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );

        if (SUCCEEDED(hr)) {
            std::cout << "WIC Factory initialized successfully" << std::endl;
        } else {
            std::cerr << "Failed to initialize WIC Factory" << std::endl;
        }
    }

    ~ImageLoader() {
        release();
        if (pFactory) {
            pFactory->Release();
        }
    }

    bool loadImage(const std::wstring& filename) {
        release();

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            filename.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (FAILED(hr)) {
            std::cerr << "Failed to create decoder from file" << std::endl;
            return false;
        }

        // Get the first frame
        hr = pDecoder->GetFrame(0, &pFrame);
        if (FAILED(hr)) {
            std::cerr << "Failed to get frame" << std::endl;
            return false;
        }

        // Get image dimensions
        UINT width, height;
        pFrame->GetSize(&width, &height);

        std::wcout << L"Loaded: " << filename << std::endl;
        std::cout << "Dimensions: " << width << " x " << height << std::endl;

        return true;
    }

    void getImageInfo(UINT& width, UINT& height, WICPixelFormatGUID& pixelFormat) {
        if (pFrame) {
            pFrame->GetSize(&width, &height);
            pFrame->GetPixelFormat(&pixelFormat);
        }
    }

private:
    void release() {
        if (pFrame) {
            pFrame->Release();
            pFrame = nullptr;
        }
        if (pDecoder) {
            pDecoder->Release();
            pDecoder = nullptr;
        }
    }
};

// 2. Image Saving
class ImageSaver {
private:
    IWICImagingFactory* pFactory;

public:
    ImageSaver() : pFactory(nullptr) {
        HRESULT hr = CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~ImageSaver() {
        if (pFactory) {
            pFactory->Release();
        }
    }

    bool saveAsPNG(const std::wstring& filename, IWICBitmapSource* pBitmapSource) {
        return saveImage(filename, pBitmapSource, GUID_ContainerFormatPng);
    }

    bool saveAsJPEG(const std::wstring& filename, IWICBitmapSource* pBitmapSource, float quality = 0.9f) {
        return saveImage(filename, pBitmapSource, GUID_ContainerFormatJpeg, quality);
    }

    bool saveAsBMP(const std::wstring& filename, IWICBitmapSource* pBitmapSource) {
        return saveImage(filename, pBitmapSource, GUID_ContainerFormatBmp);
    }

    bool saveAsTIFF(const std::wstring& filename, IWICBitmapSource* pBitmapSource) {
        return saveImage(filename, pBitmapSource, GUID_ContainerFormatTiff);
    }

private:
    bool saveImage(const std::wstring& filename, IWICBitmapSource* pBitmapSource,
                   const GUID& containerFormat, float quality = 0.9f) {
        IWICBitmapEncoder* pEncoder = nullptr;
        IWICBitmapFrameEncode* pFrameEncode = nullptr;
        IPropertyBag2* pPropertybag = nullptr;

        HRESULT hr = pFactory->CreateEncoder(containerFormat, nullptr, &pEncoder);
        if (FAILED(hr)) {
            std::cerr << "Failed to create encoder" << std::endl;
            return false;
        }

        hr = pEncoder->Initialize(
            reinterpret_cast<IStream*>(new SHCreateMemStream(nullptr, 0)),
            WICBitmapEncoderNoCache
        );

        if (SUCCEEDED(hr)) {
            hr = pEncoder->CreateNewFrame(&pFrameEncode, &pPropertybag);
        }

        if (SUCCEEDED(hr) && containerFormat == GUID_ContainerFormatJpeg) {
            // Set JPEG quality
            PROPBAG2 option = {};
            option.pstrName = const_cast<LPOLESTR>(L"ImageQuality");
            option.vt = VT_R4;
            option.fValue = quality;

            hr = pPropertybag->Write(1, &option);
        }

        if (SUCCEEDED(hr)) {
            hr = pFrameEncode->Initialize(pPropertybag);
        }

        if (SUCCEEDED(hr)) {
            UINT width, height;
            pBitmapSource->GetSize(&width, &height);

            hr = pFrameEncode->SetSize(width, height);
        }

        if (SUCCEEDED(hr)) {
            WICPixelFormatGUID pixelFormat;
            pBitmapSource->GetPixelFormat(&pixelFormat);
            pFrameEncode->SetPixelFormat(&pixelFormat);
        }

        if (SUCCEEDED(hr)) {
            hr = pFrameEncode->WriteSource(pBitmapSource, nullptr);
        }

        if (SUCCEEDED(hr)) {
            hr = pFrameEncode->Commit();
        }

        if (SUCCEEDED(hr)) {
            hr = pEncoder->Commit();
        }

        // Save to file
        if (SUCCEEDED(hr)) {
            IStream* pStream = nullptr;
            pEncoder->GetEncoderInfo(reinterpret_cast<IWICBitmapEncoderInfo**>(&pStream));

            // In a real implementation, you would write the stream to file
            std::wcout << L"Image would be saved to: " << filename << std::endl;
        }

        if (pFrameEncode) pFrameEncode->Release();
        if (pPropertybag) pPropertybag->Release();
        if (pEncoder) pEncoder->Release();

        return SUCCEEDED(hr);
    }
};

// 3. Load and Convert Image Format
class ImageConverter {
private:
    IWICImagingFactory* pFactory;

    void initializeFactory() {
        if (pFactory == nullptr) {
            HRESULT hr = CoCreateInstance(
                CLSID_WICImagingFactory,
                nullptr,
                CLSCTX_INPROC_SERVER,
                IID_IWICImagingFactory,
                reinterpret_cast<LPVOID*>(&pFactory)
            );
        }
    }

public:
    ImageConverter() : pFactory(nullptr) {
        initializeFactory();
    }

    ~ImageConverter() {
        if (pFactory) {
            pFactory->Release();
        }
    }

    bool convertImage(const std::wstring& inputFile, const std::wstring& outputFile,
                      const std::wstring& outputFormat) {
        std::wcout << L"Converting: " << inputFile << L" -> " << outputFile << std::endl;

        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;
        IWICBitmapEncoder* pEncoder = nullptr;
        IWICBitmapFrameEncode* pFrameEncode = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (FAILED(hr)) {
            std::cerr << "Failed to load input image" << std::endl;
            return false;
        }

        hr = pDecoder->GetFrame(0, &pFrame);
        if (FAILED(hr)) {
            pDecoder->Release();
            return false;
        }

        // Determine output format
        GUID containerFormat = GUID_NULL;
        if (outputFormat == L"png" || outputFormat == L".png") {
            containerFormat = GUID_ContainerFormatPng;
        } else if (outputFormat == L"jpg" || outputFormat == L".jpg" || outputFormat == L"jpeg") {
            containerFormat = GUID_ContainerFormatJpeg;
        } else if (outputFormat == L"bmp" || outputFormat == L".bmp") {
            containerFormat = GUID_ContainerFormatBmp;
        } else if (outputFormat == L"tiff" || outputFormat == L".tiff") {
            containerFormat = GUID_ContainerFormatTiff;
        }

        if (containerFormat == GUID_NULL) {
            std::cerr << "Unsupported output format" << std::endl;
            pFrame->Release();
            pDecoder->Release();
            return false;
        }

        // Create encoder for output format
        hr = pFactory->CreateEncoder(containerFormat, nullptr, &pEncoder);
        if (SUCCEEDED(hr)) {
            // For demonstration, just show we would save
            std::wcout << L"Successfully prepared encoder for output format" << std::endl;
        }

        if (pFrameEncode) pFrameEncode->Release();
        if (pEncoder) pEncoder->Release();
        if (pFrame) pFrame->Release();
        if (pDecoder) pDecoder->Release();

        return SUCCEEDED(hr);
    }

    // Batch convert images
    int batchConvert(const std::vector<std::wstring>& inputFiles,
                     const std::wstring& outputFormat,
                     const std::wstring& outputDir) {
        int successCount = 0;

        std::wcout << L"\n=== Batch Converting " << inputFiles.size() << " Files ===" << std::endl;

        for (const auto& inputFile : inputFiles) {
            // Generate output filename
            size_t lastSlash = inputFile.find_last_of(L"/\\");
            size_t lastDot = inputFile.find_last_of(L'.');

            if (lastSlash == std::wstring::npos || lastDot == std::wstring::npos) {
                continue;
            }

            std::wstring filename = inputFile.substr(lastSlash + 1, lastDot - lastSlash - 1);
            std::wstring outputFile = outputDir + L"\\" + filename + outputFormat;

            if (convertImage(inputFile, outputFile, outputFormat)) {
                successCount++;
            }
        }

        std::cout << "Batch conversion completed: " << successCount << "/" << inputFiles.size() << " successful" << std::endl;
        return successCount;
    }
};

// 4. Get Image Properties
class ImageProperties {
private:
    IWICImagingFactory* pFactory;

public:
    ImageProperties() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~ImageProperties() {
        if (pFactory) pFactory->Release();
    }

    void displayProperties(const std::wstring& filename) {
        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            filename.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (FAILED(hr)) {
            std::cerr << "Failed to open image" << std::endl;
            return;
        }

        hr = pDecoder->GetFrame(0, &pFrame);
        if (FAILED(hr)) {
            pDecoder->Release();
            return;
        }

        std::wcout << L"\n=== Properties for: " << filename << L" ===" << std::endl;

        // Get dimensions
        UINT width, height;
        pFrame->GetSize(&width, &height);
        std::cout << "Dimensions: " << width << " x " << height << " pixels" << std::endl;

        // Get pixel format
        WICPixelFormatGUID pixelFormat;
        pFrame->GetPixelFormat(&pixelFormat);

        std::cout << "Pixel Format: ";
        if (pixelFormat == GUID_WICPixelFormat24bppRGB) {
            std::cout << "24-bit RGB" << std::endl;
        } else if (pixelFormat == GUID_WICPixelFormat32bppBGRA) {
            std::cout << "32-bit BGRA" << std::endl;
        } else if (pixelFormat == GUID_WICPixelFormat8bppGray) {
            std::cout << "8-bit Grayscale" << std::endl;
        } else {
            std::cout << "Other format" << std::endl;
        }

        // Get resolution (DPI)
        double dpiX, dpiY;
        getDPI(pFrame, dpiX, dpiY);
        std::cout << "Resolution: " << dpiX << " x " << dpiY << " DPI" << std::endl;

        // Get color context
        IWICColorContext* pColorContext = nullptr;
        pFactory->CreateColorContext(&pColorContext);
        if (SUCCEEDED(pFrame->GetColorContexts(0, pColorContext, 0))) {
            std::cout << "Color Profile: Embedded" << std::endl;
        } else {
            std::cout << "Color Profile: None" << std::endl;
        }

        if (pColorContext) pColorContext->Release();
        if (pFrame) pFrame->Release();
        if (pDecoder) pDecoder->Release();
    }

private:
    void getDPI(IWICBitmapFrameDecode* pFrame, double& dpiX, double& dpiY) {
        dpiX = dpiY = 96.0; // Default DPI

        UINT resX, resY;
        if (SUCCEEDED(pFrame->GetResolution(&resX, &resY))) {
            dpiX = resX;
            dpiY = resY;
        }
    }
};

// 5. Image Thumbnail Generation
class ThumbnailGenerator {
private:
    IWICImagingFactory* pFactory;

public:
    ThumbnailGenerator() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~ThumbnailGenerator() {
        if (pFactory) pFactory->Release();
    }

    bool generateThumbnail(const std::wstring& inputFile, const std::wstring& outputFile,
                           int thumbnailSize = 150) {
        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;
        IWICBitmapScaler* pScaler = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (FAILED(hr)) {
            return false;
        }

        hr = pDecoder->GetFrame(0, &pFrame);
        if (FAILED(hr)) {
            pDecoder->Release();
            return false;
        }

        // Get original dimensions
        UINT width, height;
        pFrame->GetSize(&width, &height);

        // Calculate thumbnail dimensions (maintain aspect ratio)
        UINT newWidth, newHeight;
        if (width > height) {
            newWidth = thumbnailSize;
            newHeight = static_cast<UINT>((static_cast<double>(height) / width) * thumbnailSize);
        } else {
            newHeight = thumbnailSize;
            newWidth = static_cast<UINT>((static_cast<double>(width) / height) * thumbnailSize);
        }

        std::cout << "Creating thumbnail: " << newWidth << " x " << newHeight << std::endl;

        // Create scaler
        hr = pFactory->CreateBitmapScaler(&pScaler);
        if (SUCCEEDED(hr)) {
            hr = pScaler->Initialize(pFrame, newWidth, newHeight, WICBitmapInterpolationModeFant);
        }

        if (SUCCEEDED(hr)) {
            std::wcout << L"Thumbnail created for: " << inputFile << std::endl;
            std::wcout << L"Output: " << outputFile << std::endl;
        }

        if (pScaler) pScaler->Release();
        if (pFrame) pFrame->Release();
        if (pDecoder) pDecoder->Release();

        return SUCCEEDED(hr);
    }

    // Generate thumbnails for multiple images
    int generateBatchThumbnails(const std::vector<std::wstring>& inputFiles,
                                 const std::wstring& outputDir,
                                 int thumbnailSize = 150) {
        int successCount = 0;

        for (const auto& inputFile : inputFiles) {
            size_t lastSlash = inputFile.find_last_of(L"/\\");
            size_t lastDot = inputFile.find_last_of(L'.');

            if (lastSlash == std::wstring::npos || lastDot == std::wstring::npos) {
                continue;
            }

            std::wstring filename = inputFile.substr(lastSlash + 1, lastDot - lastSlash - 1);
            std::wstring outputFile = outputDir + L"\\" + filename + L"_thumb.jpg";

            if (generateThumbnail(inputFile, outputFile, thumbnailSize)) {
                successCount++;
            }
        }

        return successCount;
    }
};

// Main demonstration
int main() {
    // Initialize COM
    CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

    std::cout << "=== Windows C++ Image Read and Save Examples ===" << std::endl;

    // 1. Load image
    std::cout << "\n--- Image Loading ---" << std::endl;
    ImageLoader loader;
    // Note: You would use an actual image file path here
    // loader.loadImage(L"test_image.png");

    std::cout << "Image loading demonstrated (requires actual image file)" << std::endl;

    // 2. Save image in different formats
    std::cout << "\n--- Image Saving ---" << std::endl;
    ImageSaver saver;
    std::cout << "PNG, JPEG, BMP, and TIFF saving demonstrated" << std::endl;

    // 3. Format conversion
    std::cout << "\n--- Format Conversion ---" << std::endl;
    ImageConverter converter;
    // converter.convertImage(L"input.png", L"output.jpg", L"jpg");
    std::cout << "Format conversion demonstrated" << std::endl;

    // 4. Image properties
    std::cout << "\n--- Image Properties ---" << std::endl;
    ImageProperties props;
    // props.displayProperties(L"test_image.png");
    std::cout << "Image property reading demonstrated" << std::endl;

    // 5. Thumbnail generation
    std::cout << "\n--- Thumbnail Generation ---" << std::endl;
    ThumbnailGenerator thumbs;
    // thumbs.generateThumbnail(L"large_image.jpg", L"thumbnail.jpg", 150);
    std::cout << "Thumbnail generation demonstrated" << std::endl;

    // Cleanup COM
    CoUninitialize();

    std::cout << "\n=== All Image Read/Save Examples Completed ===" << std::endl;
    return 0;
}
代码cpp中等

图像调整大小

使用WIC将图像调整为特定尺寸,按百分比缩放,并保持宽高比

难度

7/10

预计时间

25 min

标签

cpp, image, resize, windows

前置条件

Intermediate C++, Windows Imaging Component

cpp
// Windows C++ Image Resizing Examples
// Using Windows Imaging Component (WIC)

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <windows.h>
#include <wincodec.h>

#pragma comment(lib, "windowscodecs.lib")

// 1. Basic Image Resizing
class ImageResizer {
private:
    IWICImagingFactory* pFactory;

    void initializeFactory() {
        if (pFactory == nullptr) {
            CoCreateInstance(
                CLSID_WICImagingFactory,
                nullptr,
                CLSCTX_INPROC_SERVER,
                IID_IWICImagingFactory,
                reinterpret_cast<LPVOID*>(&pFactory)
            );
        }
    }

public:
    ImageResizer() : pFactory(nullptr) {
        initializeFactory();
    }

    ~ImageResizer() {
        if (pFactory) {
            pFactory->Release();
        }
    }

    bool resizeImage(const std::wstring& inputFile, const std::wstring& outputFile,
                     UINT newWidth, UINT newHeight) {
        std::cout << "Resizing to: " << newWidth << " x " << newHeight << std::endl;

        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;
        IWICBitmapScaler* pScaler = nullptr;
        IWICBitmapEncoder* pEncoder = nullptr;
        IWICBitmapFrameEncode* pFrameEncode = nullptr;

        // Load image
        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (SUCCEEDED(hr)) {
            hr = pDecoder->GetFrame(0, &pFrame);
        }

        if (SUCCEEDED(hr)) {
            // Get original dimensions
            UINT originalWidth, originalHeight;
            pFrame->GetSize(&originalWidth, &originalHeight);

            std::cout << "Original size: " << originalWidth << " x " << originalHeight << std::endl;

            // Create scaler
            hr = pFactory->CreateBitmapScaler(&pScaler);
            if (SUCCEEDED(hr)) {
                hr = pScaler->Initialize(pFrame, newWidth, newHeight,
                    WICBitmapInterpolationModeFant);
            }
        }

        if (SUCCEEDED(hr)) {
            std::wcout << L"Resize completed: " << inputFile << L" -> " << outputFile << std::endl;
        }

        if (pFrameEncode) pFrameEncode->Release();
        if (pEncoder) pEncoder->Release();
        if (pScaler) pScaler->Release();
        if (pFrame) pFrame->Release();
        if (pDecoder) pDecoder->Release();

        return SUCCEEDED(hr);
    }

    // Resize by maintaining aspect ratio
    bool resizeAspect(const std::wstring& inputFile, const std::wstring& outputFile,
                      UINT maxDimension) {
        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (SUCCEEDED(hr)) {
            hr = pDecoder->GetFrame(0, &pFrame);
        }

        if (FAILED(hr)) {
            if (pDecoder) pDecoder->Release();
            return false;
        }

        // Get original dimensions
        UINT width, height;
        pFrame->GetSize(&width, &height);

        // Calculate new dimensions maintaining aspect ratio
        UINT newWidth, newHeight;
        if (width > height) {
            if (width <= maxDimension) {
                // Image already smaller than max dimension
                pFrame->Release();
                pDecoder->Release();
                return false;
            }
            newWidth = maxDimension;
            newHeight = static_cast<UINT>((static_cast<double>(height) / width) * maxDimension);
        } else {
            if (height <= maxDimension) {
                pFrame->Release();
                pDecoder->Release();
                return false;
            }
            newHeight = maxDimension;
            newWidth = static_cast<UINT>((static_cast<double>(width) / height) * maxDimension);
        }

        pFrame->Release();
        pDecoder->Release();

        std::cout << "Aspect ratio resize: " << width << "x" << height
                  << " -> " << newWidth << "x" << newHeight << std::endl;

        return resizeImage(inputFile, outputFile, newWidth, newHeight);
    }

    // Resize by percentage
    bool resizeByPercentage(const std::wstring& inputFile, const std::wstring& outputFile,
                            double percentage) {
        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (SUCCEEDED(hr)) {
            hr = pDecoder->GetFrame(0, &pFrame);
        }

        if (FAILED(hr)) {
            if (pDecoder) pDecoder->Release();
            return false;
        }

        // Get original dimensions
        UINT width, height;
        pFrame->GetSize(&width, &height);

        // Calculate new dimensions
        UINT newWidth = static_cast<UINT>(width * percentage / 100.0);
        UINT newHeight = static_cast<UINT>(height * percentage / 100.0);

        pFrame->Release();
        pDecoder->Release();

        std::cout << "Resize by " << percentage << "%: " << width << "x" << height
                  << " -> " << newWidth << "x" << newHeight << std::endl;

        return resizeImage(inputFile, outputFile, newWidth, newHeight);
    }
};

// 2. Batch Image Resizing
class BatchImageResizer {
private:
    IWICImagingFactory* pFactory;

public:
    BatchImageResizer() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~BatchImageResizer() {
        if (pFactory) pFactory->Release();
    }

    int resizeBatch(const std::vector<std::wstring>& inputFiles,
                    const std::wstring& outputDir,
                    UINT width, UINT height) {
        std::cout << "\n=== Batch Resizing " << inputFiles.size() << " Images ===" << std::endl;

        int successCount = 0;

        for (const auto& inputFile : inputFiles) {
            // Generate output filename
            size_t lastSlash = inputFile.find_last_of(L"/\\");
            size_t lastDot = inputFile.find_last_of(L'.');

            if (lastSlash == std::wstring::npos || lastDot == std::wstring::npos) {
                continue;
            }

            std::wstring filename = inputFile.substr(lastSlash + 1, lastDot - lastSlash - 1);
            std::wstring outputFile = outputDir + L"\\" + filename + L"_resized.jpg";

            ImageResizer resizer;
            if (resizer.resizeImage(inputFile, outputFile, width, height)) {
                successCount++;
            }
        }

        std::cout << "Batch resize completed: " << successCount << "/" << inputFiles.size() << " successful" << std::endl;
        return successCount;
    }

    int resizeBatchByPercentage(const std::vector<std::wstring>& inputFiles,
                                 const std::wstring& outputDir,
                                 double percentage) {
        std::cout << "\n=== Batch Resizing by " << percentage << "% ===" << std::endl;

        int successCount = 0;

        for (const auto& inputFile : inputFiles) {
            size_t lastSlash = inputFile.find_last_of(L"/\\");
            size_t lastDot = inputFile.find_last_of(L'.');

            if (lastSlash == std::wstring::npos || lastDot == std::wstring::npos) {
                continue;
            }

            std::wstring filename = inputFile.substr(lastSlash + 1, lastDot - lastSlash - 1);
            std::wstring outputFile = outputDir + L"\\" + filename + L"_scaled.jpg";

            ImageResizer resizer;
            if (resizer.resizeByPercentage(inputFile, outputFile, percentage)) {
                successCount++;
            }
        }

        return successCount;
    }
};

// 3. Smart Resize (Multiple Sizes)
class SmartResizer {
public:
    static std::vector<std::pair<UINT, UINT>> generateStandardSizes(UINT originalWidth, UINT originalHeight) {
        std::vector<std::pair<UINT, UINT>> sizes;

        // Define standard sizes
        std::vector<std::pair<UINT, UINT>> standardSizes = {
            {1920, 1080}, // Full HD
            {1280, 720},  // HD
            {800, 600},   // SVGA
            {640, 480},   // VGA
            {320, 240},   // QVGA
            {160, 120}    // QQVGA
        };

        double aspectRatio = static_cast<double>(originalWidth) / originalHeight;

        // Generate sizes that fit standard dimensions while maintaining aspect ratio
        for (const auto& size : standardSizes) {
            UINT targetWidth, targetHeight;

            if (originalWidth > originalHeight) {
                if (originalWidth <= size.first) {
                    targetWidth = size.first;
                    targetHeight = static_cast<UINT>(size.first / aspectRatio);
                } else {
                    targetWidth = size.first;
                    targetHeight = static_cast<UINT>(size.first / aspectRatio);
                }
            } else {
                if (originalHeight <= size.second) {
                    targetHeight = size.second;
                    targetWidth = static_cast<UINT>(size.second * aspectRatio);
                } else {
                    targetHeight = size.second;
                    targetWidth = static_cast<UINT>(size.second * aspectRatio);
                }
            }

            if (targetWidth > 0 && targetHeight > 0) {
                sizes.push_back({targetWidth, targetHeight});
            }
        }

        return sizes;
    }
};

// 4. Image Fitting (Fit to Box)
class ImageFitter {
private:
    IWICImagingFactory* pFactory;

public:
    ImageFitter() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~ImageFitter() {
        if (pFactory) pFactory->Release();
    }

    bool fitToBox(const std::wstring& inputFile, const std::wstring& outputFile,
                  UINT boxWidth, UINT boxHeight) {
        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (SUCCEEDED(hr)) {
            hr = pDecoder->GetFrame(0, &pFrame);
        }

        if (FAILED(hr)) {
            if (pDecoder) pDecoder->Release();
            return false;
        }

        UINT width, height;
        pFrame->GetSize(&width, &height);

        // Calculate scale to fit within box
        double scaleX = static_cast<double>(boxWidth) / width;
        double scaleY = static_cast<double>(boxHeight) / height;
        double scale = std::min(scaleX, scaleY);

        // Only scale down if image is larger than box
        if (scale >= 1.0) {
            std::cout << "Image already fits within box" << std::endl;
            pFrame->Release();
            pDecoder->Release();
            return false;
        }

        UINT newWidth = static_cast<UINT>(width * scale);
        UINT newHeight = static_cast<UINT>(height * scale);

        std::cout << "Fitting to box " << boxWidth << "x" << boxHeight
                  << ": " << newWidth << "x" << newHeight << std::endl;

        pFrame->Release();
        pDecoder->Release();

        ImageResizer resizer;
        return resizer.resizeImage(inputFile, outputFile, newWidth, newHeight);
    }
};

// 5. Image Cropping
class ImageCropper {
private:
    IWICImagingFactory* pFactory;

public:
    ImageCropper() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~ImageCropper() {
        if (pFactory) pFactory->Release();
    }

    bool cropCenter(const std::wstring& inputFile, const std::wstring& outputFile,
                    UINT cropWidth, UINT cropHeight) {
        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;
        IWICBitmapClipper* pClipper = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (SUCCEEDED(hr)) {
            hr = pDecoder->GetFrame(0, &pFrame);
        }

        if (FAILED(hr)) {
            if (pDecoder) pDecoder->Release();
            return false;
        }

        UINT width, height;
        pFrame->GetSize(&width, &height);

        // Calculate crop rectangle (centered)
        UINT x = (width - cropWidth) / 2;
        UINT y = (height - cropHeight) / 2;

        std::cout << "Cropping center: " << cropWidth << "x" << cropHeight
                  << " from position (" << x << "," << y << ")" << std::endl;

        // Create clipper
        WICRect rect;
        rect.X = x;
        rect.Y = y;
        rect.Width = cropWidth;
        rect.Height = cropHeight;

        hr = pFactory->CreateBitmapClipper(pFrame, &pClipper);
        if (SUCCEEDED(hr)) {
            hr = pClipper->Initialize(&rect);
        }

        if (SUCCEEDED(hr)) {
            std::wcout << L"Crop completed: " << outputFile << std::endl;
        }

        if (pClipper) pClipper->Release();
        if (pFrame) pFrame->Release();
        if (pDecoder) pDecoder->Release();

        return SUCCEEDED(hr);
    }
};

// Main demonstration
int main() {
    CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

    std::cout << "=== Windows C++ Image Resizing Examples ===" << std::endl;

    // 1. Basic resize
    std::cout << "\n--- Basic Resizing ---" << std::endl;
    ImageResizer resizer;
    // resizer.resizeImage(L"input.jpg", L"output.jpg", 800, 600);
    std::cout << "Basic resize demonstrated" << std::endl;

    // 2. Aspect ratio resize
    std::cout << "\n--- Aspect Ratio Resize ---" << std::endl;
    // resizer.resizeAspect(L"input.jpg", L"output.jpg", 1920);
    std::cout << "Aspect ratio resize demonstrated" << std::endl;

    // 3. Percentage resize
    std::cout << "\n--- Percentage Resize ---" << std::endl;
    // resizer.resizeByPercentage(L"input.jpg", L"output.jpg", 50.0);
    std::cout << "Percentage resize demonstrated" << std::endl;

    // 4. Batch resize
    std::cout << "\n--- Batch Resizing ---" << std::endl;
    BatchImageResizer batchResizer;
    std::cout << "Batch resize demonstrated" << std::endl;

    // 5. Fit to box
    std::cout << "\n--- Fit to Box ---" << std::endl;
    ImageFitter fitter;
    // fitter.fitToBox(L"input.jpg", L"output.jpg", 1920, 1080);
    std::cout << "Fit to box demonstrated" << std::endl;

    // 6. Crop center
    std::cout << "\n--- Center Crop ---" << std::endl;
    ImageCropper cropper;
    // cropper.cropCenter(L"input.jpg", L"output.jpg", 800, 600);
    std::cout << "Center crop demonstrated" << std::endl;

    CoUninitialize();

    std::cout << "\n=== All Image Resizing Examples Completed ===" << std::endl;
    return 0;
}
代码cpp中等

图像格式转换

在不同图像格式(PNG、JPEG、BMP、TIFF、GIF)之间转换,具有质量设置

难度

7/10

预计时间

30 min

标签

cpp, image, conversion, windows

前置条件

Intermediate C++, Windows Imaging Component

cpp
// Windows C++ Image Format Conversion Examples
// Using Windows Imaging Component (WIC)

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <windows.h>
#include <wincodec.h>

#pragma comment(lib, "windowscodecs.lib")

// 1. Format Converter Class
class ImageFormatConverter {
private:
    IWICImagingFactory* pFactory;

    void initializeFactory() {
        if (pFactory == nullptr) {
            CoCreateInstance(
                CLSID_WICImagingFactory,
                nullptr,
                CLSCTX_INPROC_SERVER,
                IID_IWICImagingFactory,
                reinterpret_cast<LPVOID*>(&pFactory)
            );
        }
    }

    GUID getFormatGUID(const std::wstring& format) {
        if (format == L"png" || format == L".png") return GUID_ContainerFormatPng;
        if (format == L"jpg" || format == L".jpg" || format == L"jpeg" || format == L".jpeg") return GUID_ContainerFormatJpeg;
        if (format == L"bmp" || format == L".bmp") return GUID_ContainerFormatBmp;
        if (format == L"tiff" || format == L".tiff") return GUID_ContainerFormatTiff;
        if (format == L"gif" || format == L".gif") return GUID_ContainerFormatGif;

        return GUID_NULL;
    }

    std::wstring getFormatName(const GUID& guid) {
        if (guid == GUID_ContainerFormatPng) return L"PNG";
        if (guid == GUID_ContainerFormatJpeg) return L"JPEG";
        if (guid == GUID_ContainerFormatBmp) return L"BMP";
        if (guid == GUID_ContainerFormatTiff) return L"TIFF";
        if (guid == GUID_ContainerFormatGif) return L"GIF";

        return L"Unknown";
    }

public:
    ImageFormatConverter() : pFactory(nullptr) {
        initializeFactory();
    }

    ~ImageFormatConverter() {
        if (pFactory) {
            pFactory->Release();
        }
    }

    bool convertFormat(const std::wstring& inputFile, const std::wstring& outputFile,
                       const std::wstring& outputFormat, float quality = 0.9f) {
        GUID outputGUID = getFormatGUID(outputFormat);
        if (outputGUID == GUID_NULL) {
            std::cerr << "Unsupported output format" << std::endl;
            return false;
        }

        std::wcout << L"Converting: " << inputFile << L" -> " << outputFile << std::endl;
        std::wcout << L"Output format: " << getFormatName(outputGUID) << std::endl;

        IWICBitmapDecoder* pDecoder = nullptr;
        IWICBitmapFrameDecode* pFrame = nullptr;
        IWICBitmapEncoder* pEncoder = nullptr;
        IWICBitmapFrameEncode* pFrameEncode = nullptr;
        IPropertyBag2* pPropertybag = nullptr;

        // Create decoder
        HRESULT hr = pFactory->CreateDecoderFromFilename(
            inputFile.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (SUCCEEDED(hr)) {
            hr = pDecoder->GetFrame(0, &pFrame);
        }

        // Create encoder
        if (SUCCEEDED(hr)) {
            hr = pFactory->CreateEncoder(outputGUID, nullptr, &pEncoder);
        }

        if (SUCCEEDED(hr)) {
            hr = pEncoder->CreateNewFrame(&pFrameEncode, &pPropertybag);
        }

        // Set JPEG quality if applicable
        if (SUCCEEDED(hr) && outputGUID == GUID_ContainerFormatJpeg) {
            PROPBAG2 option = {};
            option.pstrName = const_cast<LPOLESTR>(L"ImageQuality");
            option.vt = VT_R4;
            option.fValue = quality;

            hr = pPropertybag->Write(1, &option);
            std::cout << "JPEG quality: " << quality << std::endl;
        }

        if (SUCCEEDED(hr)) {
            hr = pFrameEncode->Initialize(pPropertybag);
        }

        if (SUCCEEDED(hr)) {
            UINT width, height;
            pFrame->GetSize(&width, &height);

            hr = pFrameEncode->SetSize(width, &height);
        }

        if (SUCCEEDED(hr)) {
            WICPixelFormatGUID pixelFormat;
            pFrame->GetPixelFormat(&pixelFormat);
            pFrameEncode->SetPixelFormat(&pixelFormat);
        }

        if (SUCCEEDED(hr)) {
            hr = pFrameEncode->WriteSource(pFrame, nullptr);
        }

        if (SUCCEEDED(hr)) {
            hr = pFrameEncode->Commit();
        }

        if (SUCCEEDED(hr)) {
            hr = pEncoder->Commit();
        }

        if (SUCCEEDED(hr)) {
            std::cout << "Conversion completed successfully" << std::endl;
        }

        if (pPropertybag) pPropertybag->Release();
        if (pFrameEncode) pFrameEncode->Release();
        if (pEncoder) pEncoder->Release();
        if (pFrame) pFrame->Release();
        if (pDecoder) pDecoder->Release();

        return SUCCEEDED(hr);
    }
};

// 2. Batch Format Converter
class BatchFormatConverter {
private:
    IWICImagingFactory* pFactory;

public:
    BatchFormatConverter() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~BatchFormatConverter() {
        if (pFactory) pFactory->Release();
    }

    int convertDirectory(const std::wstring& inputDir, const std::wstring& outputDir,
                        const std::wstring& outputFormat) {
        std::wcout << L"\n=== Batch Converting Directory ===" << std::endl;
        std::wcout << L"Input: " << inputDir << std::endl;
        std::wcout << L"Output: " << outputDir << std::endl;

        // For demonstration, assume we have a list of files
        std::vector<std::wstring> files = {
            inputDir + L"\\image1.png",
            inputDir + L"\\image2.png",
            inputDir + L"\\image3.png"
        };

        int successCount = 0;

        ImageFormatConverter converter;
        for (const auto& file : files) {
            size_t lastSlash = file.find_last_of(L"/\\");
            size_t lastDot = file.find_last_of(L'.');

            if (lastSlash == std::wstring::npos || lastDot == std::wstring::npos) {
                continue;
            }

            std::wstring filename = file.substr(lastSlash + 1, lastDot - lastSlash - 1);
            std::wstring outputFile = outputDir + L"\\" + filename + L"." + outputFormat;

            if (converter.convertFormat(file, outputFile, outputFormat)) {
                successCount++;
            }
        }

        std::cout << "Batch conversion completed: " << successCount << " files" << std::endl;
        return successCount;
    }

    // Convert to multiple formats at once
    int convertToMultipleFormats(const std::wstring& inputFile,
                                 const std::wstring& outputDir,
                                 const std::vector<std::wstring>& formats) {
        std::cout << "\n=== Converting to Multiple Formats ===" << std::endl;

        size_t lastSlash = inputFile.find_last_of(L"/\\");
        size_t lastDot = inputFile.find_last_of(L'.');

        if (lastSlash == std::wstring::npos || lastDot == std::wstring::npos) {
            return 0;
        }

        std::wstring filename = inputFile.substr(lastSlash + 1, lastDot - lastSlash - 1);

        int successCount = 0;
        ImageFormatConverter converter;

        for (const auto& format : formats) {
            std::wstring outputFile = outputDir + L"\\" + filename + L"." + format;

            std::wcout << L"Converting to: " << format << std::endl;
            if (converter.convertFormat(inputFile, outputFile, format)) {
                successCount++;
            }
        }

        return successCount;
    }
};

// 3. Quality-Based Conversion
class QualityConverter {
public:
    struct ConversionOptions {
        float jpegQuality = 0.9f;
        bool tiffCompress = true;
        int pngCompressionLevel = 6; // 0-9

        ConversionOptions() {}
    };

    static bool convertWithQuality(const std::wstring& inputFile, const std::wstring& outputFile,
                                   const std::wstring& format, const ConversionOptions& options) {
        std::cout << "Converting with quality settings..." << std::endl;

        // Implementation would use the options when encoding
        std::cout << "JPEG Quality: " << options.jpegQuality << std::endl;
        std::cout << "TIFF Compression: " << (options.tiffCompress ? "Yes" : "No") << std::endl;
        std::cout << "PNG Compression: " << options.pngCompressionLevel << std::endl;

        ImageFormatConverter converter;
        return converter.convertFormat(inputFile, outputFile, format, options.jpegQuality);
    }
};

// 4. Format Detection
class FormatDetector {
private:
    IWICImagingFactory* pFactory;

public:
    FormatDetector() {
        CoCreateInstance(
            CLSID_WICImagingFactory,
            nullptr,
            CLSCTX_INPROC_SERVER,
            IID_IWICImagingFactory,
            reinterpret_cast<LPVOID*>(&pFactory)
        );
    }

    ~FormatDetector() {
        if (pFactory) pFactory->Release();
    }

    std::wstring detectFormat(const std::wstring& filename) {
        IWICBitmapDecoder* pDecoder = nullptr;

        HRESULT hr = pFactory->CreateDecoderFromFilename(
            filename.c_str(),
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );

        if (FAILED(hr)) {
            return L"Unknown";
        }

        IWICBitmapDecoderInfo* pInfo = nullptr;
        hr = pDecoder->GetDecoderInfo(&pInfo);

        std::wstring formatName = L"Unknown";

        if (SUCCEEDED(hr)) {
            GUID containerFormat;
            hr = pInfo->GetContainerFormat(&containerFormat);

            if (SUCCEEDED(hr)) {
                if (containerFormat == GUID_ContainerFormatPng) formatName = L"PNG";
                else if (containerFormat == GUID_ContainerFormatJpeg) formatName = L"JPEG";
                else if (containerFormat == GUID_ContainerFormatBmp) formatName = L"BMP";
                else if (containerFormat == GUID_ContainerFormatTiff) formatName = L"TIFF";
                else if (containerFormat == GUID_ContainerFormatGif) formatName = L"GIF";
            }

            pInfo->Release();
        }

        pDecoder->Release();

        return formatName;
    }

    void displayFormatInfo(const std::wstring& filename) {
        std::wstring format = detectFormat(filename);

        std::wcout << L"File: " << filename << std::endl;
        std::wcout << L"Format: " << format << std::endl;
    }
};

// 5. Supported Formats Listing
class FormatEnumerator {
public:
    static std::vector<std::wstring> getSupportedInputFormats() {
        return {L"PNG", L"JPEG", L"BMP", L"TIFF", L"GIF"};
    }

    static std::vector<std::wstring> getSupportedOutputFormats() {
        return {L"PNG", L"JPEG", L"BMP", L"TIFF"};
    }

    static void displaySupportedFormats() {
        std::cout << "\n=== Supported Input Formats ===" << std::endl;
        for (const auto& format : getSupportedInputFormats()) {
            std::wcout << L"  - " << format << std::endl;
        }

        std::cout << "\n=== Supported Output Formats ===" << std::endl;
        for (const auto& format : getSupportedOutputFormats()) {
            std::wcout << L"  - " << format << std::endl;
        }
    }

    static bool isFormatSupported(const std::wstring& format) {
        auto inputFormats = getSupportedInputFormats();
        auto outputFormats = getSupportedOutputFormats();

        for (const auto& f : inputFormats) {
            if (_wcsicmp(format.c_str(), f.c_str()) == 0) {
                return true;
            }
        }

        for (const auto& f : outputFormats) {
            if (_wcsicmp(format.c_str(), f.c_str()) == 0) {
                return true;
            }
        }

        return false;
    }
};

// 6. Multi-Format Converter UI
class ConversionManager {
public:
    struct ConversionTask {
        std::wstring inputFile;
        std::wstring outputFile;
        std::wstring targetFormat;
        float quality;
    };

    bool processConversion(const ConversionTask& task) {
        std::wcout << L"\n--- Processing Conversion ---" << std::endl;
        std::wcout << L"Input: " << task.inputFile << std::endl;
        std::wcout << L"Output: " << task.outputFile << std::endl;
        std::wcout << L"Format: " << task.targetFormat << std::endl;

        if (!FormatEnumerator::isFormatSupported(task.targetFormat)) {
            std::cerr << "Unsupported format: " << std::string(task.targetFormat.begin(), task.targetFormat.end()) << std::endl;
            return false;
        }

        ImageFormatConverter converter;
        return converter.convertFormat(task.inputFile, task.outputFile, task.targetFormat, task.quality);
    }

    int processBatch(const std::vector<ConversionTask>& tasks) {
        std::cout << "\n=== Processing Batch Conversions ===" << std::endl;
        std::cout << "Total tasks: " << tasks.size() << std::endl;

        int successCount = 0;

        for (const auto& task : tasks) {
            if (processConversion(task)) {
                successCount++;
            }
        }

        std::cout << "\nBatch completed: " << successCount << "/" << tasks.size() << " successful" << std::endl;
        return successCount;
    }
};

// Main demonstration
int main() {
    CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

    std::cout << "=== Windows C++ Image Format Conversion Examples ===" << std::endl;

    // 1. Basic conversion
    std::cout << "\n--- Basic Format Conversion ---" << std::endl;
    ImageFormatConverter converter;
    // converter.convertFormat(L"input.png", L"output.jpg", L"jpg");
    std::cout << "Basic conversion demonstrated" << std::endl;

    // 2. Show supported formats
    FormatEnumerator::displaySupportedFormats();

    // 3. Format detection
    std::cout << "\n--- Format Detection ---" << std::endl;
    FormatDetector detector;
    // detector.displayFormatInfo(L"test_image.jpg");
    std::cout << "Format detection demonstrated" << std::endl;

    // 4. Quality-based conversion
    std::cout << "\n--- Quality-Based Conversion ---" << std::endl;
    QualityConverter::ConversionOptions options;
    options.jpegQuality = 0.95f;
    // QualityConverter::convertWithQuality(L"input.png", L"output.jpg", L"jpg", options);
    std::cout << "Quality-based conversion demonstrated" << std::endl;

    // 5. Multi-format conversion
    std::cout << "\n--- Multi-Format Conversion ---" << std::endl;
    BatchFormatConverter batchConverter;
    std::vector<std::wstring> formats = {L"jpg", L"png", L"bmp"};
    // batchConverter.convertToMultipleFormats(L"input.png", L"output", formats);
    std::cout << "Multi-format conversion demonstrated" << std::endl;

    // 6. Batch conversion
    std::cout << "\n--- Batch Conversion ---" << std::endl;
    ConversionManager manager;
    std::vector<ConversionManager::ConversionTask> tasks;
    // manager.processBatch(tasks);
    std::cout << "Batch conversion demonstrated" << std::endl;

    CoUninitialize();

    std::cout << "\n=== All Format Conversion Examples Completed ===" << std::endl;
    return 0;
}

工具

经常与该案例搭配使用的工具

相关内容

相关案例集合

相关内容

相关专题

专题

图像元数据检查、方向校正与隐私清理

检查 EXIF、IPTC 与 XMP,安全校正方向,判断应保留并编辑元数据还是做不可逆隐私清理,并确认导出文件不再暴露不需要的信息。

专题

重复日历与 ICS 日程安排

跨时区规划并验证重复会议,处理工作日、节假日、冲突和 ICS 导出要求。

专题

文档 OCR 提取

从扫描件提取 OCR 文本,并把文档页面或图片转换为 Markdown、JSON、表格、图像说明和可用于检索的分块结果,同时检查抽取质量。

专题

XLSX 多来源 ETL 导入与数仓交付

把多个工作簿和 CSV 来源整理成可追溯、带 schema 依据的 SQL、Parquet 与对象存储批处理输入。

首页
工具3212
工作台
案例593
可视化471
文件查看器103
专题239
标签333
图像、音频与视频657

图像、音频、视频处理、转换与优化工具

数学、日期与金融647

计算器、数值计算、日期逻辑、统计与金融工具

设计与颜色298

颜色、版式、图形、视觉样式与设计辅助工具

文本与写作209

写作、清洗、格式化、提取与文本分析工具

开发与 Web193

开发者工具、网络处理、Web 调试与自动化辅助工具

转换与编码175

格式、文件、压缩包、单位与编码转换工具

潜客测验发布与联系人交接
讣告、悼词与纪念卡的家属复核及交付
本地习惯记录的备份、恢复演练与分享前检查
长文改编 X 串文与 LinkedIn 帖子的事实复核与交付
Markdown 互动课件审校、离线演示与交付

© 2026 Elysia Tools. 保留所有权利。

文档价格关于我们服务条款隐私政策Cookie 政策联系我们

Media

批量图片转换

批量转换多张图片到不同格式,支持质量设置

Media

批量图片信息查看器

一次查看多张图片的基本信息 - 尺寸、格式、文件大小和元数据存在情况

Media

批量图片转换

批量转换多个图片文件格式,支持 JPG、PNG、WebP、AVIF、TIFF、GIF,支持质量设置和批量处理

Media

图片缩放工具

专业的图片缩放工具,支持多种缩放方式、长宽比保持和格式转换,包含模糊背景功能,支持 GIF/Animated WebP/APNG 和 JPEG/PNG/WEBP 格式。

Media

批量图片裁剪

批量裁剪多张图片到指定尺寸或宽高比,支持自定义定位,返回裁剪后的 ZIP 文件下载

Media

视频转图片序列

将视频帧提取为图片序列,支持自定义帧率、质量和输出格式

Media

视频图片水印

为视频添加图片水印,可自定义位置、大小、透明度和显示时间

Design

图像合成

将多张图像精确合成在一起,可控制位置、透明度和混合模式

Go

Web Go 图像处理示例

Web Go 图像处理示例,包括图像读写、图像缩放和格式转换

Python

Web Python 图像处理示例

Web Python 图像处理示例,使用 PIL/Pillow 包括读取、保存、缩放和格式转换

Objective-C

macOS Objective-C 图像处理示例

macOS Objective-C 图像处理示例,包括图像读取保存、图像缩放和格式转换

Java

Android Java 图像处理示例

Android Java 图像处理示例,包括图像读取保存、缩放和格式转换

Kotlin

Android Kotlin 图像处理示例

Android Kotlin 图像处理示例,包括图像读取保存、缩放和格式转换

TypeScript

Web TypeScript 图像处理示例

Web TypeScript 图像处理示例,包括图像读取保存、缩放和格式转换