Skip to content

Instantly share code, notes, and snippets.

@heatblazer
Last active June 8, 2023 09:44
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 heatblazer/0d726a4c64c48bb1384e22f0d4a753ec to your computer and use it in GitHub Desktop.
Save heatblazer/0d726a4c64c48bb1384e22f0d4a753ec to your computer and use it in GitHub Desktop.
zigzaging of NxN matrix
#include <iostream>
/**
*
*Entropy coding is a special form of lossless data compression.
*It involves arranging the image components in a "zigzag" order employing run-length encoding (RLE) algorithm that groups similar frequencies together, inserting length coding zeros, and then using Huffman coding on what is left.
The JPEG standard also allows, but does not require, decoders to support the use of arithmetic coding, which is mathematically superior to Huffman coding.
However, this feature has rarely been used, as it was historically covered by patents requiring royalty-bearing licenses, and because it is slower to encode and decode compared to Huffman coding.
Arithmetic coding typically makes files about 5–7% smaller.
The previous quantized DC coefficient is used to predict the current quantized DC coefficient. The difference between the two is encoded rather than the actual value. The encoding of the 63 quantized AC coefficients does not use such prediction differencing.
as given
[1][2][3][4]
[5][6][7][8]
[9][1][2][3]
[4][5][6][7]
shall output:
[1][2][5][9]
[6][3][4][7]
[1][4][5][2]
[8][3][6][7]
*/
//define debug with size for the local array for debugging
//#define DBG 64
//helper get an element at x,y
int getat(const int* mat, const int x, const int y, const int rows)
{
return mat[y * rows + x];
}
#if DBG >= 4
void zigzag(const int* mat, const int ROWS, const int COLS,...)
#else
void zigzag(const int* mat, const int ROWS, const int COLS,int* outmat)
#endif
{
//bitmasking the location and mask for diagonals to bitwise compare
// if you go down for example,
// then after that you mask a diagonal walk to be as (FORWARD | UP)
//and reversed respectively
enum Location {
UP = 0x1,
DOWN = 0x2,
FORWARD = 0x4,
BACKWARD = 0x8
};
int i=0,j=0,h=0;
int location = FORWARD;
int diag = 0; //helper calc of diag i - j or j - i
#ifdef DBG
int outmat[DBG] = {0};
#endif
if (!mat || !outmat) return;
//if not a regular matrix - do nothing - can't zigzag
if (ROWS != COLS || ROWS==0 || COLS==0)
{
return;
}
//loop till x and y does not equal end of matrix
// eg 3x3 to be i == 2 and j == 2
while(i != ROWS-1 || j != ROWS-1)
{
if (location == (BACKWARD | DOWN)) {
diag = i-j;
for(int d =0 ; d < diag; d++)
outmat[h++] = getat(mat, --i, ++j, ROWS);
if (j < COLS-1)
location = DOWN;
else
location = FORWARD;
}
if (location == (FORWARD | UP)) {
diag = j-i;
for(int d=0; d < diag; d++)
outmat[h++] = getat(mat, ++i, --j, ROWS);
if (i+1 >= ROWS)
location = DOWN;
else
location = FORWARD;
}
if (location == DOWN) {
outmat[h++] = getat(mat, i, ++j, ROWS);
if (i < ROWS-1)
location = (FORWARD | UP);
else
location = (BACKWARD | DOWN);
}
if (location == FORWARD) {
//this is the end case scenario
// at the end even if i > j by one and are not equall,
// the while loop will stop after the increment after the
// if (i==0 && j==0) since we will get
// getat(mat, ++i, j) and they become equall
if (i==0 && j==0)
outmat[h++] = getat(mat, i, j, ROWS);
outmat[h++] = getat(mat, ++i, j, ROWS);
if (i <= ROWS-1 && j ==0)
location = (BACKWARD | DOWN);
else
location = (FORWARD | UP);
}
}
#ifdef DBG
for(int i=0; i < ROWS * COLS; i++) {
std::cout << "{" << outmat[i] << "}";
}
std::cout << "\r\n";
#endif
}
// driver test programs ---------------------------------------------//
void drivertest2x2()
{
const int mat2x2[] = {
1,2, //0
3,4 //1
};
int newmat2x2[4] = {0};
zigzag(mat2x2, 2,2, newmat2x2);
for(int i=0; i < 4; i++) {
if (i % 2 == 0) std::cout << "\r\n";
std::cout << "[" << newmat2x2[i] << "]";
}
std::cout << "\r\n---------\r\n";
}
void drivertest3x3()
{
const int mat3x3[] = {
1,2,3, //0
4,5,6, //1
7,8,9 //2
};
int newmat3x3[9] = {0};
zigzag(mat3x3, 3,3, newmat3x3);
for(int i=0; i < 9; i++) {
if (i %3 == 0) std::cout << "\r\n";
std::cout << "[" << newmat3x3[i] << "]";
}
std::cout << "\r\n---------\r\n";
}
void drivertest4x4()
{
const int mat4x4[] = {
1,2,3,4, //0
5,6,7,8, //1
9,1,2,3, //2
4,5,6,7 //3
};
int newmat4x4[16] = {0};
zigzag(mat4x4, 4,4, newmat4x4);
for(int i=0; i < 16; i++) {
if (i % 4 == 0) std::cout << "\r\n";
std::cout << "[" << newmat4x4[i] << "]";
}
std::cout << "\r\n---------\r\n";
}
void drivertest8x8()
{
const int mat8x8[] = {
1,2,3,4,5,6,7,8, //0
0,0,0,0,0,0,0,0, //1
0,0,0,0,0,0,0,0, //2
0,0,0,0,0,0,0,0, //3
0,0,0,0,0,0,0,0, //4
0,0,0,0,0,0,0,0, //5
0,0,0,0,0,6,6,6, //6
0,0,0,0,0,10,11,12 //7
};
int newmat8x8[64] = {0};
zigzag(mat8x8, 8,8, newmat8x8);
for(int i=0; i < 64; i++) {
if (i % 8 == 0) std::cout << "\r\n";
std::cout << "[" << newmat8x8[i] << "]";
}
std::cout << "\r\n----------\r\n";
}
int main(int argc, char** argv)
{
(void)argc; (void)argv;
std::cout << "Begin\r\n";
drivertest2x2();
drivertest3x3();
drivertest4x4();
drivertest8x8();
std::cout << "finish\r\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment