Elysia Tools
Navigation mobile
C++
Exemples de Traitement d'Images Windows C++
Exemples de traitement d'images Windows C++ incluant lecture/sauvegarde d'images, redimensionnement et conversion de format utilisant Windows Imaging Component
Exemples
Entrées de cette collection
Lecture et Sauvegarde d'Images
Charger des images depuis des fichiers et sauvegarder des images dans divers formats utilisant Windows Imaging Component
Difficulté
7/10
Temps estimé
25 min
Étiquettes
cpp, image, windows, wic
Prérequis
Intermediate C++, Windows Imaging Component (WIC), COM
// 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;
}Redimensionnement d'Images
Redimensionner des images à des dimensions spécifiques, mettre à l'échelle en pourcentage et maintenir le rapport d'aspect utilisant WIC
Difficulté
7/10
Temps estimé
25 min
Étiquettes
cpp, image, resize, windows
Prérequis
Intermediate C++, Windows Imaging Component
// 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;
}Conversion de Format d'Image
Convertir entre différents formats d'image (PNG, JPEG, BMP, TIFF, GIF) avec des paramètres de qualité
Difficulté
7/10
Temps estimé
30 min
Étiquettes
cpp, image, conversion, windows
Prérequis
Intermediate C++, Windows Imaging Component
// 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;
}Outils
Outils souvent utilisés avec cet exemple
Associé