how to draw point and line between 2 points in opencv??? Would like by clicking in image using mouse draw points and connect them.
See Drawing Functions specifically cv::Line
look at the included samples called drawing.py and inpaint.py or their c++ equivalents.
The Sketcher class inside inpaint.py is probably what you are looking for.
Using the Mouse functions in opencv is a real chore. If it helps, here is my code example of drawing rectangles on video. Its fully functional so you can just cut and paste the whole thing. You should be able to pick it apart and see how mouse handling works.
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#define SSTR( x ) dynamic_cast< std::ostringstream & >(( std::ostringstream() << std::dec << x ) ).str()
using namespace std;
using namespace cv;
Rect box;
bool drawing_box = false;
struct mousecallbackstruct{
Mat* src;
Mat* overlay;
string windowname;
};
Mat srcoverlay,smallsrcoverlay;
void onMouse(int event, int x, int y, int flags, void* param) //it seems the only way to use this is by keeping different globals for different windows - meaning you have to set up all thise ahead of time, and keep track of it and not mix/match windows/frames!! horrible design here.
{
cout << event;
mousecallbackstruct mousestruct;
mousestruct = *((mousecallbackstruct*)param);
Mat* srcp = mousestruct.src;
Mat* overlayp = mousestruct.overlay;
Mat src = *srcp;
Mat overlay = *overlayp;
if(!src.data){
cout << "your void * cast didn't work :(\n";
return;
}
switch( event ){
case CV_EVENT_MOUSEMOVE:
if( drawing_box ){
box.width = x-box.x;
box.height = y-box.y;
}
break;
case CV_EVENT_LBUTTONDOWN: //start drawing
drawing_box = true;
box = cvRect( x, y, 0, 0 );
break;
case CV_EVENT_LBUTTONDBLCLK: //double click to clear
drawing_box = false;
overlay.setTo(cv::Scalar::all(0)); //clear it
break;
case CV_EVENT_LBUTTONUP: //draw what we created with Lbuttondown
drawing_box = false;
if( box.width < 0 ){
box.x += box.width;
box.width *= -1;
}
if( box.height < 0 ){
box.y += box.height;
box.height *= -1;
}
rectangle( overlay, Point(box.x, box.y), Point(box.x+box.width,box.y+box.height),CV_RGB(100,200,100),4); //draw rectangle. You can change this to line or circle or whatever. Maybe with the Right mouse button.
break;
}
}
void iimshow(mousecallbackstruct* mystructp){ //this is where we add the text/drawing created in the mouse handler to the actual image (since mouse handler events do not line up with the drawing events)
mousecallbackstruct mystruct = *mystructp; //custom struct made for the mouse callback - very handy for other functions too
Mat overlay, src;
Mat* srcp = mystruct.src;
Mat* overlayp = mystruct.overlay;
src = *srcp; // yeah, yeah, i use 9 lines where I could use 3, so sue me
overlay = *overlayp;
string name = mystruct.windowname;
Mat added,imageROI;
try{
//cout << "tch:" << overlay.rows << "," << src.rows << ";" << overlay.cols << "," << src.cols << ";" << src.channels() << "," << overlay.channels() <<"," << src.type() << "," << overlay.type() << "\n";
if(overlay.data && overlay.rows == src.rows && overlay.cols == src.cols && overlay.channels() == src.channels()){ //basic error checking
add(src,overlay,added);
}else{
//try to resize it
imageROI= overlay(Rect(0,0,src.cols,src.rows));
add(src,imageROI,added);
}
imshow(name,added);// the actual draw moment
}catch(...){ //if resize didn't work then this should catch it
cout << "Error. Mismatch:" << overlay.rows << "," << src.rows << ";" << overlay.cols << "," << src.cols << ";" << src.channels() << "," << overlay.channels() <<"," << src.type() << "," << overlay.type() << "\n";
imshow(name + "overlay",overlay);
imshow(name+"source",src);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) { // check if we succeeded
cout << "NO camera found \n";
return -1;
}
Mat src,smallsrc,overlay;
cap >> src; //grab 1 frame to build our preliminary Mats and overlays
srcoverlay.create(src.rows,src.cols,src.type()); //create overlays
smallsrcoverlay.create(src.rows,src.cols,src.type());
srcoverlay.setTo(cv::Scalar::all(0)); //clear it
smallsrcoverlay.setTo(cv::Scalar::all(0)); //clear it
namedWindow( "smallsrc", CV_WINDOW_AUTOSIZE );
namedWindow( "source", CV_WINDOW_AUTOSIZE ); //these must be created early for the setmousecallback, AND you have to know what Mats will be using them and not switch them around :(
moveWindow("smallsrc",2000,100); //create a small original capture off to the side of screen
////////////// for each window/mat that uses a mouse handler, you must create one of these structures for it and pass it into the mouse handler
mousecallbackstruct srcmousestruct,smallsrcmousestruct; //these get passed into the mouse callback function. Hopefully they update their contents automatically for the callback? :(
srcmousestruct.overlay = &srcoverlay; //fill our custom struct
srcmousestruct.src = &src;
srcmousestruct.windowname = "source";
smallsrcmousestruct.overlay = &smallsrcoverlay; //the small window
smallsrcmousestruct.src = &smallsrc;
smallsrcmousestruct.windowname = "smallsrc";
setMouseCallback(smallsrcmousestruct.windowname, onMouse, (void*)&smallsrcmousestruct); //the actual 'set mouse callback' call
setMouseCallback(srcmousestruct.windowname, onMouse, (void*)&srcmousestruct);
for(;;){ //main loop
/// Load an image
cap >> src;
if( !src.data )
{ return -1; }
resize(src,smallsrc,Size(),.5,.5); //smaller scale window of original
overlay = *srcmousestruct.overlay;
src = *srcmousestruct.src;
iimshow(&srcmousestruct); //my imshow replacement. uses structs
iimshow(&smallsrcmousestruct);
if(waitKey(30) == 27) cin.get(); //esc pauses
}
cin.get();
return 0;
}
Related
I'have started to work on ns3 and i try to extract from code manet-routing-compare.cc which is intalled by default with NS3.26 in examples/routing.I want to extract 4 parameters :number of sent packet, reception time of packet ,send time and packet size in order to calculate throughput and delay end to end.I have tried but i don't find a solution and every time we have error. Please, help me i really need this parametrs and thank you very much.
#include <fstream>
#include <iostream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/wifi-module.h"
#include "ns3/aodv-module.h"
#include "ns3/olsr-module.h"
#include "ns3/dsdv-module.h"
#include "ns3/dsr-module.h"
#include "ns3/applications-module.h"
using namespace ns3;
using namespace dsr;
NS_LOG_COMPONENT_DEFINE ("manet-routing-compare");
class RoutingExperiment
{
public:
RoutingExperiment ();
void Run (int nSinks, double txp, std::string CSVfileName);
//static void SetMACParam (ns3::NetDeviceContainer & devices,
// int slotDistance);
std::string CommandSetup (int argc, char **argv);
private:
Ptr<Socket> SetupPacketReceive (Ipv4Address addr, Ptr<Node> node);
void ReceivePacket (Ptr<Socket> socket);
void CheckThroughput ();
uint32_t port;
uint32_t bytesTotal;
uint32_t packetsReceived;
std::string m_CSVfileName;
int m_nSinks;
std::string m_protocolName;
double m_txp;
bool m_traceMobility;
uint32_t m_protocol;
};
RoutingExperiment::RoutingExperiment ()
: port (9),
bytesTotal (0),
packetsReceived (0),
m_CSVfileName ("manet-routing.output.csv"),
m_traceMobility (false),
m_protocol (2) // AODV
{
}
static inline std::string
PrintReceivedPacket (Ptr<Socket> socket, Ptr<Packet> packet, Address senderAddress)
{
std::ostringstream oss;
oss << Simulator::Now ().GetSeconds () << " " << socket->GetNode ()->GetId ();
if (InetSocketAddress::IsMatchingType (senderAddress))
{
InetSocketAddress addr = InetSocketAddress::ConvertFrom (senderAddress);
oss << " received one packet from " << addr.GetIpv4 ();
}
else
{
oss << " received one packet!";
}
return oss.str ();
}
void
RoutingExperiment::ReceivePacket (Ptr<Socket> socket)
{
Ptr<Packet> packet;
Address senderAddress;
while ((packet = socket->RecvFrom (senderAddress)))
{
bytesTotal += packet->GetSize ();
packetsReceived += 1;
NS_LOG_UNCOND (PrintReceivedPacket (socket, packet, senderAddress));
}
}
void
RoutingExperiment::CheckThroughput ()
{
double kbs = (bytesTotal * 8.0) / 1000;
bytesTotal = 0;
std::ofstream out (m_CSVfileName.c_str (), std::ios::app);
out << (Simulator::Now ()).GetSeconds () << ","
<< kbs << ","
<< packetsReceived << ","
<< m_nSinks << ","
<< m_protocolName << ","
<< m_txp << ""
<< std::endl;
out.close ();
packetsReceived = 0;
Simulator::Schedule (Seconds (1.0), &RoutingExperiment::CheckThroughput, this);
}
Ptr<Socket>
RoutingExperiment::SetupPacketReceive (Ipv4Address addr, Ptr<Node> node)
{
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
Ptr<Socket> sink = Socket::CreateSocket (node, tid);
InetSocketAddress local = InetSocketAddress (addr, port);
sink->Bind (local);
sink->SetRecvCallback (MakeCallback (&RoutingExperiment::ReceivePacket, this));
return sink;
}
std::string
RoutingExperiment::CommandSetup (int argc, char **argv)
{
CommandLine cmd;
cmd.AddValue ("CSVfileName", "The name of the CSV output file name", m_CSVfileName);
cmd.AddValue ("traceMobility", "Enable mobility tracing", m_traceMobility);
cmd.AddValue ("protocol", "1=OLSR;2=AODV;3=DSDV;4=DSR", m_protocol);
cmd.Parse (argc, argv);
return m_CSVfileName;
}
int
main (int argc, char *argv[])
{
RoutingExperiment experiment;
std::string CSVfileName = experiment.CommandSetup (argc,argv);
//blank out the last output file and write the column headers
std::ofstream out (CSVfileName.c_str ());
out << "SimulationSecond," <<
"ReceiveRate," <<
"PacketsReceived," <<
"NumberOfSinks," <<
"RoutingProtocol," <<
"TransmissionPower" <<
std::endl;
out.close ();
int nSinks = 10;
double txp = 7.5;
experiment.Run (nSinks, txp, CSVfileName);
}
void
RoutingExperiment::Run (int nSinks, double txp, std::string CSVfileName)
{
Packet::EnablePrinting ();
m_nSinks = nSinks;
m_txp = txp;
m_CSVfileName = CSVfileName;
int nWifis = 50;
double TotalTime = 200.0;
std::string rate ("2048bps");
std::string phyMode ("DsssRate11Mbps");
std::string tr_name ("manet-routing-compare");
int nodeSpeed = 20; //in m/s
int nodePause = 0; //in s
m_protocolName = "protocol";
Config::SetDefault ("ns3::OnOffApplication::PacketSize",StringValue ("64"));
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (rate));
//Set Non-unicastMode rate to unicast mode
Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",StringValue (phyMode));
NodeContainer adhocNodes;
adhocNodes.Create (nWifis);
// setting up wifi phy and channel using helpers
WifiHelper wifi;
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper wifiChannel;
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
wifiPhy.SetChannel (wifiChannel.Create ());
// Add a mac and disable rate control
WifiMacHelper wifiMac;
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",StringValue (phyMode),
"ControlMode",StringValue (phyMode));
wifiPhy.Set ("TxPowerStart",DoubleValue (txp));
wifiPhy.Set ("TxPowerEnd", DoubleValue (txp));
wifiMac.SetType ("ns3::AdhocWifiMac");
NetDeviceContainer adhocDevices = wifi.Install (wifiPhy, wifiMac, adhocNodes);
MobilityHelper mobilityAdhoc;
int64_t streamIndex = 0; // used to get consistent mobility across scenarios
ObjectFactory pos;
pos.SetTypeId ("ns3::RandomRectanglePositionAllocator");
pos.Set ("X", StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=300.0]"));
pos.Set ("Y", StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1500.0]"));
Ptr<PositionAllocator> taPositionAlloc = pos.Create ()->GetObject<PositionAllocator> ();
streamIndex += taPositionAlloc->AssignStreams (streamIndex);
std::stringstream ssSpeed;
ssSpeed << "ns3::UniformRandomVariable[Min=0.0|Max=" << nodeSpeed << "]";
std::stringstream ssPause;
ssPause << "ns3::ConstantRandomVariable[Constant=" << nodePause << "]";
mobilityAdhoc.SetMobilityModel ("ns3::RandomWaypointMobilityModel",
"Speed", StringValue (ssSpeed.str ()),
"Pause", StringValue (ssPause.str ()),
"PositionAllocator", PointerValue (taPositionAlloc));
mobilityAdhoc.SetPositionAllocator (taPositionAlloc);
mobilityAdhoc.Install (adhocNodes);
streamIndex += mobilityAdhoc.AssignStreams (adhocNodes, streamIndex);
AodvHelper aodv;
OlsrHelper olsr;
DsdvHelper dsdv;
DsrHelper dsr;
DsrMainHelper dsrMain;
Ipv4ListRoutingHelper list;
InternetStackHelper internet;
switch (m_protocol)
{
case 1:
list.Add (olsr, 100);
m_protocolName = "OLSR";
break;
case 2:
list.Add (aodv, 100);
m_protocolName = "AODV";
break;
case 3:
list.Add (dsdv, 100);
m_protocolName = "DSDV";
break;
case 4:
m_protocolName = "DSR";
break;
default:
NS_FATAL_ERROR ("No such protocol:" << m_protocol);
}
if (m_protocol < 4)
{
internet.SetRoutingHelper (list);
internet.Install (adhocNodes);
}
else if (m_protocol == 4)
{
internet.Install (adhocNodes);
dsrMain.Install (dsr, adhocNodes);
}
NS_LOG_INFO ("assigning ip address");
Ipv4AddressHelper addressAdhoc;
addressAdhoc.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer adhocInterfaces;
adhocInterfaces = addressAdhoc.Assign (adhocDevices);
OnOffHelper onoff1 ("ns3::UdpSocketFactory",Address ());
onoff1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
onoff1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"));
for (int i = 0; i < nSinks; i++)
{
Ptr<Socket> sink = SetupPacketReceive (adhocInterfaces.GetAddress (i), adhocNodes.Get (i));
AddressValue remoteAddress (InetSocketAddress (adhocInterfaces.GetAddress (i), port));
onoff1.SetAttribute ("Remote", remoteAddress);
Ptr<UniformRandomVariable> var = CreateObject<UniformRandomVariable> ();
ApplicationContainer temp = onoff1.Install (adhocNodes.Get (i + nSinks));
temp.Start (Seconds (var->GetValue (100.0,101.0)));
temp.Stop (Seconds (TotalTime));
}
std::stringstream ss;
ss << nWifis;
std::string nodes = ss.str ();
std::stringstream ss2;
ss2 << nodeSpeed;
std::string sNodeSpeed = ss2.str ();
std::stringstream ss3;
ss3 << nodePause;
std::string sNodePause = ss3.str ();
std::stringstream ss4;
ss4 << rate;
std::string sRate = ss4.str ();
//NS_LOG_INFO ("Configure Tracing.");
//tr_name = tr_name + "_" + m_protocolName +"_" + nodes + "nodes_" + sNodeSpeed + "speed_" + sNodePause + "pause_" + sRate + "rate";
//AsciiTraceHelper ascii;
//Ptr<OutputStreamWrapper> osw = ascii.CreateFileStream ( (tr_name + ".tr").c_str());
//wifiPhy.EnableAsciiAll (osw);
AsciiTraceHelper ascii;
MobilityHelper::EnableAsciiAll (ascii.CreateFileStream (tr_name + ".mob"));
//Ptr<FlowMonitor> flowmon;
//FlowMonitorHelper flowmonHelper;
//flowmon = flowmonHelper.InstallAll ();
NS_LOG_INFO ("Run Simulation.");
CheckThroughput ();
Simulator::Stop (Seconds (TotalTime));
Simulator::Run ();
//flowmon->SerializeToXmlFile ((tr_name + ".flowmon").c_str(), false, false);
Simulator::Destroy ();
}
I am gonna answer it in two parts,
First the parameters which you can get without making much changes, which are reception time and packet size:
PrintReceivedPacket function is called when a packet is received at the receiver, you have access to received packet at this point. The Simulator::Now () gives you the reception time of the packet at sink and packet->GetSize () gives you the size of packet received.
Second the parameters of send time and number of packet sent. You will have to add a sequence to steps to get the trace to
Tx of OnOffApplication
Get Application from ApplicationContainer temp using Get (0)
Cast Application to OnOffApplication using dynamic cast
Connect to the Tx of this pointer to a function and in this function increase a global counter for number of packet sent and log the current time for sent time
Do let me know if any query
I'm trying to draw offscreen with OpenGL. For this I use EGL to initialize a pbuffer surface, and then draw to it, reading the results back with glReadPixels. But the following program gives me garbage on different (Mesa-based Intel on Linux) GPUs. Namely, on Atom N550 I get zeros, while on Xeon E3-1200 v3 I have 70 00 07 44 instead of the expected 40 80 bf ff.
With LIBGL_ALWAYS_SOFTWARE=1 environment variable set, I get the expected results. Also, if I comment out the line with eglBindAPI, I get good result on Xeon, but still zeros on Atom.
Here's my program:
#include <EGL/egl.h>
#include <GL/gl.h>
#include <iostream>
#include <iomanip>
#include <cstring>
int eglPrintError(std::string const& context)
{
const GLint error=eglGetError();
std::cerr << context << ": error 0x" << std::hex << int(error) << "\n";
return 1;
}
bool checkError(std::string const& funcName)
{
const GLenum error=glGetError();
if(error!=GL_NO_ERROR)
{
std::cerr << funcName << ": error 0x" << std::hex << int(error) << "\n";
return true;
}
return false;
}
constexpr int fbW=1, fbH=1;
bool initGL()
{
if(!eglBindAPI(EGL_OPENGL_API)) return !eglPrintError("eglBindAPI");
const EGLDisplay dpy=eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(!dpy) return !eglPrintError("eglGetDisplay");
if(!eglInitialize(dpy,nullptr,nullptr)) return !eglPrintError("eglInitialize");
static const EGLint cfgAttribs[]={EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE};
EGLConfig cfg;
EGLint cfgCount;
if(!eglChooseConfig(dpy,cfgAttribs,&cfg,1,&cfgCount))
return !eglPrintError("eglChooseConfig");
if(cfgCount==0)
{
std::cerr << "Failed to get any usable EGL configs\n";
return false;
}
const EGLContext context=eglCreateContext(dpy,cfg,EGL_NO_CONTEXT,NULL);
if(!context) return !eglPrintError("eglCreateContext");
const EGLint surfaceAttribs[]={EGL_WIDTH, fbW, EGL_HEIGHT, fbH, EGL_NONE};
const EGLSurface surface=eglCreatePbufferSurface(dpy,cfg,surfaceAttribs);
if(!surface) return eglPrintError("eglCreatePbufferSurface");
if(!eglMakeCurrent(dpy,surface,surface,context))
return !eglPrintError("eglMakeCurrent");
return true;
}
int main(int argc, char** argv)
{
if(!initGL()) return 1;
glViewport(0,0,fbW,fbH);
glClearColor(0.25,0.5,0.75,1.);
glClear(GL_COLOR_BUFFER_BIT);
glFinish();
unsigned char data[4*fbW*fbH];
std::memset(data,0xb7,sizeof data); // to see unchanged values
glReadPixels(0,0,fbW,fbH,GL_RGBA,GL_UNSIGNED_BYTE,data);
if(checkError("glReadPixels")) return 1;
std::cout << "Data read: " << std::hex << std::setfill('0');
for(auto datum : data)
std::cout << std::setw(2) << +datum << " ";
std::cout << "\n";
return 0;
}
My question is, is there anything wrong in the above code which could lead to such behavior, or are my drivers just simply buggy?
Hello and thanks in advance.
my problem today is i'm getting back "garbage" for the strings for a registry key value name, and value data. this appears to be a problem on all registry values within a key/folder except for the last value, though sometimes I am able to read the name of the first value (but still not the data)
what I'm trying to do is be able to display the value name and value data that are in a single, possibly variable, registry key (I dont care about subkeys at this point)
I'm trying to do this with windows unicode strings, WCHAR * and LPWSTR types.
the "garbage" i see for the problem strings is a repeated series of non-english characters, which messes up the subsequent wcout displays.
in the registry editor display, the values i'm attempting to read have REG_SZ type data, which I understand to be a string.
probably my biggest problem is i cannot find a clear guide on simply how to do exactly what I'm trying to do, look inside a registry key, and list the value names and value data. any help would be greatly appreciated. I am new to unicode strings and the windows api. my environment is windows xp sp3, visual c++ 2010 express.
#include <stdio.h>
#include <iostream> /* for std::wcin and wcout */
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#include "conio.h"
#
include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
int return_val;
DWORD error;
HKEY hkey;
BYTE iterations = 0;
/* 1. first, open key (folder) */
return_val = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\VIDEO", 0, KEY_READ, &hkey);
/* check how the open went */
if(return_val != ERROR_SUCCESS)
{
std::wcout << L"error opening the key: " << return_val << std::endl;
}
else
{
std::wcout << L"it's cool" << std::endl;
/* 1.a. query the key (optional) */
LPTSTR className = new WCHAR[255];
DWORD classNameSize = MAX_PATH;
DWORD subKey = 0;
DWORD maxSubKey;
DWORD maxClass;
DWORD value;
DWORD maxValue;
DWORD maxValueData;
DWORD securityDescriptor;
FILETIME ftLastWriteTime;
DWORD sectionNameSize;
return_val = RegQueryInfoKey(hkey, className, &classNameSize, NULL,
&subKey, &maxSubKey, &maxClass, &value, &maxValue,
&maxValueData, &securityDescriptor, &ftLastWriteTime);
std::wcout << L"query return: " << return_val << std::endl;
std::wcout << L"class name: " << className << L", (size): " << classNameSize << std::endl;
std::wcout << L"subkey: " << subKey << L", max: " << maxSubKey << L", maxClass: " << maxClass << std::endl;
std::wcout << L"Value: " << value << L", maxval: " << maxValue << L", maxvaldata: " << maxValueData << std::endl;
std::wcout << L"Sec descrpt: " << securityDescriptor << std::endl << std::endl;
/* now enumerate the strings in the key */
int count = 0;
DWORD valuename_size = 16, type_return = 0, data_size = 102;
LPWSTR valuename = new WCHAR[valuename_size];//maxValue
LPWSTR data = new WCHAR[data_size];//maxValueData>>1
/* 2. the outer loop grabs the values one at a time (the data within the key/folder) */
do {
iterations++; /* just for debugging */
return_val = RegEnumValue(hkey, count, valuename, &valuename_size, 0, &type_return, (LPBYTE)data, &data_size);
/* return of RegEnumValue */
std::wcout << L"RegEnumValue return val: " << return_val << std::endl;
/* double check sizes */
std::wcout << L"size: valname_size: " << valuename_size << L", data_size: " << data_size << std::endl;
if(return_val == ERROR_SUCCESS || return_val == ERROR_MORE_DATA)
{
/* to try and avoid bad strings */
if(type_return == REG_DWORD || count == 0)
std::wcout << L"Value - " << valuename << L", Type: " << type_return << L" Data - " << (BYTE)(*data) << std::endl;
else
std::wcout << L"Value - " << valuename << L", Type: " << type_return << L" Data - " << data << std::endl;
}
//data = REG_SZ;
count++;
} while (return_val != ERROR_NO_MORE_ITEMS && count < value);
}
/* just to check my code */
std::wcout << L"iterations: " << iterations << std::endl;
/* to "pause" during debugging */
std::wcin >> input;
return 0;
}
this version based in part on the commentors help seems to work how I want, and I'm posting this for others to reference. What wasnt clear to me is that when getting the number of characters back for the valuename did not include a null terminating character (of course) but also that the size of buffer you pass into it needs to include that, so if you get back 16 and you input 16, thats why it would return 234, (not fair that the input follows diferent constraints than the output but life's not fair), you then need to input 17 for the string size
/* now enumerate the strings in the key */
int count = 0;
DWORD valuename_size, type_return = 0, data_size;
LPWSTR valuename;
BYTE *data;
/* 2. the outer loop grabs the values one at a time (the data within the key/folder) */
do {
valuename_size = maxValue;
data_size = maxValueData;
iterations++; /* just for debugging */
return_val = RegEnumValue(hkey, count, NULL, &valuename_size, 0, &type_return, NULL, &data_size); /* value name */
//return_val = RegEnumValue(hkey, count, NULL, NULL, 0, &type_return, NULL, &data_size); /* value data */
valuename = new WCHAR[valuename_size+1];
data = new BYTE[data_size]; /* data_size is in BYTES, of any type */
valuename[0] = L'\0'; /* if the string returned is still invalid, this will help make sure wcout doesnt mess up */
return_val = RegEnumValue(hkey, count, valuename, &valuename_size, 0, &type_return, (LPBYTE)data, &data_size); /* value name */
//return_val = RegEnumValue(hkey, count, NULL, NULL, 0, &type_return, (LPBYTE)data, &data_size); /* value data */
/* return of RegEnumValue */
std::wcout << L"RegEnumValue return val: " << return_val << std::endl;
/* double check sizes */
std::wcout << L"size: valname_size: " << valuename_size << L", data_size: " << data_size << L", Type: " << type_return << std::endl;
if(return_val == ERROR_MORE_DATA /*&& type_return == REG_DWORD*/)
{
/* try again? */
delete valuename;//free(valuename);
delete data;
/* double the "global" max number of WORDs for the string (including null termination) */
maxValue <<= 1;
valuename_size = maxValue;
maxValueData <<= 1;
data_size = maxValueData;
/* doublecheck */
std::wcout << L"new val size before enum: " << valuename_size << L", new data size before enum: " << data_size << std::endl;
return_val = RegEnumValue(hkey, count, NULL, &valuename_size, 0, &type_return, NULL, &data_size); /* value name */
/* the return version of valuename_size is the number of characters, not including the null terminating character */
valuename = new WCHAR[valuename_size+1];
data = new BYTE[data_size];
valuename[0] = L'\0'; /* if the string returned is still invalid, this will help make sure wcout doesnt mess up */
return_val = RegEnumValue(hkey, count, valuename, &valuename_size, 0, &type_return, (LPBYTE)data, &data_size); /* value name */
std::wcout << std::endl << L"return: " << return_val << L", Val size: " << valuename_size << L", data_size: " << data_size << std::endl << std::endl;
}
if(return_val == ERROR_SUCCESS)
{
valuename[valuename_size] = L'\0'; /* null terminate the string before printing */
/* I only care about string data */
if (type_return == REG_SZ)
{
data[data_size] = 0; /* null terminate the string before printing */
std::wcout << L"Value - " << valuename << L", Type: " << type_return << L" Data - " << (LPWSTR)data << std::endl;
}
}
count++;
} while (return_val != ERROR_NO_MORE_ITEMS && count < value);
}
/* just to check my code */
std::wcout << L"iterations: " << iterations << std::endl;
/* to "pause" during debugging */
std::wcin >> input;
return 0;
}
A few obvious problems:
When you call RegEnumValue, valuename_size and data_size should contain the size of the buffers, but they only do so for the first value. For the second value and beyond they contain the results of the previous call.
String values in the registry are not guaranteed to be NULL terminated. You need to explicitly terminate strings (using the returned length) before using them. Note that since you're using unicode you need to divide the byte length by two to get the length in code units. These comments only apply to values, not names.
You assume that any value that isn't a DWORD is a string. What about binary values?
This program is a nightmare, it wont even give me errors when ran, visual studios tells me nothing and i need some help
#include <iostream>
using namespace std;
class Textbook
{
private:
char *aPtr;
char *tPtr;
int yearPub;
int numPages;
char bookType;
public:
Textbook(char *, char *, int, int, char);
void display();
void operator=(Textbook&);
};
Textbook::Textbook(char*string = NULL, char*string2 = NULL, int ypub = 0, int npages = 0, char btype = 'X')
{
aPtr = new char[strlen(string) +1];
strcpy(aPtr, string);
tPtr = new char[strlen(string2) +1];
strcpy(tPtr, string2);
yearPub = ypub;
numPages = npages;
bookType = btype;
}
void Textbook::display()
{
cout << "The name of the author is: " << *aPtr << endl;
cout << "The Title of the book is: " << *tPtr << endl;
cout << "The year it was published is: " << yearPub << endl;
cout << "The number of pages is: " << numPages << endl;
cout << "The initial of the title is: " << bookType << endl;
return;
}
void Textbook::operator=(Textbook& newbook)
{
if(aPtr != NULL) //check that it exists
delete(aPtr);// delete if neccessary
aPtr = new char[strlen(newbook.aPtr) + 1];
strcpy(aPtr, newbook.aPtr);
if(tPtr != NULL) //check that it exists
delete(tPtr); // delete if neccessary
tPtr = new char[strlen(newbook.tPtr) + 1];
strcpy(tPtr, newbook.tPtr);
yearPub = newbook.yearPub;
numPages = newbook.numPages;
bookType = newbook.bookType;
}
void main()
{
Textbook book1("sehwag", "Programming Methods", 2009, 200, 'H');
Textbook book2("Ashwin", "Security Implementation", 2011, 437, 'P');
Textbook book3;
book1.display();
book2.display();
book3.display();
book3 = book1;
book2 = book3;
book1.display();
book2.display();
book3.display();
}
im not sure if the problem lies in the default constructor but that's about the only thing i could think of, but im not sure at all on how to fix it.
Problem is with the default-parameters in the constructor.
You can't do those kind of operations with NULL-pointers.
Textbook book3;
crashes your program.
Change:
cout << "The name of the author is: " << *aPtr << endl;
cout << "The Title of the book is: " << *tPtr << endl;
to:
cout << "The name of the author is: " << aPtr << endl;
cout << "The Title of the book is: " << tPtr << endl;
Also change:
aPtr = new char[strlen(string) +1];
strcpy(aPtr, string);
to:
if (string != NULL)
{
aPtr = new char[strlen(string) +1];
strcpy(aPtr, string);
}
else
{
aPtr = new char[1];
aPtr[0] = '\0';
}
and ditto for tptr and string2.
The reason you need this checking is because you have NULL as a default value for your two string inputs, so when you call the constructor with no arguments (as is the case with book3) these strings are just NULL pointers. Calling functions such as strlen or strcat with a NULL pointer will result in an exception as you have seen.
Ideally you should not be using C-style strings with C++ - use C++ strings instead - this will help to avoid problems such as the above.
I'm searching for a library to get the outline of a glyph in a true type font on a linux system. We are using Pango and Cairo but unfortunatly I didn't find anything.
I'm looking for somethig similar to GlyphTypeface.GetGlyphOutline under .NET
Any help or hints are appreciated!
Thanks in advance
The solution is to use FreeType, it offers the range of function I need:
#include <string>
#include <iostream>
#include <freetype/ftglyph.h>
#include <freetype/freetype.h>
//******************* check error code ********************
void Check(FT_Error ErrCode, const char* OKMsg, const char* ErrMsg)
{
if(ErrCode != 0)
{
std::cout << ErrMsg << ": " << ErrCode << "\n";
std::cout << "program halted\n";
exit(1);
}
else
std::cout << OKMsg << "\n";
}
//******************** get outline ************************
int GetOutLine(FT_Glyph glyph, FT_OutlineGlyph* Outg)
{
int Err = 0;
switch ( glyph->format )
{
case FT_GLYPH_FORMAT_BITMAP:
Err = 1;
break;
case FT_GLYPH_FORMAT_OUTLINE:
*Outg = (FT_OutlineGlyph)glyph;
break;
default:
;
}
return Err;
}
//*********** print outline to console ***************
int PrintOutLine(FT_OutlineGlyph Outg)
{
int Err = 0;
FT_Outline* Ol = &Outg->outline;
int Start = 0; //start index of contour
int End = 0; //end index of contour
short* pContEnd = Ol->contours; //pointer to contour end
FT_Vector* pPoint = Ol->points; //pointer to outline point
char* pFlag = Ol->tags; //pointer to flag
for(int c = 0; c < Ol->n_contours; c++)
{
std::cout << "\nContour " << c << ":\n";
End = *pContEnd++;
for(int p = Start; p <= End; p++)
{
char Ch = *pFlag++ + '0';
std::cout << "Point " << p <<": X=" << pPoint->x << " Y="<<pPoint->y << " Flag=" << Ch << "\n";
pPoint++;
}
Start = End + 1;
}
return Err;
}
//*********** get glyph index from command line *************
FT_UInt GetGlyphIndex(int argc, char* argv[], int Nr)
{
if(argc > Nr)
{
return atoi(argv[Nr]);
}
else
{
return 36;
}
}
//*********** get font name from command line *************
void GetFontName(int argc, char* argv[], int Nr, std::string& FontName)
{
if(argc > Nr)
{
FontName += argv[Nr];
}
else
{
FontName += "FreeMono.ttf";
}
}
//*********** get font size from command line *************
int GetFontSize(int argc, char* argv[], int Nr)
{
short FontSize = 50 * 64;
if(argc > Nr)
FontSize += atoi(argv[Nr]);
return FontSize;
}
//******************** M A I N ************************
// par1: FontName, par2:Glyph-Nr, par3: FontSize as FT_F26Dot6
int main(int argc, char* argv[])
{
FT_Face face;
FT_Library library;
FT_Error error;
error = FT_Init_FreeType( &library );
Check(error, "", "error initializing FT lib");
std::string FontName;
FontName = "/usr/share/fonts/truetype/freefont/";
GetFontName(argc, argv, 1, FontName);
error = FT_New_Face( library, FontName.c_str(), 0, &face );
Check(error, "", "error loading font");
FT_F26Dot6 font_size = GetFontSize(argc, argv, 3);
error = FT_Set_Char_Size( face, font_size, font_size, 72, 72 );
Check(error, "", "error setting char size");
FT_UInt glyph_index = GetGlyphIndex(argc, argv, 2);
FT_Int32 load_flags = FT_LOAD_DEFAULT;
error = FT_Load_Glyph( face, glyph_index, load_flags );
Check(error, "", "error loading glyph");
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
Check(error, "", "error getting glyph");
FT_OutlineGlyph Outg;
error = GetOutLine(glyph, &Outg);
Check(error,"", "error getting outline");
std::cout << "=======================================================\n";
std::cout << "Font: " << FontName << "\n";
std::cout << "Glyph Index: " << glyph_index << "\n";
std::cout << "=======================================================\n";
error = PrintOutLine(Outg);
Check(error,"", "error printing outline");
return 0;
}
Cairo has this capability builtin.
cairo_glyph_path() will get the glyph outline and make it the current path, and allow you to get the current path and iterate over it.