GIF LZW decompression - c++

I am trying to implement a simple Gif-Reader in c++.
I currently stuck with decompressing the Imagedata.
If an image includes a Clear Code my decompression algorithm fails.
After the Clear Code I rebuild the CodeTable reset the CodeSize to MinimumLzwCodeSize + 1.
Then I read the next code and add it to the indexstream. The problem is that after clearing, the next codes include values greater than the size of the current codetable.
For example the sample file from wikipedia: rotating-earth.gif has a code value of 262 but the GlobalColorTable is only 256. How do I handle this?
I implemented the lzw decompression according to gif spec..
here is the main code part of decompressing:
int prevCode = GetCode(ptr, offset, codeSize);
codeStream.push_back(prevCode);
while (true)
{
auto code = GetCode(ptr, offset, codeSize);
//
//Clear code
//
if (code == IndexClearCode)
{
//reset codesize
codeSize = blockA.LZWMinimumCodeSize + 1;
currentNodeValue = pow(2, codeSize) - 1;
//reset codeTable
codeTable.resize(colorTable.size() + 2);
//read next code
prevCode = GetCode(ptr, offset, codeSize);
codeStream.push_back(prevCode);
continue;
}
else if (code == IndexEndOfInformationCode)
break;
//exists in dictionary
if (codeTable.size() > code)
{
if (prevCode >= codeTable.size())
{
prevCode = code;
continue;
}
for (auto c : codeTable[code])
codeStream.push_back(c);
newEntry = codeTable[prevCode];
newEntry.push_back(codeTable[code][0]);
codeTable.push_back(newEntry);
prevCode = code;
if (codeTable.size() - 1 == currentNodeValue)
{
codeSize++;
currentNodeValue = pow(2, codeSize) - 1;
}
}
else
{
if (prevCode >= codeTable.size())
{
prevCode = code;
continue;
}
newEntry = codeTable[prevCode];
newEntry.push_back(codeTable[prevCode][0]);
for (auto c : newEntry)
codeStream.push_back(c);
codeTable.push_back(newEntry);
prevCode = codeTable.size() - 1;
if (codeTable.size() - 1 == currentNodeValue)
{
codeSize++;
currentNodeValue = pow(2, codeSize) - 1;
}
}
}

Found the solution.
It is called Deferred clear code. So when I check if the codeSize needs to be incremented I also need to check if the codeSize is already max(12), as it is possible to to get codes that are of the maximum Code Size. See spec-gif89a.txt.
if (codeTable.size() - 1 == currentNodeValue && codeSize < 12)
{
codeSize++;
currentNodeValue = (1 << codeSize) - 1;
}

Related

How to allow my C++ code to update variables?

I'm new to coding and C++.
The code below is meant to monitor a magswitch and a status led on another controller. The code needs to run once the magswitch pin goes high (this works).
The additional code for pulseIn, is what I hope to use to monitor different flash rates of the led when I get the code working. For now I'm just looking for the state variable to update with the if and else if statements.
When I toggle the statusPin, the code picks up the changing state, but I cannot get it to update the "state" and "statuspinstate" variables.
The statuspinstate variable shows as 1, even though it is initialized as 0.
I inserted all the serial prints to try and see where things are going wrong.
This is the serial print when "statusPin" is LOW:
statuspinstate: 0
rate1: 2147483647
period: 0.00
rate2: 0
ontime: 0
offtime: 0
state: 0
statepinstatus: 1
This is the serial print when "statusPin" is HIGH
statuspinstate: 1
rate1: 2147483647
period: 0.00
rate2: 0
ontime: 0
offtime: 0
state: 0
statepinstatus: 1
Code:
const int statusPin = 19; //Reads status led
const int magSwitch = 22; //Magswitch to detect movement
int ontime,offtime,rate1,rate2;
float freq,period;
volatile unsigned int state =0;
volatile unsigned int statuspinstate = 0;
void setup()
{
pinMode(statusPin, INPUT); //input from controller
pinMode(magSwitch, INPUT);
Serial.begin(115200);
}
void loop()
{
while (digitalRead(magSwitch) == LOW) {
}
{
statuspinstate = digitalRead(statusPin);
ontime = pulseIn(statusPin,HIGH);
offtime = pulseIn(statusPin,LOW);
period = ontime+offtime;
rate1 = (ontime/period); //future use
rate2 = (offtime); //future use
Serial.println(String("statuspinstate ") + (digitalRead(statusPin))); //all serial print is debug info
Serial.println(String("rate1: ") + (rate1));
Serial.println(String("period: ") + (period));
Serial.println(String("rate2: ") + (rate2));
Serial.println(String("ontime: ") + (ontime));
Serial.println(String("offtime: ") + (offtime));
delay(500);
}
if ((ontime) != 0)
state = period;
else if (statuspinstate = 1)
state = 9999;
else if (statuspinstate = 0);
state = 0;
Serial.println(String("state: ") + (state));
Serial.println(String("statepinstatus: ") + (statuspinstate));
statuspinstate = 0; //return statuspinstate to zero
}
Look at your conditional, with proper indentation (do get a text editor that can indent your code for you):
if ((ontime) != 0)
state = period;
else if (statuspinstate = 1)
state = 9999;
else if (statuspinstate = 0);
state = 0;
We know that ontime is zero, so the second condition is tried next.
Now, statuspinstate = 1 is an assignment, not a comparison, and its value is "truth-y" so you take that branch.
Next, the stray semicolon in if (statuspinstate = 0); (which is also an assignment condition, but not evaluated) makes state = 0 unconditional.
So every time ontime is zero, you end up executing statuspinstate = 1 and state = 0.
What you probably want is
if (ontime != 0)
state = period;
else if (statuspinstate == 1)
state = 9999;
else if (statuspinstate == 0)
state = 0;

