Skip to content

Instantly share code, notes, and snippets.

@hex007
Last active November 18, 2017 03:12
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 hex007/fc4396de31e0c9e04a511869038d889c to your computer and use it in GitHub Desktop.
Save hex007/fc4396de31e0c9e04a511869038d889c to your computer and use it in GitHub Desktop.
Program to test Pi's overscan, aspect ratio, and color settings
/*
Raspberry Pi SDL2 image test with gradient and boundry.
- use keyboard buttons to change frames
- press F4 to exit
- in the boundaries frame, the entire boundry (white) should be visible and as outside as possible
to ensure overscan settings is optimal
- in the boundaries frame, the central rectangle should be a perfect square
- in the next frame, the circle should be perfect circle to ensure proper aspect ratio
To test:
wget -O tests.cpp "https://gist.githubusercontent.com/hex007/fc4396de31e0c9e04a511869038d889c/raw"
g++ -std=c++11 -lSDL2 -o tests tests.cpp
./tests
Changelog:
rev 1) initial commit
rev 2) Added documentation and instructions
rev 3) Added more gradients
rev 4) Removed abs ambiguity
*/
#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <SDL2/SDL.h>
using namespace std;
typedef void (*draw_func) ();
struct rgb { unsigned char R, G, B; };
const int sq_percent = 50; // Should be < 100
const int bytes = 3;
int func_c = 0;
int width = 0;
int height = 0;
unsigned char* frame;
SDL_Renderer *renderer;
SDL_Texture *texture;
SDL_Window *window;
void loadDisplayDimentions()
{
SDL_DisplayMode dispMode;
SDL_GetDesktopDisplayMode(0, &dispMode);
width = dispMode.w;
height = dispMode.h;
printf("Width : %d, Height : %d\n", width, height);
}
void drawBoundry()
{
int c = sq_percent * min(height, width) / 100;
int c_w = width / 2;
int c_h = height / 2;
for (int j = 0; j < height; j++)
{
int d1 = j * width * bytes; // first column
int d2 = d1 + (width-1) * bytes; // last column
int d3 = (j * width + (width - c)/2) * bytes;
int d4 = (j * width + (width + c)/2) * bytes;
frame[d1 + 0] = frame[d1 + 1] = frame[d1 + 2] = 255;
frame[d2 + 0] = frame[d2 + 1] = frame[d2 + 2] = 255;
frame[d3 + 0] = frame[d3 + 1] = frame[d3 + 2] = 255;
frame[d4 + 0] = frame[d4 + 1] = frame[d4 + 2] = 255;
}
for (int i = 0; i < width; i++)
{
int d1 = i * bytes; // first row
int d2 = d1 + width * (height-1) * bytes; // last row
int d3 = (width * (height - c)/2 + i) * bytes;
int d4 = (width * (height + c)/2 + i) * bytes;
frame[d1 + 0] = frame[d1 + 1] = frame[d1 + 2] = 255;
frame[d2 + 0] = frame[d2 + 1] = frame[d2 + 2] = 255;
frame[d3 + 0] = frame[d3 + 1] = frame[d3 + 2] = 255;
frame[d4 + 0] = frame[d4 + 1] = frame[d4 + 2] = 255;
}
}
void drawCircle()
{
int thresh = 25 * min(height, width) / 100; // draw threshold
int r2 = pow(sq_percent * min(height, width) / 200, 2);
int c_w = width / 2;
int c_h = height / 2;
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
if (abs((int) (pow(i - c_w, 2) + pow(j - c_h, 2) - r2)) < thresh)
{
int p = (j*width + i) * bytes;
frame[p + 0] = frame[p + 1] = frame[p + 2] = 255;
}
}
}
}
void drawGradient(rgb tl, rgb tr, rgb bl, rgb br, int w = width, int h = height, int v_offset = 0, int h_offset = 0)
{
int p;
double l, m;
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
p = bytes * ((j + h_offset) * width + (i + v_offset));
l = (double) i / w;
m = (double) j / h;
frame[p + 0] = (1-l)*(1-m)*tl.R + l*(1-m)*tr.R + (1-l)*m*bl.R + l*m*br.R;
frame[p + 1] = (1-l)*(1-m)*tl.G + l*(1-m)*tr.G + (1-l)*m*bl.G + l*m*br.G;
frame[p + 2] = (1-l)*(1-m)*tl.B + l*(1-m)*tr.B + (1-l)*m*bl.B + l*m*br.B;
}
}
}
void drawColor(unsigned char r, unsigned char g, unsigned char b)
{
int total = width * height * bytes;
for (int i = 0; i < total; i = i+3)
{
frame[i + 0] = r;
frame[i + 1] = g;
frame[i + 2] = b;
}
}
void drawR() { drawColor(255, 0 , 0 ); }
void drawG() { drawColor(0 , 255, 0 ); }
void drawB() { drawColor(0 , 0 , 255); }
void drawC() { drawColor(0 , 255, 255); }
void drawM() { drawColor(255, 0 , 255); }
void drawY() { drawColor(255, 255, 0 ); }
void drawK() { drawColor(0 , 0 , 0 ); }
void drawW() { drawColor(255, 255, 255); }
void drawRainPi() { drawGradient({255,0,0}, {255,255,0}, {0,0,255}, {0,255,255}); }
void drawRain00() { drawGradient({255,255,255}, {0,0,0}, {255,255,255}, {0,0,0}); }
void drawRain01() { drawGradient({255,255,255}, {255,255,255}, {0,0,0}, {0,0,0}); }
void drawRain02() { drawGradient({255,0,0}, {0,255,0}, {0,0,255}, {255,255,255}); }
void drawRain03() { drawGradient({255,255,0}, {0,255,255}, {255,0,255}, {0,0,0}); }
void drawRainHor()
{
drawGradient({255,0,0}, {255,255,0}, {255,0,0}, {255,255,0}, width/6, height, 0 * width/6, 0);
drawGradient({255,255,0}, {0,255,0}, {255,255,0}, {0,255,0}, width/6, height, 1 * width/6, 0);
drawGradient({0,255,0}, {0,255,255}, {0,255,0}, {0,255,255}, width/6, height, 2 * width/6, 0);
drawGradient({0,255,255}, {0,0,255}, {0,255,255}, {0,0,255}, width/6, height, 3 * width/6, 0);
drawGradient({0,0,255}, {255,0,255}, {0,0,255}, {255,0,255}, width/6, height, 4 * width/6, 0);
drawGradient({255,0,255}, {255,0,0}, {255,0,255}, {255,0,0}, width/6, height, 5 * width/6, 0);
}
void drawRainVer()
{
drawGradient({255,0,0}, {255,255,0}, {255,0,0}, {255,255,0}, width, height/6, 0, 0 * height/6);
drawGradient({255,255,0}, {0,255,0}, {255,255,0}, {0,255,0}, width, height/6, 0, 1 * height/6);
drawGradient({0,255,0}, {0,255,255}, {0,255,0}, {0,255,255}, width, height/6, 0, 2 * height/6);
drawGradient({0,255,255}, {0,0,255}, {0,255,255}, {0,0,255}, width, height/6, 0, 3 * height/6);
drawGradient({0,0,255}, {255,0,255}, {0,0,255}, {255,0,255}, width, height/6, 0, 4 * height/6);
drawGradient({255,0,255}, {255,0,0}, {255,0,255}, {255,0,0}, width, height/6, 0, 5 * height/6);
}
draw_func funcs[] = {
drawRainPi, drawRainHor, drawRainVer,
drawRain00, drawRain01, drawRain02, drawRain03,
drawR, drawG, drawB, drawW, drawC, drawY, drawM, drawK,
drawBoundry, drawCircle
};
void drawFrame()
{
funcs[func_c]();
func_c = (func_c + 1) % (sizeof(funcs)/sizeof(draw_func));
SDL_RenderClear(renderer);
SDL_UpdateTexture(texture, NULL, frame, width * sizeof(char) * bytes);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
int main(int argc, char const *argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) < 0 ) {
cerr << "Unable to initialize SDL" << endl;
exit(1);
}
loadDisplayDimentions();
SDL_CreateWindowAndRenderer(0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP, &window, &renderer);
SDL_ShowCursor(SDL_DISABLE);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, width, height);
frame = new unsigned char[height * width * bytes];
drawFrame();
SDL_Event event;
while(SDL_WaitEvent(&event)) {
if (event.type == SDL_QUIT)
break;
if (event.type != SDL_KEYDOWN)
continue;
if (event.key.keysym.sym == SDLK_F4)
break;
drawFrame();
}
SDL_Quit();
delete[] frame;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment