Linux DRM ( DRI ) Cannot Screen Scrape /dev/fb0 as before with FBDEV - linux

On other Linux machines using the FBDEV drivers ( Raspberry Pi.. etc. ), I could mmap the /dev/fb0 device and directly create a BMP file that saved what was on the screen.
Now, I am trying to do the same thing with DRM on a TI Sitara AM57XX ( Beagleboard X-15 ). The code that used to work with FBDEV is shown below.
This mmap no longer seems to work the DRM. I'm using a very simple Qt5 Application with the Qt platform linuxfb plugin. It draws just fine into /dev/fb0 and shows on the screen properly, however I cannot read back from /dev/fb0 with a memory mapped pointer and have an image of the screen saved to file. It looks garbled like this:
Code:
#ifdef FRAMEBUFFER_CAPTURE
repaint();
QCoreApplication::processEvents();
// Setup framebuffer to desired format
struct fb_var_screeninfo var;
struct fb_fix_screeninfo finfo;
memset(&finfo, 0, sizeof(finfo));
memset(&var, 0, sizeof(var));
/* Get variable screen information. Variable screen information
* gives information like size of the image, bites per pixel,
* virtual size of the image etc. */
int fbFd = open("/dev/fb0", O_RDWR);
int fdRet = ioctl(fbFd, FBIOGET_VSCREENINFO, &var);
if (fdRet < 0) {
qDebug() << "Error opening /dev/fb0!";
close(fbFd);
return -1;
}
if (ioctl(fbFd, FBIOPUT_VSCREENINFO, &var)<0) {
qDebug() << "Error setting up framebuffer!";
close(fbFd);
return -1;
} else {
qDebug() << "Success setting up framebuffer!";
}
//Get fixed screen information
if (ioctl(fbFd, FBIOGET_FSCREENINFO, &finfo) < 0) {
qDebug() << "Error getting fixed screen information!";
close(fbFd);
return -1;
} else {
qDebug() << "Success getting fixed screen information!";
}
//int screensize = var.xres * var.yres * var.bits_per_pixel / 8;
//int screensize = var.yres_virtual * finfo.line_length;
//int screensize = finfo.smem_len;
int screensize = finfo.line_length * var.yres_virtual;
qDebug() << "Framebuffer size is: " << var.xres << var.yres << var.bits_per_pixel << screensize;
int linuxFbWidth = var.xres;
int linuxFbHeight = var.yres;
int location = (var.xoffset) * (var.bits_per_pixel/8) +
(var.yoffset) * finfo.line_length;
// Perform memory mapping of linux framebuffer
char* frameBufferMmapPixels = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbFd, 0);
assert(frameBufferMmapPixels != MAP_FAILED);
QImage toSave((uchar*)frameBufferMmapPixels,linuxFbWidth,linuxFbHeight,QImage::Format_ARGB32);
toSave.save("/usr/bin/test.bmp");
sync();
#endif
Here is the output of the code when it runs:
Success setting up framebuffer!
Success getting fixed screen information!
Framebuffer size is: 800 480 32 1966080
Here is the output of fbset showing the pixel format:
mode "800x480"
geometry 800 480 800 480 32
timings 0 0 0 0 0 0 0
accel true
rgba 8/16,8/8,8/0,8/24
endmode
root#am57xx-evm:~#

finfo.line_length gives the size of the actual physical scan line in bytes. It is not necessarily the same as screen width multiplied by pixel size, as scan lines may be padded.
However the QImage constructor you are using assumes no padding.
If xoffset is zero, it should be possible to construct a QImage directly from the framebuffer data using a constructor with the bytesPerLine argument. Otherwise there are two options:
allocate a separate buffer and copy only the visible portion of each scanline to it
create an image from the entire buffer (including the padding) and then crop it

If you're using DRM, then /dev/fb0 might point to an entirely different buffer (not the currently visible one) or have an different format.
fbdev is really just for old legacy that hasn't been ported DRM/KMS yet
and only has very limited modsetting capabilities.
BTW: which kernel are you using ? hopefully not that ancient and broken TI vendor kernel ...

Related

Can't read frame buffer colormap information using ioctl on raspberry pi

I am working on Raspberry Pi 4, with raspios bullseye-arm-64-lite (version 11).
I want to configure the frame buffer to 8-bits per pixel and use a custom colormap.
I configured the frame buffer to 8-bits per pixel. I could read the fixed and variable information about the frame buffer correctly using ICOTL functions in my C code, but could not read colormap information. While trying to read colormap info, the IOCTL call returns -1.
I added the user to video group and set the frame buffer to 1280x1024 resolution with 8-bit bitdepth using fbset command as follows.
pi#raspberrypi:~ $ fbset -fb /dev/fb0 -g 1280 1024 1280 1024 8
Here is the output of fbset -i command.
pi#raspberrypi:~ $ fbset -i
mode "1280x1024"
geometry 1280 1024 1280 1024 8
timings 0 0 0 0 0 0 0
rgba 8/0,8/0,8/0,0/0
endmode
Frame buffer device information:
Name : BCM2708 FB
Address : 0x3ea87000
Size : 1310720
Type : PACKED PIXELS
Visual : PSEUDOCOLOR
XPanStep : 1
YPanStep : 1
YWrapStep : 0
LineLength : 1280
Accelerator : No
Here is the my C code.
#include <cstdio>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
static struct fb_fix_screeninfo fb_fix;
static struct fb_var_screeninfo fb_var;
static int fb;
static unsigned short ored[256], ogreen[256], oblue[256];
static struct fb_cmap ocmap = { 0, 256, ored, ogreen, oblue };
int main()
{
int fp = open ("/dev/fb0", O_RDWR | O_CLOEXEC);
if (fp < 0){
printf("Error : Can not open framebuffer device/n");
return -1;
}
// Get fixed info about fb
if (ioctl(fp,FBIOGET_FSCREENINFO,&fb_fix)){
printf("Error reading fixed information/n");
return -1;
}
// Get variable info about fb
if (ioctl(fp,FBIOGET_VSCREENINFO,&fb_var)){
printf("Error reading variable information/n");
return -1;
}
printf("--- FB info ---\n");
printf("FB_VISUAL : %u \nFB_BITS_PER_PIXEL : %u \n\n", fb_fix.visual, fb_var.bits_per_pixel);
// Get info about cmap
int i = ioctl(fp,FBIOGETCMAP,&ocmap);
if (i == -1){
printf("Error reading cmap information\n");
return -1;
}
return 0;
}
And, here is the output of C code.
--- FB info ---
FB_VISUAL : 3
FB_BITS_PER_PIXEL : 8
Error reading cmap information
After looking at many sources including fbida, trinity and this, I believe that I am using the IOCTL calls in right way, but still can't figure out why "ioctl(fp,FBIOGETCMAP,&ocmap);" returns -1.
I would greatly appreciate any help in this direction.

sending audio via bluetooth a2dp source esp32

