Skip to content

Instantly share code, notes, and snippets.

@SuperKogito
Created October 3, 2020 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SuperKogito/434ac8489f8b99aa10377966180e3a35 to your computer and use it in GitHub Desktop.
Save SuperKogito/434ac8489f8b99aa10377966180e3a35 to your computer and use it in GitHub Desktop.
#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