Encountering issues with std::mutex and std::thread

I am encountering issues with both std::thread and std::mutex, unable to get both to play nicely with each other. I've been pulling my hair out over this for the past few hours and just cannot make any progress whatsoever. I believe it is out of my skill area. The code is just below:
void GekkoFyre::TuiHangouts::gui_userRosterListNav(std::shared_ptr<WINDOW> display,
std::vector<const char *> userList,
const short &menuItem)
{
while (rosterEnabled) {
for (short i = 0; i < totalMenuItems; ++i) {
short diff = (menuItem - i);
if (i < numMenuItems) {
if (i == menuItem) {
size_t msgLen = strlen(userList.at(i));
size_t l = 0;
if (msgLen > subMaxX) {
for (l = subMaxX; l < msgLen; ++l) {
// Scroll the message from left to right, then vice versa, so that it fits within
// the designated window.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
rosterListMutex.lock();
wattron(usrSubWin.get(), A_REVERSE); // Highlight selection
const char *msg = userList.at(i);
mvwaddstr(usrSubWin.get(), i, 0, &msg[(msgLen - l)]);
wrefresh(usrSubWin.get());
touchwin(usrSubWin.get());
rosterListMutex.unlock();
}
} else {
rosterListMutex.lock();
wattron(usrSubWin.get(), A_REVERSE); // Highlight selection
mvwaddstr(usrSubWin.get(), i, 0, userList.at(i));
wrefresh(usrSubWin.get());
touchwin(usrSubWin.get());
rosterListMutex.unlock();
}
}
wattroff(usrSubWin.get(), A_REVERSE); // Remove highlight
if ((i + 1) < numMenuItems) {
mvwaddstr(usrSubWin.get(), (i + 1), 0, userList.at((i + 1)));
}
} else if (diff < (totalMenuItems - numMenuItems) && diff > 0) {
// Allow the scrolling of a username list, from downwards and then back upwards, so that
// the user may see the list in its entirety.
wclear(usrSubWin.get());
int pos = 0;
for (short c = diff; c < (numMenuItems + diff); ++c) {
++pos;
mvwaddstr(usrSubWin.get(), pos, 0, userList.at(c));
}
pos = 0;
break;
}
}
rosterListMutex.lock();
wattroff(usrSubWin.get(), A_REVERSE); // Remove highlight
touchwin(usrSubWin.get());
wrefresh(usrSubWin.get());
wrefresh(display.get());
rosterListMutex.unlock();
}
}
I am trying to display a list of users to the left of a chat window in NCurses, as can be seen in [ 1 ] below, albeit without any users present in said screenshot. I want to keep my privacy :) What happens is that as you scroll down the list, flickering begins to occur back and forth between two usernames after scrolling past just a few. They keep repeatedly selecting each other, just over and over. I believe this is reason of the threads not syncing up properly. The function is implemented as so:
[ 1 ] - http://imgur.com/ZZlFHg2
#define WIDGET_USERS_LIST 1
short menuItem = 0;
int ch = 0;
int curr_widget = 0;
std::thread rosterListNav1(&GekkoFyre::TuiHangouts::gui_userRosterListNav, this, userListWin, rosterFormatted, menuItem);
rosterListNav1.detach();
while ((ch = wgetch(display.get())) != KEY_F(12)) {
switch (ch) {
case KEY_DOWN:
if (curr_widget == WIDGET_USERS_LIST && rosterEnabled) {
++menuItem;
if (menuItem > totalMenuItems - 1) {
menuItem = 0;
}
}
break;
case KEY_UP:
if (curr_widget == WIDGET_USERS_LIST && rosterEnabled) {
--menuItem;
if (menuItem < 0) {
menuItem = totalMenuItems - 1;
}
}
}
std::thread rosterListNav2(&GekkoFyre::TuiHangouts::gui_userRosterListNav, this, userListWin, rosterFormatted, menuItem);
rosterListNav2.detach();
}
Any help on this issue would be dearly appreciated, and I believe I have placed the std::mutex's in the right areas. I am really stumped with this problem. Also beware that while I know a few tricks of the trade, I am entirely self-taught. Some of the nomenclature that is normal to programmers who have gone through university is completely unintelligible to me.

optimize octree octant_determination function in c++

I am building a spacial octree. In order to determine in which branch/octant a certain point (x,y,z) should be placed, I use this function:
if (x>x_centre) {
xsign = 1;
}
else {
xsign = 0;
}
if (y>y_centre) {
ysign = 1;
}
else {
ysign = 0;
}
if (z>z_centre) {
zsign = 1;
}
else {
zsign = 0;
}
return xsign + 2*ysign + 4*zsign;
It returns a number between 0 and 7 unique for every octant. It turns out this snippet is called a big many times. It gets quite time consuming when building large trees.
Is there any easy way to speed this proces up?
This allready gives a 30 percent speed up:
xsign = x>x_centre;
ysign = y>y_centre;
zsign = z>y_centre;
return xsign + 2*ysign + 4*zsign;
Any other tips?

How to find out the next time when the clock will be adjusted for Daylight Saving?

I'm curious, if there's any way to find out the UTC date/time when the next Daylight Saving adjustment will take place?
Something akin to what Windows reports (see circled):
This information is provided in Windows by the EnumDynamicTimeZoneInformation function.
See http://msdn.microsoft.com/en-us/library/windows/desktop/hh706893%28v=vs.85%29.aspx
There is a database that has code and data: http://www.iana.org/time-zones
I don't think there's a specific API for this. I would just do a binary search, using localtime (and maybe time and mktime) from <ctime> (C++) or <time.h> (C).
A basic approach is to scan ahead three months at a time until the tm_isdst flag in the returned data structure is flipped. Then you can start binary searching between the last two two dates to figure out exactly when it flips.
See http://www.cplusplus.com/reference/ctime/tm/ for reference material.
I appreciate all your replies. And, yes, indeed I was asking about a WinAPI for Windows.
I did more research and came up with the following method that does what I wanted. It uses C++ and MFC's COleDateTime for easier date/time calculations. Other than that it's just C++ and WinAPIs. Please check if I understood the documentation for the DYNAMIC_TIME_ZONE_INFORMATION correctly. Here's the code:
int GetNextDaylightSavingAdjustmentTime(SYSTEMTIME* pOutDtNextDST_Local, int* pnOutAdjustmentMin)
{
//Get next time when DST adjustment will take place
//'pOutDtNextDST_Local' = if not NULL, receives the (local) time when next DST adjustment will take place
//'pnOutAdjustmentMin' = if not NULL, receives the amount of adjustment in minutes
//RETURN:
// = 1 if got the time, or
// = 0 if DST is not used
// = -1 if error (check GetLastError() for info)
int nOSError = NO_ERROR;
//Load API dynamically (in case of Windows XP)
BOOL (WINAPI *pfnGetDynamicTimeZoneInformation)(PDYNAMIC_TIME_ZONE_INFORMATION);
(FARPROC&)pfnGetDynamicTimeZoneInformation =
::GetProcAddress(::GetModuleHandle(L"Kernel32.dll"), "GetDynamicTimeZoneInformation");
DWORD tzID;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
int nBiasDaylight;
//Use newer API if possible
if(pfnGetDynamicTimeZoneInformation)
{
DYNAMIC_TIME_ZONE_INFORMATION dtzi = {0};
tzID = pfnGetDynamicTimeZoneInformation(&dtzi);
StandardDate = dtzi.StandardDate;
DaylightDate = dtzi.DaylightDate;
nBiasDaylight = dtzi.DaylightBias;
}
else
{
//Older API
TIME_ZONE_INFORMATION tzi = {0};
tzID = GetTimeZoneInformation(&tzi);
StandardDate = tzi.StandardDate;
DaylightDate = tzi.DaylightDate;
nBiasDaylight = tzi.DaylightBias;
}
int nRes = -1;
int nAdjMins = 0;
SYSTEMTIME stDstChange;
memset(&stDstChange, 0, sizeof(stDstChange));
SYSTEMTIME stDst;
if(tzID == TIME_ZONE_ID_STANDARD ||
tzID == TIME_ZONE_ID_DAYLIGHT)
{
stDst = tzID != TIME_ZONE_ID_DAYLIGHT ? DaylightDate : StandardDate;
if(stDst.wMonth >= 1 &&
stDst.wMonth <= 12 &&
stDst.wDay >= 1 &&
stDst.wDayOfWeek >= 0 &&
stDst.wDayOfWeek <= 6)
{
//Get adjustment bias
nAdjMins = tzID != TIME_ZONE_ID_DAYLIGHT ? -nBiasDaylight : nBiasDaylight;
if(stDst.wYear == 0)
{
//Relative date
SYSTEMTIME stLocal;
::GetLocalTime(&stLocal);
//Begin from the 1st day of the month &
//make sure that the date is in the future
COleDateTime dt;
for(int nYear = stLocal.wYear;; nYear++)
{
dt.SetDateTime(nYear, stDst.wMonth, 1, stDst.wHour, stDst.wMinute, stDst.wSecond);
if(dt > COleDateTime::GetCurrentTime())
break;
}
int nRequiredWeek = stDst.wDay >= 1 && stDst.wDay <= 5 ? stDst.wDay : 5;
for(int nCntDOW = 1;;)
{
//0=Sunday, 1=Monday; 2=Tuesday; 3=Wednesday; 4=Thursday; 5=Friday; 6=Saturday
int dow = dt.GetDayOfWeek() - 1;
ASSERT(dow >= 0 && dow <= 6);
if(dow == stDst.wDayOfWeek)
{
if(nCntDOW >= nRequiredWeek)
{
//Stop
break;
}
else
{
nCntDOW++;
}
}
//Go to next day
dt += COleDateTimeSpan(1, 0, 0, 0);
}
//Convert back to system time
if(dt.GetAsSystemTime(stDstChange))
{
//Success
nRes = 1;
}
else
{
//Failed
nOSError = ERROR_INVALID_FUNCTION;
ASSERT(NULL);
}
}
else
{
//Absolute date
stDstChange = stDst;
nRes = 1;
}
}
else
{
//Failed
nOSError = ERROR_INVALID_PARAMETER;
ASSERT(NULL);
}
}
else
{
//DST is not used
if(tzID == TIME_ZONE_ID_UNKNOWN)
{
nRes = 0;
}
else
{
//Error
nOSError = ERROR_INVALID_DATA;
ASSERT(NULL);
}
}
if(pOutDtNextDST_Local)
*pOutDtNextDST_Local = stDstChange;
if(pnOutAdjustmentMin)
*pnOutAdjustmentMin = nAdjMins;
::SetLastError(nOSError);
return nRes;
}
PS. And scratch my request for the UTC time. As I learned, it is easier to deal with local time in this situation.

playing created Audio-Data has noise and periodical clicking in sound

I write an application, which plays a sound getting from Hardware (like a ring buffer filled with a sinus wave with certain frequency). Everything works fine, and I can playback the created sound correctly except a periodical clicking (maybe at the end of buffer?) and noise.
I initialize and run the Buffer:
void Audiooutput::InitializeAudioParameters()
{
Audio_DataWritten = 0;
Audio_fragments = 4;
Audio_channels = 2;
Audio_BufferSize = 256;
Audio_Samplerate = 8000;
Audio_ResamplingFactor = 1;
Audio_Framesize = 2;
// (SND_PCM_FORMAT_S16_LE / 8);
Audio_frames = Audio_BufferSize / Audio_Framesize * Audio_fragments;
snd_pcm_uframes_t size;
err = snd_pcm_hw_params_any(pcmPlaybackHandle, hw_params);
err = snd_pcm_hw_params_set_rate_resample(pcmPlaybackHandle, hw_params, 1);
// qDebug()<<a1.sprintf(" % d \t snd_pcm_hw_params_set_rate: %s",Audio_Samplerate,snd_strerror(err));
err =
snd_pcm_hw_params_set_format(pcmPlaybackHandle, hw_params,
SND_PCM_FORMAT_S16_LE);
err =
snd_pcm_hw_params_set_channels(pcmPlaybackHandle, hw_params,
Audio_channels);
err = snd_pcm_hw_params_set_rate_near(pcmPlaybackHandle, hw_params, &Audio_Samplerate, 0);
// qDebug()<<a1.sprintf(" % d \t snd_pcm_hw_params_set_rate: %s",Audio_Samplerate,snd_strerror(err));
if ((err =
snd_pcm_hw_params_set_periods_near(pcmPlaybackHandle, hw_params,
&Audio_fragments, 0)) < 0) {
qDebug() << a1.sprintf("Error setting # fragments to %d: %s\n",
Audio_fragments, snd_strerror(err));
} else
qDebug() << a1.sprintf("setting # fragments to %d: %s\n",
Audio_fragments, snd_strerror(err));
err = snd_pcm_hw_params_get_buffer_size(hw_params, &size);
if ((err =
snd_pcm_hw_params_set_buffer_size_near(pcmPlaybackHandle,
hw_params,
&Audio_frames)) < 0) {
qDebug() << a1.
sprintf("Error setting buffer_size %d frames: %s",
Audio_frames, snd_strerror(err));
} else
qDebug() << a1.sprintf("setting Buffersize to %d --> %d: %s\n",
Audio_BufferSize, Audio_frames,
snd_strerror(err));
Audio_BufferSize = Audio_frames;
if ((err = snd_pcm_hw_params(pcmPlaybackHandle, hw_params)) < 0) {
qDebug() << a1.sprintf("Error setting HW params: %s",
snd_strerror(err));
}
Q_ASSERT(err >= 0);
}
void Audiooutput::ProduceAudioOutput(int n, int mmodes, int totalMModeGates,
short *sinusValue, short *cosinusValue)
{
for (int audioSample = 0; audioSample < n;
audioSample += Audio_ResamplingFactor) {
currentposition =
(int)(m_Audio.generalPos % (Audio_BufferSize / 2));
if (currentposition == 0) {
QueueAudioBuffer();
m_Audio.currentPos = 0;
}
m_Audio.generalPos++;
AudioData[currentposition * 2] =
(short)(sinusValue[audioSample]);
AudioData[currentposition * 2 + 1] =
(short)(cosinusValue[audioSample]);
}
}
void Audiooutput::QueueAudioBuffer()
{
snd_pcm_prepare(pcmPlaybackHandle);
Audio_DataWritten +=
snd_pcm_writei(pcmPlaybackHandle, AudioData, Audio_BufferSize);
}
Changing the audiobuffer size or fragments changes also the clicking period.
Can anyone help me with this issue ?
I checked also the first and Last Values. Thy are always difference.
OS: Ubuntu 11
more detail.
the count of received data is dynamically, and changes depend of different parameters. But I play always a certain part e.g. 128 values or 256 or 512....
// I get the Audiodata from a hardware (in a Timerloop)
audiobuffersize = 256;
short *AudioData = new short[256];
int generalAudioSample = 0;
void CollectDataFromHw()
{
...
int n = 0;
n = GetData(buf1,buf2);//buf1 = new short[MAX_SHRT]
if(n > 0)
FillAudioBuffer(n,buf1,buf2)
...
}
-------------------------------------------
void FillAudioBuffer(int n, short*buf1, short*buf2)
{
for(int audioSample = 0;audioSample < n; audioSample++){
iCurrentAudioSample = (int)(generalAudioSample % (audiobuffersize/2));
if(iCurrentAudioSample == 0) {
snd_pcm_writei(pcmPlaybackHandle,AudioData,audiobuffersize );
memset(AudioData,0x00,audiobuffersize*sizeof(short));
}
generalAudioSample++;
AudioData[iCurrentAudioSample * 2] = (short)(buf1[audioSample];
AudioData[iCurrentAudioSample * 2 +1] = (short)(buf2[audioSample];
}
}
I changed the audiobuffersize also. If I set it to a bigger size, I have some Echo additional to clicks.
any Idea ?
//-----------------------
the Problem is
snd_pcm_prepare(pcmPlaybackHandle);
every call of this function produce a click in sound !
Can't test the source code, but I think that the high-frequency clicks you hear are discontinuities in the sound wave. You have to assure that looping period (or, buffer size) is multiple of wave period.
Check if first and last value of buffer are almost the same (+/- 1, for example). Their distance determines the amplitude of the unwanted click.
solved
buffer has been played several times before it was filled with the data.
stupid error in the code.missing a parantez --> audio_buffersize/2 <--
and therefore the result was very often if(iCurrentAudioSample == 0) true !!!!!
iCurrentAudioSample = (int)(generalAudioSample % (audio_buffersize/2));
if(iCurrentAudioSample == 0)
{
writetoaudioStream(audiobuffer);
}