I am trying to send measured i2s analogue signal (e.g. from mic) to the sink device via Bluetooth instead of the default noise.
Currently I am trying to change the bt_app_a2d_data_cb()
static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t i2s_read_len)
{
if (i2s_read_len < 0 || data == NULL) {
return 0;
}
char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
bytes_read = 0;
i2s_adc_enable(I2S_NUM_0);
while(bytes_read == 0)
{
i2s_read(I2S_NUM_0, i2s_read_buff, i2s_read_len,&bytes_read, portMAX_DELAY);
}
i2s_adc_disable(I2S_NUM_0);
// taking care of the watchdog//
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
uint32_t j = 0;
uint16_t dac_value = 0;
// change 16bit input signal to 8bit
for (int i = 0; i < i2s_read_len; i += 2) {
dac_value = ((((uint16_t) (i2s_read_buff[i + 1] & 0xf) << 8) | ((i2s_read_buff[i + 0]))));
data[j] = (uint8_t) dac_value * 256 / 4096;
j++;
}
// testing for loop
//uint8_t da = 0;
//for (int i = 0; i < i2s_read_len; i++) {
// data[i] = (uint8_t) (i2s_read_buff[i] >> 8);// & 0xff;
// da++;
// if(da>254) da=0;
//}
free(i2s_read_buff);
i2s_read_buff = NULL;
return i2s_read_len;
}
I can hear the sawtooth sound from the sink device.
Any ideas what to do?
your data can be an array of some float digits representing analog signals or analog signal variations, for example, a 32khz sound signal contains 320000 float numbers to define captures sound for every second. if your data have been expected to transmit in offline mode you can prepare your outcoming data in the form of a buffer plus a terminator sign then send buffer by Bluetooth module of sender device which is connected to the proper microcontroller. for the receiving device, if you got terminator character like "\r" you can process incoming buffer e.g. for my case, I had to send a string array of numbers but I often received at most one or two unknown characters and to avoid it I reject it while fulfill receiving container.
how to trim unknown first characters of string in code vision
if you want it in online mode i.e. your data must be transmitted and played concurrently. you must consider delays and reasonable time to process for all microcontrollers and devices like Bluetooth, EEprom iCs and...
I'm also working on a project "a2dp source esp32".
I'm playing a wav-file from spiffs.
If the wav-file is 44100, 16-bit, stereo then you can directly write a stream of bytes from the file to the array data[ ].
When I tried to write less data than in the len-variable and return less (for example 88), I got an error, now I'm trying to figure out how to reduce this buffer because of big latency (len=512).
Also, the data in the array data[ ] is stored as stereo.
Example: read data from file to data[ ]-array:
size_t read;
read = fread((void*) data, 1, len, fwave);//fwave is a file
if(read<len){//If get EOF, go to begin of the file
fseek(fwave , 0x2C , SEEK_SET);//skip wav-header 44bytesт
read = fread((void*) (&(data[read])), 1, len-read, fwave);//read up
}
If file mono, I convert it to stereo like this (I read half and then double data):
int32_t lenHalf=len/2;
read = fread((void*) data, 1, lenHalf, fwave);
if(read<lenHalf){
fseek(fwave , 0x2C , SEEK_SET);//skip wav-header 44bytesт
read = fread((void*) (&(data[read])), 1, lenHalf-read, fwave);//read up
}
//copy to the second channel
uint16_t *data16=(uint16_t*)data;
for (int i = lenHalf/2-1; i >= 0; i--) {
data16[(i << 1)] = data16[i];
data16[(i << 1) + 1] = data16[i];
}
I think you have got sawtooth sound because:
your data is mono?
in your "return i2s_read_len;" i2s_read_len less than len
you // change 16bit input signal to 8bit, in the array data[ ] data as 16-bit: 2ByteLeft-2ByteRight-2ByteLeft-2ByteRight-...
I'm not sure, it's a guess.

What is the smallest audio buffer needed to produce Tone sound without distotions with WaveOUT API

Does the WaveOut API has some internal limitation of the size for the current piece of buffer played ? I mean if I provide a very small buffer does it affects somehow the sound played to the speakers. I am experiencing very strange noise when I am generating and playing the sinus wave with small buffer. Something like a peak, or "BUMP".
The complete Story:
I made a program that can generate Sinus sound signal in real time.
The variable parameters are Frequency and Volume. The project requirement was to have a maximum latency of 50 ms. So the program must be able to produce Sinus signals with manually adjustable frequency of audio signal in real time.
I used Windows WaveOut API, C# and P/invoke to access the API.
Everything works fine when the sound buffer is 1000 ms large. If I minimize the buffer to 50 ms as per latency requirement then for certain frequencies I am experiencing at the end of every buffer, a noise or "BUMP". I do not understand if the sound generated is malformed ( I checked and is not) or something happens with the Audio chip, or some delay in initializing and playing.
When I save the produced audio to .wav file everything is perfect.
This means the must be some bug in my code or the audio subsystem has a limitation to the buffer chunks sent to it.
For those who doesn't know WaveOut must be initialized at first time and then must be prepared with audio headers for each buffer that are containing the number of bytes that needs to be played and the pointer to a memory that contains the audio that needs to be player.
UPDATE
Noise happens with the following combinations 44100 SamplingRate, 16 Bits, 2 channels, 50 ms buffer and generated Sinus audio signal of 201Hz, 202Hz, 203Hz, 204Hz, 205Hz ... 219Hz,
220Hz, 240 Hz, is ok
Why is this difference of 20, I do not know.
There are a few things to keep in mind when you need to output audio smoothly:
waveOutXxxx API is a legacy/compatibility layer on top of lower level API and as such it has greater overhead and is not recommended when you are to reach minimal latency. Note that this is unlikely to be your primary problem, but this is a piece of general knowledge helpful for understanding
because Windows is not real time OS and its audio subsystem is not realtime either you don't have control over random latency involved between you queue audio data for output and the data is really played back, the key is to keep certain level of buffer fullness which protects you from playback underflows and delivers smooth playback
with waveOutXxxx you are no limited to having single buffer, you can allocate multiple reusable buffers and recycle them
All in all, waveOutXxxx, DirectSound, DirectShow APIs work well with latencies 50 ms and up. With WASAPI exclusive mode streams you can get 5 ms latencies and even lower.
EDIT: I seem to have said too early about 20 ms latencies. To compensate for this, here is a simple tool LowLatencyWaveOutPlay (Win32, x64) to estimate the latency you can achieve. With sufficient buffering playback is smooth, otherwise you hear stuttering.
My understanding is that buffers might be returned late and the optimal design in terms of smallest latency lies along the line of having more smaller buffers so that you are given them back as early as possible. For example, 10 buffers 3 ms/buffer rather than 3 buffers 10 ms/buffer.
D:\>LowLatencyWaveOutPlay.exe 48000 10 3
Format: 48000 Hz, 1 channels, 16 bits per sample
Buffer Count: 10
Buffer Length: 3 ms (288 bytes)
Signal Frequency: 1000 Hz
^C
So I came here because I wanted to find the basic latency of waveoutwrite() as well. I got around 25-26ms of latency before I got to the smooth sine tone.
This is for:
AMD Phenom(tm) 9850 Quad-Core Processor 2.51 GHz
4.00 GB ram
64-bit operating system, x64-based processor
Windows 10 Enterprise N
The code follows. It is a modfied version of Petzold's sine wave program, refactored to run on the command line. I also changed the polling of buffers to use of a callback on buffer complete with the idea that this would make the program more efficient, but it didn't make a difference.
It also has a setup for elapsed timing, which I used to probe various timings for operations on the buffers. Using those I get:
Sine wave output program
Channels: 2
Sample rate: 44100
Bytes per second: 176400
Block align: 4
Bits per sample: 16
Time per buffer: 0.025850
Total time prepare header: 87.5000000000 usec
Total time to fill: 327.9000000000 usec
Total time for waveOutWrite: 90.8000000000 usec
Program:
/*******************************************************************************
WaveOut example program
Based on C. Petzold's sine wave example, outputs a sine wave via the waveOut
API in Win32.
*******************************************************************************/
#include <stdio.h>
#include <windows.h>
#include <math.h>
#include <limits.h>
#include <unistd.h>
#define SAMPLE_RATE 44100
#define FREQ_INIT 440
#define OUT_BUFFER_SIZE 570*4
#define PI 3.14159
#define CHANNELS 2
#define BITS 16
#define MAXTIM 1000000000
double fAngle;
LARGE_INTEGER perffreq;
PWAVEHDR pWaveHdr1, pWaveHdr2;
int iFreq = FREQ_INIT;
VOID FillBuffer (short* pBuffer, int iFreq)
{
int i;
int c;
for (i = 0 ; i < OUT_BUFFER_SIZE ; i += CHANNELS) {
for (c = 0; c < CHANNELS; c++)
pBuffer[i+c] = (short)(SHRT_MAX*sin (fAngle));
fAngle += 2*PI*iFreq/SAMPLE_RATE;
if (fAngle > 2 * PI) fAngle -= 2*PI;
}
}
double elapsed(LARGE_INTEGER t)
{
LARGE_INTEGER rt;
long tt;
QueryPerformanceCounter(&rt);
tt = rt.QuadPart-t.QuadPart;
return (tt*(1.0/(double)perffreq.QuadPart));
}
void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
if (uMsg == WOM_DONE) {
if (pWaveHdr1->dwFlags & WHDR_DONE) {
FillBuffer((short*)pWaveHdr1->lpData, iFreq);
waveOutWrite(hwo, pWaveHdr1, sizeof(WAVEHDR));
}
if (pWaveHdr2->dwFlags & WHDR_DONE) {
FillBuffer((short*)pWaveHdr2->lpData, iFreq);
waveOutWrite(hwo, pWaveHdr2, sizeof(WAVEHDR));
}
}
}
int main()
{
HWAVEOUT hWaveOut ;
short* pBuffer1;
short* pBuffer2;
short* pBuffer3;
WAVEFORMATEX waveformat;
UINT wReturn;
int bytes;
long t;
LARGE_INTEGER rt;
double timprep;
double filtim;
double waveouttim;
printf("Sine wave output program\n");
fAngle = 0; /* start sine angle */
QueryPerformanceFrequency(&perffreq);
pWaveHdr1 = malloc (sizeof (WAVEHDR));
pWaveHdr2 = malloc (sizeof (WAVEHDR));
pBuffer1 = malloc (OUT_BUFFER_SIZE*sizeof(short));
pBuffer2 = malloc (OUT_BUFFER_SIZE*sizeof(short));
pBuffer3 = malloc (OUT_BUFFER_SIZE*sizeof(short));
if (!pWaveHdr1 || !pWaveHdr2 || !pBuffer1 || !pBuffer2) {
if (!pWaveHdr1) free (pWaveHdr1) ;
if (!pWaveHdr2) free (pWaveHdr2) ;
if (!pBuffer1) free (pBuffer1) ;
if (!pBuffer2) free (pBuffer2) ;
fprintf(stderr, "*** Error: No memory\n");
exit(1);
}
// Load prime parameters to format
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = CHANNELS;
waveformat.nSamplesPerSec = SAMPLE_RATE;
waveformat.wBitsPerSample = BITS;
waveformat.cbSize = 0;
// Calculate other parameters
bytes = waveformat.wBitsPerSample/8; /* find bytes per sample */
if (waveformat.wBitsPerSample&8) bytes++; /* round up */
bytes *= waveformat.nChannels; /* find total channels size */
waveformat.nBlockAlign = bytes; /* set block align */
/* find average bytes/sec */
waveformat.nAvgBytesPerSec = bytes*waveformat.nSamplesPerSec;
printf("Channels: %d\n", waveformat.nChannels);
printf("Sample rate: %d\n", waveformat.nSamplesPerSec);
printf("Bytes per second: %d\n", waveformat.nAvgBytesPerSec);
printf("Block align: %d\n", waveformat.nBlockAlign);
printf("Bits per sample: %d\n", waveformat.wBitsPerSample);
printf("Time per buffer: %f\n",
OUT_BUFFER_SIZE*sizeof(short)/(double)waveformat.nAvgBytesPerSec);
if (waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveformat, (DWORD_PTR)waveOutProc, 0, CALLBACK_FUNCTION)
!= MMSYSERR_NOERROR) {
free (pWaveHdr1) ;
free (pWaveHdr2) ;
free (pBuffer1) ;
free (pBuffer2) ;
hWaveOut = NULL ;
fprintf(stderr, "*** Error: No memory\n");
exit(1);
}
// Set up headers and prepare them
pWaveHdr1->lpData = (LPSTR)pBuffer1;
pWaveHdr1->dwBufferLength = OUT_BUFFER_SIZE*sizeof(short);
pWaveHdr1->dwBytesRecorded = 0;
pWaveHdr1->dwUser = 0;
pWaveHdr1->dwFlags = WHDR_DONE;
pWaveHdr1->dwLoops = 1;
pWaveHdr1->lpNext = NULL;
pWaveHdr1->reserved = 0;
QueryPerformanceCounter(&rt);
waveOutPrepareHeader(hWaveOut, pWaveHdr1, sizeof (WAVEHDR));
timprep = elapsed(rt);
pWaveHdr2->lpData = (LPSTR)pBuffer2;
pWaveHdr2->dwBufferLength = OUT_BUFFER_SIZE*sizeof(short);
pWaveHdr2->dwBytesRecorded = 0;
pWaveHdr2->dwUser = 0;
pWaveHdr2->dwFlags = WHDR_DONE;
pWaveHdr2->dwLoops = 1;
pWaveHdr2->lpNext = NULL;
pWaveHdr2->reserved = 0;
waveOutPrepareHeader(hWaveOut, pWaveHdr2, sizeof (WAVEHDR));
// Send two buffers to waveform output device
QueryPerformanceCounter(&rt);
FillBuffer (pBuffer1, iFreq);
filtim = elapsed(rt);
QueryPerformanceCounter(&rt);
waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR));
waveouttim = elapsed(rt);
FillBuffer (pBuffer2, iFreq);
waveOutWrite (hWaveOut, pWaveHdr2, sizeof (WAVEHDR));
// Run waveform loop
sleep(10);
printf("Total time prepare header: %.10f usec\n", timprep*1000000);
printf("Total time to fill: %.10f usec\n", filtim*1000000);
printf("Total time for waveOutWrite: %.10f usec\n", waveouttim*1000000);
waveOutUnprepareHeader(hWaveOut, pWaveHdr1, sizeof (WAVEHDR));
waveOutUnprepareHeader(hWaveOut, pWaveHdr2, sizeof (WAVEHDR));
// Close waveform file
free (pWaveHdr1) ;
free (pWaveHdr2) ;
free (pBuffer1) ;
free (pBuffer2) ;
}

cvFindContours always returns 0 - OpenCV

I'm calling the cvFindContours function inside a separate thread that I've created to handle all OpenCV work while another is kept for OpenGL stuff.
I noticed that my cvFindContours function always returns 0 when this code is executed inside a separate thread. It worked fine before, when executed in the main thread itself. I used breakpoints and Watches to evaluate value changes. everything else (variables) gets values except for contourCount (value: 0).
Any clue?
// header includes goes here
CvCapture* capture = NULL;
IplImage* frame = NULL;
IplImage* image;
IplImage* gray;
IplImage* grayContour;
CvMemStorage *storage;
CvSeq *firstcontour=NULL;
CvSeq *polycontour=NULL;
int contourCount = 0;
DWORD WINAPI startOCV(LPVOID vpParam){
capture = cvCaptureFromCAM(0); // NOTE 1
capture = cvCaptureFromCAM(0);
frame = cvQueryFrame(capture);
image = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U,3);
gray = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U,1);
grayContour = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U,1);
storage = cvCreateMemStorage (0);
firstcontour=NULL;
while(1){
frame = cvQueryFrame(capture);
cvCopy(frame,image);
cvCvtColor(image,gray,CV_BGR2GRAY);
cvSmooth(gray,gray,CV_GAUSSIAN,3);
cvThreshold (gray, gray, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
cvNot(gray,gray);
cvCopy(gray,grayContour);
contourCount=cvFindContours (grayContour, storage, &firstcontour, sizeof (CvContour),
CV_RETR_CCOMP);
polycontour=cvApproxPoly(firstcontour,sizeof(CvContour),storagepoly,CV_POLY_APPROX_DP,3,1); // Error starts here (Pls refer to stack trace)
}
// goes on...
}
int main(int argc, char** argv){
DWORD qThreadID;
HANDLE ocvThread = CreateThread(0,0,startOCV, NULL,0, &qThreadID);
initGL(argc, argv); //some GL intitialization functions
glutMainLoop(); // draw some 3D objects
CloseHandle(ocvThread);
return 0;
}
NOTE1: these lines had to be duplicated due to the error mentioned at How to avoid "Video Source -> Capture source" selection in OpenCV 2.3.0 - Visual C++ 2008
Environment:
OpenCV 2.3.0
Visual C++ 2008
EDIT
Traces
opencv_core230d.dll!cv::error(const cv::Exception & exc={...}) Line 431 C++
opencv_imgproc230d.dll!cvPointSeqFromMat(int seq_kind=20480, const void * arr=0x00000000, CvContour * contour_header=0x01a6f514, CvSeqBlock * block=0x01a6f4f4) Line 47 + 0xbd bytes C++
opencv_imgproc230d.dll!cvApproxPoly(const void * array=0x00000000, int header_size=88, CvMemStorage * storage=0x017e7b40, int method=0, double parameter=3.0000000000000000, int parameter2=1) Line 703 + 0x28 bytes C++
Project.exe!startOCV(void * vpParam=0x00000000) Line 267 + 0x24 bytes C++
All this stuff boils down to the function CV_Assert( arr != 0 && contour_header != 0 && block != 0 ) in cvPointSeqFromMat and it fails since arr it requires is empty.
Your variable contourCount is not doing what you think it's doing. From the contours.cpp source file:
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvFindContours
// Purpose:
// Finds all the contours on the bi-level image.
// Context:
// Parameters:
// img - source image.
// Non-zero pixels are considered as 1-pixels
// and zero pixels as 0-pixels.
// step - full width of source image in bytes.
// size - width and height of the image in pixels
// storage - pointer to storage where will the output contours be placed.
// header_size - header size of resulting contours
// mode - mode of contour retrieval.
// method - method of approximation that is applied to contours
// first_contour - pointer to first contour pointer
// Returns:
// CV_OK or error code
// Notes:
//F*/
You are getting CV_OK == 0, which means it successfully ran. cvFindContours does not return the number of contours found to you. It merely lets you known if it failed or not. You should use the CvSeq* first_contour to figure out the number of contours detected.
Hope that helps!

