Created
October 3, 2020 14:56
-
-
Save SuperKogito/434ac8489f8b99aa10377966180e3a35 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <minmax.h> | |
#include <gdiplus.h> | |
#include <SDKDDKVer.h> | |
#pragma comment(lib,"gdiplus.lib") | |
#include "atlimage.h" | |
bool saveToMemory(Gdiplus::Bitmap* tile, std::vector<BYTE>& data, std::string dataFormat) | |
{ | |
// write to IStream | |
IStream* istream = nullptr; | |
CreateStreamOnHGlobal(NULL, TRUE, &istream); | |
// define encoding | |
CLSID clsid; | |
if (dataFormat.compare("bmp") == 0) | |
{ | |
CLSIDFromString(L"{557cf400-1a04-11d3-9a73-0000f81ef32e}", &clsid); | |
Gdiplus::Status status = tile->Save(istream, &clsid, NULL); | |
if (status != Gdiplus::Status::Ok) | |
return false; | |
} | |
else if (dataFormat.compare("jpg") == 0) | |
{ | |
CLSIDFromString(L"{557cf401-1a04-11d3-9a73-0000f81ef32e}", &clsid); | |
// Before we call Image::Save, we must initialize an EncoderParameters object. | |
// The EncoderParameters object has an array of EncoderParameter objects. | |
// In this case, there is only one EncoderParameter object in the array. | |
// The one EncoderParameter object has an array of values. | |
// In this case, there is only one value (of type ULONG) | |
Gdiplus::EncoderParameters encoderParameters; | |
encoderParameters.Count = 1; | |
encoderParameters.Parameter[0].Guid = Gdiplus::EncoderQuality; | |
encoderParameters.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; | |
encoderParameters.Parameter[0].NumberOfValues = 1; | |
// Save the image as a JPEG with quality level 0. | |
int quality = 70; | |
encoderParameters.Parameter[0].Value = &quality; | |
Gdiplus::Status status = tile->Save(istream, &clsid, &encoderParameters); | |
if (status != Gdiplus::Status::Ok) | |
return false; | |
} | |
else if (dataFormat.compare("png") == 0) | |
{ | |
CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid); | |
Gdiplus::Status status = tile->Save(istream, &clsid, NULL); | |
if (status != Gdiplus::Status::Ok) | |
return false; | |
} | |
// get memory handle associated with istream | |
HGLOBAL hg = NULL; | |
GetHGlobalFromStream(istream, &hg); | |
// copy IStream to buffer | |
int bufsize = GlobalSize(hg); | |
data.resize(bufsize); | |
// lock & unlock memory | |
LPVOID pimage = GlobalLock(hg); | |
if (pimage != 0) | |
memcpy(&data[0], pimage, bufsize); | |
GlobalUnlock(hg); | |
istream->Release(); | |
return true; | |
} | |
int gdiplusDivideImage(Gdiplus::Bitmap* img, const int blockWidth, const int blockHeight, std::vector<std::vector<BYTE>>& blocks) | |
{ | |
int imgWidth = img->GetWidth(); | |
int imgHeight = img->GetHeight(); | |
int bhSize = 0; | |
int bwSize = 0; | |
int blockId = 0; | |
int y0 = 0; | |
while (y0 < imgHeight) | |
{ | |
bhSize = ((y0 + blockHeight) > imgHeight) * (blockHeight - (y0 + blockHeight - imgHeight)) + ((y0 + blockHeight) <= imgHeight) * blockHeight; | |
int x0 = 0; | |
while (x0 < imgWidth) | |
{ | |
bwSize = ((x0 + blockWidth) > imgWidth) * (blockWidth - (x0 + blockWidth - imgWidth)) + ((x0 + blockWidth) <= imgWidth) * blockWidth; | |
blockId += 1; | |
Gdiplus::Bitmap* bmp = img->Clone(x0, y0, bwSize, bhSize, PixelFormat24bppRGB); | |
// encode block | |
std::vector<BYTE> pngbytes; | |
// encode block | |
if (!(saveToMemory(bmp, pngbytes, "png"))) | |
{ | |
std::cout << "Cannot save block_" << std::to_string(x0) << "_" << std::to_string(y0) << "to png" << std::endl; | |
return EXIT_FAILURE; | |
} | |
// update starting coordinates | |
x0 = x0 + blockWidth; | |
// append to vec | |
blocks.push_back(pngbytes); | |
} | |
// update starting coordinates | |
y0 = y0 + blockHeight; | |
} | |
return EXIT_SUCCESS; | |
} | |
int main() | |
{ | |
// initilialize GDI+ | |
CoInitialize(NULL); | |
ULONG_PTR token; | |
Gdiplus::GdiplusStartupInput tmp; | |
Gdiplus::GdiplusStartup(&token, &tmp, NULL); | |
// init vars | |
std::vector<std::vector<BYTE>> imgblocks; | |
// load img | |
Gdiplus::Bitmap* bitmap = Gdiplus::Bitmap::FromFile(L"Lenna.png"); | |
// divide img | |
int divstatus = gdiplusDivideImage(bitmap, blockw, blockh, imgblocks); | |
// create repository for blocks | |
if (!CreateDirectory(L"blocksFolder", NULL)) | |
{ | |
std::wcout << "Directory Error: Cannot create directory for blocks." << std::endl; | |
return 1; | |
} | |
// save blocks | |
for (int j = 0; j < imgblocks.size(); j++) | |
{ | |
std::string blockId = std::to_string(j); | |
std::string blockImgName = "blocksFolder/block#" + blockId + ".png"; | |
// write from memory to file for testing: | |
std::ofstream fout(blockImgName, std::ios::binary); | |
fout.write((char*)imgblocks[j].data(), imgblocks[j].size()); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment