Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
mcychan authored Mar 22, 2024
1 parent eb3a2de commit fc48572
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 40 deletions.
82 changes: 46 additions & 36 deletions nQuantCpp/GifWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,53 @@

namespace GifEncode
{
const int UintBytes = sizeof(int);
const int UintBytes = sizeof(long);

GifWriter::GifWriter(const wstring& destPath, const bool hasAlpha, const int count, const long delay, const bool loop)
GifWriter::GifWriter(const wstring& destPath, const bool hasAlpha, const long delay, const bool loop)
{
_destPath = destPath;
_hasAlpha = hasAlpha;
_delay = delay;
_loop = loop;
}

static GUID GetEncoder()
{
const CLSID gifEncoderClsId = { 0x557cf402, 0x1a04, 0x11d3,{ 0x9a,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e } };
return gifEncoderClsId;
}

static void SetFrameDelay(Bitmap* pFirstBitmap, PropertyItem& frameDelay, vector<long>& frameDelays)
{
// PropertyItem for the frame delay (apparently, no other way to create a fresh instance).
_frameDelay = make_unique<PropertyItem>();
_frameDelay->id = PropertyTagFrameDelay;
_frameDelay->type = PropertyTagTypeLong;
frameDelay.id = PropertyTagFrameDelay;
frameDelay.type = PropertyTagTypeLong;
// Length of the value in bytes.
_frameDelay->length = (count + 1) * UintBytes;
frameDelay.length = frameDelays.size() * UintBytes;
// The value is an array of 4-byte entries: one per frame.
// Every entry is the frame delay in 1/100-s of a second, in little endian.
// E.g., here, we're setting the delay of every frame to 1 second.
frameDelay.value = frameDelays.data();
pFirstBitmap->SetPropertyItem(&frameDelay);
}

// E.g., here, we're setting the delay of every frame.
_frameDelays = make_unique<long[]>(count + 1);
for (int j = 0; j < count + 1; ++j)
_frameDelays[j] = delay / 10;
_frameDelay->value = _frameDelays.get();
static void SetLoop(Bitmap* pFirstBitmap, PropertyItem& loopPropertyItem, const bool loop)
{
if (!loop)
return;

// PropertyItem for the number of animation loops.
_loopPropertyItem = make_unique<PropertyItem>();
_loopPropertyItem->id = PropertyTagLoopCount;
_loopPropertyItem->type = PropertyTagTypeShort;
_loopPropertyItem->length = 2;
loopPropertyItem.id = PropertyTagLoopCount;
loopPropertyItem.type = PropertyTagTypeShort;
loopPropertyItem.length = 2;
// 0 means to animate forever.
short sValue = 0;
_loopPropertyItem->value = &sValue;
}

static GUID GetEncoder()
{
const CLSID gifEncoderClsId = { 0x557cf402, 0x1a04, 0x11d3,{ 0x9a,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e } };
return gifEncoderClsId;
loopPropertyItem.value = &sValue;
pFirstBitmap->SetPropertyItem(&loopPropertyItem);
}

Status GifWriter::AddImages(vector<shared_ptr<Bitmap> >& bitmaps)
{
auto firstBitmap = bitmaps[0];
auto& pFirstBitmap = bitmaps[0];
auto gifGUID = GetEncoder();

// Params of the first frame.
Expand All @@ -53,24 +60,27 @@ namespace GifEncode
encoderParams.Parameter[0].Guid = EncoderSaveFlag;
encoderParams.Parameter[0].NumberOfValues = 1;
encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
long firstValue = EncoderValueMultiFrame;
encoderParams.Parameter[0].Value = &firstValue;
firstBitmap->SetPropertyItem(_frameDelay.get());
if (_loop)
firstBitmap->SetPropertyItem(_loopPropertyItem.get());
firstBitmap->Save(_destPath.c_str(), &gifGUID, &encoderParams);
auto valueMultiFrame = EncoderValueMultiFrame;
encoderParams.Parameter[0].Value = &valueMultiFrame;

PropertyItem frameDelay;
vector<long> frameDelays(bitmaps.size(), _delay / 10);
SetFrameDelay(pFirstBitmap.get(), frameDelay, frameDelays);
PropertyItem loopPropertyItem;
SetLoop(pFirstBitmap.get(), loopPropertyItem, _loop);
pFirstBitmap->Save(_destPath.c_str(), &gifGUID, &encoderParams);

// Params of other frames.
firstValue = EncoderValueFrameDimensionTime;
encoderParams.Parameter[0].Value = &firstValue;
auto valueFrameDimensionTime = EncoderValueFrameDimensionTime;
encoderParams.Parameter[0].Value = &valueFrameDimensionTime;
Status status;
for (int i = 1; i < bitmaps.size(); ++i)
status = firstBitmap->SaveAdd(bitmaps[i].get(), &encoderParams);
status = pFirstBitmap->SaveAdd(bitmaps[i].get(), &encoderParams);

// Params for the finalizing call.
encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
firstValue = EncoderValueFlush;
encoderParams.Parameter[0].Value = &firstValue;
return firstBitmap->SaveAdd(&encoderParams);
auto valueFlush = EncoderValueFlush;
encoderParams.Parameter[0].Value = &valueFlush;
return pFirstBitmap->SaveAdd(&encoderParams);
}
}
5 changes: 2 additions & 3 deletions nQuantCpp/GifWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ namespace GifEncode
private:
bool _hasAlpha, _loop;
wstring _destPath;
unique_ptr<long[]> _frameDelays;
unique_ptr<PropertyItem> _frameDelay, _loopPropertyItem;
long _delay;

public:
GifWriter(const wstring& destPath, const bool hasAlpha, const int count = 1, const long delay = 850, const bool loop = true);
GifWriter(const wstring& destPath, const bool hasAlpha, const long delay = 850, const bool loop = true);
Status AddImages(vector<shared_ptr<Bitmap> >& bitmaps);
};
}
2 changes: 1 addition & 1 deletion nQuantCpp/nQuantCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void OutputImages(const fs::path& sourceDir, wstring& targetDir, const UINT& nMa
targetDir = fileExists(targetDir) ? fs::canonical(fs::path(targetDir)) : fs::current_path();
auto destPath = targetDir + L"/" + fileName + L"-";
destPath += L"PNNLAB+quant.gif";
GifEncode::GifWriter gifWriter(destPath, pGAq->hasAlpha(), 1, abs(delay));
GifEncode::GifWriter gifWriter(destPath, pGAq->hasAlpha(), abs(delay));
auto status = gifWriter.AddImages(pDests);
if (status == Status::Ok)
tcout << L"Converted image: " << destPath << endl;
Expand Down
Binary file modified nQuantCpp/nQuantCpp.rc
Binary file not shown.

0 comments on commit fc48572

Please sign in to comment.