How to get screen DPI (linux,mac) programatically?

I need to know active screen DPI on Linux and Mac OS. I think on linux xlib might be useful, but I can't find a way how to get currect DPI.
I want this information to get real screen size in inches.
Thanks in advance!
On a mac, use CGDisplayScreenSize to get the screen size in millimeters.
In X on Linux, call XOpenDisplay() to get the Display, then use DisplayWidthMM() and DisplayHeightMM() together with DisplayWidth() and DisplayHeight() to compute the DPI.
On the Mac, there's almost certainly a more native API to use than X. Mac OS X does not run X Window by default, it has a native windowing environment.
I cobbled this together from xdpyinfo...
Compile with: gcc -Wall -o getdpi getdpi.c -lX11
/* Get dots per inch
*/
static void get_dpi(int *x, int *y)
{
double xres, yres;
Display *dpy;
char *displayname = NULL;
int scr = 0; /* Screen number */
if( (NULL == x) || (NULL == y)){ return ; }
dpy = XOpenDisplay (displayname);
/*
* there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
*
* dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
* = N pixels / (M inch / 25.4)
* = N * 25.4 pixels / M inch
*/
xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) /
((double) DisplayWidthMM(dpy,scr)));
yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) /
((double) DisplayHeightMM(dpy,scr)));
*x = (int) (xres + 0.5);
*y = (int) (yres + 0.5);
XCloseDisplay (dpy);
}
You can use NSScreen to get the dimensions of the attached display(s) in pixels, but this won't give you the physical size/PPI of the display and in fact I don't think there are any APIs that will be able to do this reliably.
You can ask a window for its resolution like so:
NSDictionary* deviceDescription = [window deviceDescription];
NSSize resolution = [[deviceDescription objectForKey:NSDeviceResolution] sizeValue];
This will currently give you an NSSize of {72,72} for all screens, no matter what their actual PPI. The only thing that make this value change is changing the scaling factor in the Quartz Debug utility, or if Apple ever turns on resolution-independent UI. You can obtain the current scale factor by calling:
[[NSScreen mainScreen] userSpaceScaleFactor];
If you really must know the exact resolution (and I'd be interested to know why you think you do), you could create a screen calibration routine and have the user measure a line on-screen with an actual physical ruler. Crude, yes, but it will work.
Here's a platform independent way to get the screen DPI:
// Written in Java
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.border.EmptyBorder;
public final class DpiTest {
public static void main(String[] args) {
JFrame frame = new JFrame("DPI");
JLabel label = new JLabel("Current Screen DPI: " + Toolkit.getDefaultToolkit().getScreenResolution());
label.setBorder(new EmptyBorder(20, 20, 20, 20));
frame.add(label);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
You can download a compiled jar of this from here. After downloading, java -jar dpi.jar will show you the DPI.

Resources