├── .gitignore ├── Counter ├── Makefile ├── README.md ├── counter.cpp ├── counter.hpp ├── counter.nmf ├── counter.pexe ├── counterView.js ├── index.html └── instance_factory.hpp ├── GettingStarted ├── Makefile ├── README.md ├── hello_tutorial.cc ├── hello_tutorial.nmf ├── hello_tutorial.pexe ├── httpd.py └── index.html ├── ImageProc ├── Makefile ├── README.md ├── deploy ├── face_detector.hpp ├── image_proc.cpp ├── image_proc.hpp ├── image_proc.nmf ├── improc_instance.hpp ├── include │ ├── catch │ │ ├── LICENSE_1_0.txt │ │ └── catch.hpp │ └── rapidjson │ │ ├── allocators.h │ │ ├── document.h │ │ ├── encodedstream.h │ │ ├── encodings.h │ │ ├── error │ │ ├── en.h │ │ └── error.h │ │ ├── filereadstream.h │ │ ├── filewritestream.h │ │ ├── internal │ │ ├── biginteger.h │ │ ├── diyfp.h │ │ ├── dtoa.h │ │ ├── ieee754.h │ │ ├── itoa.h │ │ ├── meta.h │ │ ├── pow10.h │ │ ├── stack.h │ │ ├── strfunc.h │ │ ├── strtod.h │ │ └── swap.h │ │ ├── license.txt │ │ ├── memorybuffer.h │ │ ├── memorystream.h │ │ ├── msinttypes │ │ ├── inttypes.h │ │ └── stdint.h │ │ ├── pointer.h │ │ ├── prettywriter.h │ │ ├── rapidjson.h │ │ ├── reader.h │ │ ├── stringbuffer.h │ │ └── writer.h ├── index.html ├── instance_factory.hpp ├── mmcdonne.jpg ├── processor.hpp ├── processor_barcode.cpp ├── processor_cartoon.cpp ├── processor_diff.cpp ├── processor_eyetrack.cpp ├── processor_facedetect.cpp ├── processor_facedetect.hpp ├── processor_gblur.cpp ├── processor_houghline.cpp ├── processor_id.cpp ├── processor_invert.cpp ├── processor_laplacian.cpp ├── processor_probabilistichoughline.cpp ├── processor_pulsedetect.cpp ├── processor_redchannel.cpp ├── processor_skindetect.cpp ├── processor_smiley.cpp ├── processor_sobel.cpp ├── processor_watershed.cpp ├── singleton_factory.hpp ├── smiley_200x200.png ├── test │ ├── Makefile │ └── simpledom.cpp ├── test_display.cpp ├── test_processor.cpp ├── url_loader_handler.cpp ├── url_loader_handler.hpp ├── video.js ├── video_img.js └── water_coins.jpg ├── LICENSE ├── MonteCarlo ├── Makefile ├── README.md ├── d3 │ ├── LICENSE │ └── d3.v3.min.js ├── index.html ├── instance_factory.hpp ├── mcView.js ├── mc_instance.hpp ├── model_circle.cpp ├── model_parabola.cpp ├── monte_carlo.cpp ├── monte_carlo.hpp ├── monte_carlo.nmf ├── monte_carlo.pexe ├── singleton_factory.hpp └── test_mc.cpp ├── README.md ├── Simple ├── Makefile ├── README.md ├── common.js ├── example.js ├── favicon.ico ├── index.html ├── simple_template.cpp └── simple_template.nmf └── setup.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /Counter/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 The Native Client Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | # 6 | # GNU Make based build file.  For details on GNU Make see: 7 | # http://www.gnu.org/software/make/manual/make.html 8 | # 9 | 10 | # Project Build flags 11 | WARNINGS := -Wno-long-long -Wall -Wswitch-enum -pedantic -Werror 12 | CXXFLAGS := -pthread -std=c++11 $(WARNINGS) 13 | 14 | # 15 | # Compute tool paths 16 | # 17 | GETOS := python $(NACL_SDK_ROOT)/tools/getos.py 18 | OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py 19 | OSNAME := $(shell $(GETOS)) 20 | RM := $(OSHELPERS) rm 21 | 22 | PNACL_TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_pnacl) 23 | PNACL_CXX := $(PNACL_TC_PATH)/bin/pnacl-clang++ 24 | PNACL_FINALIZE := $(PNACL_TC_PATH)/bin/pnacl-finalize 25 | CXXFLAGS := -I$(NACL_SDK_ROOT)/include $(CXXFLAGS) 26 | LDFLAGS := -L$(NACL_SDK_ROOT)/lib/pnacl/Release -lppapi_cpp -lppapi 27 | 28 | # Declare the ALL target first, to make the 'all' target the default build 29 | all: counter.pexe 30 | 31 | clean: 32 | $(RM) counter.pexe counter.bc 33 | 34 | counter.bc: counter.cpp counter.hpp instance_factory.hpp 35 | $(PNACL_CXX) -o $@ $< -O2 $(CXXFLAGS) $(LDFLAGS) 36 | 37 | counter.pexe: counter.bc 38 | $(PNACL_FINALIZE) -o $@ $< 39 | 40 | serve: 41 | python -m SimpleHTTPServer 8000 42 | -------------------------------------------------------------------------------- /Counter/README.md: -------------------------------------------------------------------------------- 1 | Counter 2 | ======= 3 | Example of transferring numeric data from javascript to NaCl. 4 | -------------------------------------------------------------------------------- /Counter/counter.cpp: -------------------------------------------------------------------------------- 1 | #include "counter.hpp" 2 | 3 | pp::Module* pp::CreateModule() { 4 | return new InstanceFactory(); 5 | } 6 | 7 | void CounterInstance::HandleMessage( const pp::Var& var_message ) { 8 | if ( !var_message.is_number() ) 9 | return; //Early exit 10 | auto x = var_message.AsInt(); 11 | count += x; 12 | const pp::Var reply( count ); 13 | PostMessage( reply ); 14 | } 15 | -------------------------------------------------------------------------------- /Counter/counter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COUNTER_HPP 2 | #define COUNTER_HPP 3 | 4 | #include "instance_factory.hpp" 5 | 6 | // The CounterInstance that stores count of values passed from webpage 7 | class CounterInstance : public pp::Instance { 8 | public: 9 | explicit CounterInstance( PP_Instance instance ) 10 | : pp::Instance(instance), count(0) {}; 11 | virtual ~CounterInstance( ){}; 12 | virtual void HandleMessage( const pp::Var& ); 13 | private: 14 | void inc(int x=0); 15 | int count; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /Counter/counter.nmf: -------------------------------------------------------------------------------- 1 | { "program" : 2 | { "portable" : 3 | { "pnacl-translate" : 4 | { "url" : "counter.pexe" 5 | } 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Counter/counter.pexe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmcd/NaCl/56e0f6a5d45bb35f13ae63d79425b329667aba3a/Counter/counter.pexe -------------------------------------------------------------------------------- /Counter/counterView.js: -------------------------------------------------------------------------------- 1 | // Global handle to module 2 | CounterModule = null; 3 | 4 | // Global status message 5 | statusText = 'NO-STATUS'; 6 | 7 | function pageDidLoad() { 8 | var listener = document.getElementById("listener"); 9 | listener.addEventListener('load', moduleDidLoad, true ); 10 | listener.addEventListener('message', handleMessage, true ); 11 | if ( CounterModule == null ) { 12 | updateStatus( 'LOADING...' ); 13 | } else { 14 | updateStatus(); 15 | } 16 | } 17 | 18 | function moduleDidLoad() { 19 | CounterModule = document.getElementById( 'counter' ); 20 | updateStatus( 'OK' ); 21 | var inc = document.getElementById( 'inc' ); 22 | inc.onclick = function() { CounterModule.postMessage(1); }; 23 | inc.disabled = false; 24 | } 25 | 26 | function handleMessage(message_event) { 27 | updateStatus(message_event.data); 28 | } 29 | 30 | function updateStatus( optMessage ) { 31 | if (optMessage) 32 | statusText = optMessage; 33 | var statusField = document.getElementById('statusField'); 34 | if (statusField) { 35 | statusField.innerHTML = statusText; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NaCl Counter 5 | 6 | 7 | 8 |

Counter using NaCl

9 | 10 |
11 | 12 | 14 |
15 | 16 |

Status NO-STATUS

17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Counter/instance_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INSTANCE_FACTORY_HPP 2 | #define INSTANCE_FACTORY_HPP 3 | 4 | #include "ppapi/cpp/instance.h" 5 | #include "ppapi/cpp/module.h" 6 | #include "ppapi/cpp/var.h" 7 | 8 | // Factory method called by the browser when first loaded 9 | namespace pp { 10 | Module* CreateModule(); 11 | }; 12 | 13 | // Module used to create instance of NaCl module on webpage 14 | template 15 | class InstanceFactory : public pp::Module { 16 | public: 17 | InstanceFactory( ){}; 18 | virtual ~InstanceFactory(){}; 19 | virtual pp::Instance* CreateInstance( PP_Instance instance ) { 20 | return new T(instance); 21 | }; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /GettingStarted/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 The Native Client Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | # 6 | # GNU Make based build file.  For details on GNU Make see: 7 | # http://www.gnu.org/software/make/manual/make.html 8 | # 9 | 10 | # 11 | # Get pepper directory for toolchain and includes. 12 | # 13 | # If NACL_SDK_ROOT is not set, then assume it can be found three directories up. 14 | # 15 | THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST))) 16 | NACL_SDK_ROOT ?= $(abspath $(dir $(THIS_MAKEFILE))../..) 17 | 18 | # Project Build flags 19 | WARNINGS := -Wno-long-long -Wall -Wswitch-enum -pedantic -Werror 20 | # CXXFLAGS := -pthread -std=gnu++98 $(WARNINGS) 21 | CXXFLAGS := -pthread -std=c++11 $(WARNINGS) 22 | 23 | # 24 | # Compute tool paths 25 | # 26 | GETOS := python $(NACL_SDK_ROOT)/tools/getos.py 27 | OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py 28 | OSNAME := $(shell $(GETOS)) 29 | RM := $(OSHELPERS) rm 30 | 31 | PNACL_TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_pnacl) 32 | PNACL_CXX := $(PNACL_TC_PATH)/bin/pnacl-clang++ 33 | PNACL_FINALIZE := $(PNACL_TC_PATH)/bin/pnacl-finalize 34 | CXXFLAGS := -I$(NACL_SDK_ROOT)/include -std=c++11 35 | LDFLAGS := -L$(NACL_SDK_ROOT)/lib/pnacl/Release -lppapi_cpp -lppapi 36 | 37 | # 38 | # Disable DOS PATH warning when using Cygwin based tools Windows 39 | # 40 | CYGWIN ?= nodosfilewarning 41 | export CYGWIN 42 | 43 | 44 | # Declare the ALL target first, to make the 'all' target the default build 45 | all: hello_tutorial.pexe 46 | 47 | clean: 48 | $(RM) hello_tutorial.pexe hello_tutorial.bc 49 | 50 | hello_tutorial.bc: hello_tutorial.cc 51 | $(PNACL_CXX) -o $@ $< -O2 $(CXXFLAGS) $(LDFLAGS) 52 | 53 | hello_tutorial.pexe: hello_tutorial.bc 54 | $(PNACL_FINALIZE) -o $@ $< 55 | 56 | 57 | # 58 | # Makefile target to run the SDK's simple HTTP server and serve this example. 59 | # 60 | HTTPD_PY := python httpd.py 61 | 62 | .PHONY: serve 63 | serve: all 64 | $(HTTPD_PY) -C $(CURDIR) 65 | -------------------------------------------------------------------------------- /GettingStarted/README.md: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | Getting Started example from Pepper 31. 4 | Includes the modifications described in the tutorial, plus use of 5 | some C++11 features. 6 | -------------------------------------------------------------------------------- /GettingStarted/hello_tutorial.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | /// @file hello_tutorial.cc 6 | /// This example demonstrates loading, running and scripting a very simple NaCl 7 | /// module. To load the NaCl module, the browser first looks for the 8 | /// CreateModule() factory method (at the end of this file). It calls 9 | /// CreateModule() once to load the module code. After the code is loaded, 10 | /// CreateModule() is not called again. 11 | /// 12 | /// Once the code is loaded, the browser calls the CreateInstance() 13 | /// method on the object returned by CreateModule(). It calls CreateInstance() 14 | /// each time it encounters an tag that references your NaCl module. 15 | /// 16 | /// The browser can talk to your NaCl module via the postMessage() Javascript 17 | /// function. When you call postMessage() on your NaCl module from the browser, 18 | /// this becomes a call to the HandleMessage() method of your pp::Instance 19 | /// subclass. You can send messages back to the browser by calling the 20 | /// PostMessage() method on your pp::Instance. Note that these two methods 21 | /// (postMessage() in Javascript and PostMessage() in C++) are asynchronous. 22 | /// This means they return immediately - there is no waiting for the message 23 | /// to be handled. This has implications in your program design, particularly 24 | /// when mutating property values that are exposed to both the browser and the 25 | /// NaCl module. 26 | 27 | #include "ppapi/cpp/instance.h" 28 | #include "ppapi/cpp/module.h" 29 | #include "ppapi/cpp/var.h" 30 | 31 | namespace { 32 | // The expected string sent by the browser 33 | const std::string kHelloString( "hello" ); 34 | // The string sent back to the browser in response to hello 35 | const std::string kReplyString("Hello from NaCl!"); 36 | } 37 | 38 | /// The Instance class. One of these exists for each instance of your NaCl 39 | /// module on the web page. The browser will ask the Module object to create 40 | /// a new Instance for each occurrence of the tag that has these 41 | /// attributes: 42 | /// src="hello_tutorial.nmf" 43 | /// type="application/x-pnacl" 44 | /// To communicate with the browser, you must override HandleMessage() to 45 | /// receive messages from the browser, and use PostMessage() to send messages 46 | /// back to the browser. Note that this interface is asynchronous. 47 | class HelloTutorialInstance : public pp::Instance { 48 | public: 49 | /// The constructor creates the plugin-side instance. 50 | /// @param[in] instance the handle to the browser-side plugin instance. 51 | explicit HelloTutorialInstance(PP_Instance instance) : pp::Instance(instance) 52 | {} 53 | virtual ~HelloTutorialInstance() {} 54 | 55 | /// Handler for messages coming in from the browser via postMessage(). The 56 | /// @a var_message can contain be any pp:Var type; for example int, string 57 | /// Array or Dictinary. Please see the pp:Var documentation for more details. 58 | /// @param[in] var_message The message posted by the browser. 59 | virtual void HandleMessage(const pp::Var& var_message) { 60 | // TODO(sdk_user): 1. Make this function handle the incoming message. 61 | if ( !var_message.is_string()) 62 | return; // Early exit 63 | // Convert from var string to std::string 64 | // std::string message = var_message.AsString(); 65 | auto message = var_message.AsString(); 66 | if ( message == kHelloString ) { 67 | pp::Var var_reply( kReplyString ); 68 | PostMessage( var_reply ); 69 | } 70 | } 71 | }; 72 | 73 | /// The Module class. The browser calls the CreateInstance() method to create 74 | /// an instance of your NaCl module on the web page. The browser creates a new 75 | /// instance for each tag with type="application/x-pnacl". 76 | class HelloTutorialModule : public pp::Module { 77 | public: 78 | HelloTutorialModule() : pp::Module() {} 79 | virtual ~HelloTutorialModule() {} 80 | 81 | /// Create and return a HelloTutorialInstance object. 82 | /// @param[in] instance The browser-side instance. 83 | /// @return the plugin-side instance. 84 | virtual pp::Instance* CreateInstance(PP_Instance instance) { 85 | return new HelloTutorialInstance(instance); 86 | } 87 | }; 88 | 89 | namespace pp { 90 | /// Factory function called by the browser when the module is first loaded. 91 | /// The browser keeps a singleton of this module. It calls the 92 | /// CreateInstance() method on the object you return to make instances. There 93 | /// is one instance per tag on the page. This is the main binding 94 | /// point for your NaCl module with the browser. 95 | Module* CreateModule() { 96 | return new HelloTutorialModule(); 97 | } 98 | } // namespace pp 99 | -------------------------------------------------------------------------------- /GettingStarted/hello_tutorial.nmf: -------------------------------------------------------------------------------- 1 | { 2 | "program": { 3 | "portable": { 4 | "pnacl-translate": { 5 | "url": "hello_tutorial.pexe" 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /GettingStarted/hello_tutorial.pexe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmcd/NaCl/56e0f6a5d45bb35f13ae63d79425b329667aba3a/GettingStarted/hello_tutorial.pexe -------------------------------------------------------------------------------- /GettingStarted/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | hello_tutorial 13 | 14 | 63 | 64 | 65 | 66 |

NaCl C++ Tutorial: Getting Started

67 |

68 | 81 |

82 | 87 | 88 | 92 |
93 |

94 | 95 |

Status NO-STATUS

96 | 97 | 98 | -------------------------------------------------------------------------------- /ImageProc/Makefile: -------------------------------------------------------------------------------- 1 | # Project Build flags 2 | WARNINGS := -Wno-long-long -Wall -pedantic -Werror # -Wswitch-enum -pedantic -Werror 3 | CXXFLAGS := -pthread -std=gnu++11 $(WARNINGS) 4 | 5 | # 6 | # Compute tool paths 7 | # 8 | GETOS := python $(NACL_SDK_ROOT)/tools/getos.py 9 | OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py 10 | OSNAME := $(shell $(GETOS)) 11 | RM := $(OSHELPERS) rm 12 | 13 | PNACL_TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_pnacl) 14 | PNACL_CXX := $(PNACL_TC_PATH)/bin/pnacl-clang++ 15 | PNACL_FINALIZE := $(PNACL_TC_PATH)/bin/pnacl-finalize 16 | PNACL_CXXFLAGS := -I$(NACL_SDK_ROOT)/include $(CXXFLAGS) 17 | LDFLAGS := -lopencv_objdetect -lopencv_imgproc -lopencv_core -lz 18 | PNACL_LDFLAGS := -L$(NACL_SDK_ROOT)/lib/pnacl/Release -lppapi_cpp -lppapi -lpthread $(LDFLAGS) 19 | 20 | PROCESSORS := $(wildcard processor_*.cpp) 21 | PROC_OBJECTS := $(PROCESSORS:.cpp=.bc) 22 | 23 | IMPROC_HEADERS := image_proc.cpp image_proc.hpp instance_factory.hpp improc_instance.hpp singleton_factory.hpp 24 | 25 | # Declare the ALL target first, to make the 'all' target the default build 26 | all: image_proc.pexe 27 | 28 | # Create individual test 29 | .PHONY: test 30 | test: 31 | g++ -g -o test_display test_display.cpp $(PROC) -std=c++0x -lopencv_highgui $(LDFLAGS) 32 | 33 | .PHONY: test_processor 34 | test_processor: test_processor.cpp singleton_factory.hpp $(PROCESSORS) 35 | g++ -g -o test_processor test_processor.cpp $(PROCESSORS) -std=c++0x $(LDFLAGS) 36 | 37 | clean: 38 | $(RM) image_proc.pexe image_proc.bc 39 | 40 | #$(PROC_OBJECTS): $(PROCESSORS) singleton_factory.hpp 41 | # $(PNACL_CXX) -o $@ $< -O2 $(CXXFLAGS) $(LDFLAGS) 42 | 43 | image_proc.bc: $(IMPROC_HEADERS) $(PROCESSORS) url_loader_handler.cpp 44 | $(PNACL_CXX) -o $@ $< $(PROCESSORS) url_loader_handler.cpp -O2 $(PNACL_CXXFLAGS) $(PNACL_LDFLAGS) 45 | 46 | image_proc.pexe: image_proc.bc 47 | $(PNACL_FINALIZE) -o $@ $< 48 | 49 | serve: 50 | python -m SimpleHTTPServer 8000 51 | -------------------------------------------------------------------------------- /ImageProc/README.md: -------------------------------------------------------------------------------- 1 | Image Processing 2 | ================ 3 | Image processing using Native Client. The goal of this project is to use 4 | the C++ OpenCV image processing library to do realtime image processing of 5 | the webcam feed. 6 | 7 | Implementation 8 | -------------- 9 | Rough plan for next few commits: 10 | 11 | - [x] Hidden HTML5 __video__ element sourced from navigator.getUserMedia (webcam). 12 | - [x] Canvas element samples video every 20ms and draws on the canvas. 13 | - [x] Send canvas image as ArrayBuffer to Native Client. 14 | - [x] NaCl echoes image that has been received. 15 | - [x] Javascript puts echoed image to __processed__ canvas. 16 | - [x] Start playing with OpenCV image processing. 17 | - [x] Use strategy pattern on the C++ side to register new image 18 | processors. 19 | - [x] Modify NaCl getVersion interface to return list of available processors. 20 | - [x] Use returned list of processors to populate js list selector. 21 | - [ ] Get the [Pulse Detection](http://people.csail.mit.edu/mrub/vidmag/) filter working. 22 | - [x] Get the [Detecting 23 | Barcodes](http://www.pyimagesearch.com/2014/11/24/detecting-barcodes-images-python-opencv) demo working. 24 | - [x] Simple cartoon filter. 25 | - [x] Face detection. 26 | 27 | [Try it out!](https://www.matt-mcdonnell.com/code/NaCl/ImageProc/index.html) - you may need 28 | to clear the cache to see any updates. To do this open Chrome Developer Tools (Ctrl-Shift-i or F12), 29 | then click and hold Reload, choose "Empty Cache and Hard Reload" from the popup menu. Popup menu may 30 | only appear if you have a cached page i.e. have previously visited. 31 | 32 | Build Setup 33 | ----------- 34 | UPDATED: Please see setup.txt in parent directory for a step by step setup on a new Ubuntu server. 35 | 36 | There are a few steps needed to configure in order to use OpenCV with NaCl. 37 | Fortunately, once you become aware of the existence of [NaCl Ports](https://code.google.com/p/naclports/) 38 | they are fairly straight forward. 39 | 40 | 1. Install [Depo Tools](http://dev.chromium.org/developers/how-tos/install-depot-tools). 41 | 2. [Check out the NaCl Ports](https://code.google.com/p/naclports/wiki/HowTo_Checkout). 42 | 2. ~~Follow the [Install guide for SDL](https://code.google.com/p/naclports/wiki/InstallingSDL), 43 | replacing __sdl__ with __opencv__ and choosing pnacl as the architecture to 44 | build.~~ 45 | Seems like the original instructions have been deleted, and didn't cover 46 | which branch to use in any event. cd to the dir where you've checked 47 | out nacl_ports (for me ~/Work/ExternCode/nacl_ports/src ) with depotools 48 | then change to the branch that matches NACL_SDK_ROOT 49 | 50 | git checkout pepper_40
51 | NACL_ARCH=pnacl make opencv 52 | 53 | The build itself took about 15 minutes on my Intel i3 dual core laptop. 54 | 55 | 3. Add the opencv libraries and zlib to the build arguments: 56 | 57 | LDFLAGS := -L$(NACL_SDK_ROOT)/lib/pnacl/Release -lppapi_cpp -lppapi -lopencv_core -lz 58 | 59 | Updating NaCl and NaCl Ports 60 | ---------------------------- 61 | NaCl updates on around the same release cycle as the Chrome browser. 62 | Chrome itself is backwards compatible but it's still a good idea to keep 63 | roughly up to date. 64 | 65 | Here we assume that the NaCl SDK has been installed in NACL_ROOT 66 | (NACL_SDK_ROOT will be under this), and NaCl ports has been installed in 67 | PORTS_ROOT. On my machine these are ~/Work/ExternCode/nacl_sdk and 68 | ~/Work/ExternCode/nacl_ports respectively. 69 | 70 | 1. Update NaCl SDK 71 | - cd NACL_ROOT 72 | - ./naclsdk update 73 | 2. Update NACL_SDK_ROOT environment variable e.g. NACL_ROOT/pepper_41 74 | 3. Update ports 75 | - cd PORTS_ROOT 76 | - cd src 77 | - git checkout -b pepper_41 origin/pepper_41 78 | - gclient sync 79 | - (If that fails, cd .. vim .gclient and set managed=False) 80 | 81 | LICENSE 82 | ------- 83 | BSD 84 | -------------------------------------------------------------------------------- /ImageProc/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sshfs $SERVER_ID:$SERVER_IMAGEPROC_LOC $SERVER_MOUNT 3 | echo Copying files to server 4 | cp $LOCAL_IMAGEPROC_LOC/{image_proc.pexe,image_proc.nmf,index.html,video.js,video_img.js,smiley_200x200.png} $SERVER_MOUNT 5 | echo Unmounting sshfs 6 | fusermount -u $SERVER_MOUNT 7 | -------------------------------------------------------------------------------- /ImageProc/face_detector.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FACE_DETECTOR_HPP 2 | #define FACE_DETECTOR_HPP 3 | 4 | #include "processor.hpp" 5 | 6 | class FaceDetector : public Processor { 7 | public: 8 | virtual void detectFaces(const cv::Mat, std::vector&)=0; 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /ImageProc/image_proc.cpp: -------------------------------------------------------------------------------- 1 | #include "improc_instance.hpp" 2 | #include "singleton_factory.hpp" 3 | #include "url_loader_handler.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | pp::Module* pp::CreateModule() 9 | { 10 | return new InstanceFactory(); 11 | } 12 | 13 | void ImageProcInstance::Process( cv::Mat im) 14 | { 15 | auto result = (*processor)( im ); 16 | auto nBytes = result.elemSize() * result.total(); 17 | pp::VarDictionary msg; 18 | pp::VarArrayBuffer data(nBytes); 19 | uint8_t* copy = static_cast( data.Map()); 20 | memcpy( copy, result.data, nBytes ); 21 | 22 | msg.Set( "Type", "completed" ); 23 | msg.Set( "Data", data ); 24 | msg.Set( "Parameters", processor->getParameters()); 25 | PostMessage( msg ); 26 | } 27 | 28 | void ImageProcInstance::PostTest() 29 | { 30 | pp::VarDictionary msg; 31 | msg.Set( "Type", "completed" ); 32 | msg.Set( "Data", "Processed ok" ); 33 | PostMessage( msg ); 34 | } 35 | 36 | void ImageProcInstance::SendStatus(const std::string& status) 37 | { 38 | pp::VarDictionary msg; 39 | msg.Set( "Type", "status" ); 40 | msg.Set( "Message", status ); 41 | PostMessage( msg ); 42 | } 43 | 44 | 45 | void ImageProcInstance::HandleMessage( const pp::Var& var_message ) 46 | { 47 | // Interface: receive a { cmd: ..., args... } dictionary 48 | pp::VarDictionary var_dict( var_message ); 49 | auto cmd = var_dict.Get( "cmd" ).AsString(); 50 | if ( cmd == "process" ) { 51 | 52 | // Message is number of simulations to run 53 | auto width = var_dict.Get("width").AsInt(); 54 | auto height = var_dict.Get("height").AsInt(); 55 | auto data = pp::VarArrayBuffer( var_dict.Get("data") ); 56 | auto selectedProcessor = var_dict.Get("processor").AsString(); 57 | bool newProcessor = selectedProcessor != processorName; 58 | if ( newProcessor ) { 59 | SendStatus("Creating processor factory"); 60 | auto processorFactory = SingletonFactory< 61 | std::function()> >::getInstance(); 62 | SendStatus("Creating processor"); 63 | processor = processorFactory.getObject( selectedProcessor )(); 64 | processorName = selectedProcessor; 65 | } else { 66 | SendStatus("Reusing processor"); 67 | } 68 | // Convert data to CMat 69 | // SendStatus("Casting to byte array"); 70 | uint8_t* byteData = static_cast(data.Map()); 71 | // SendStatus("Creating cv::Mat"); 72 | auto Img = cv::Mat(height, width, CV_8UC4, byteData ); 73 | // SendStatus("Calling processing"); 74 | 75 | // Special case: Smiley 76 | if ( (selectedProcessor == "Smiley!") && newProcessor ) { 77 | // Only send the image data for overlay on the first time we change 78 | // processor 79 | pp::VarDictionary sm_var_dict( var_dict.Get( "args" )); 80 | auto sm_width = sm_var_dict.Get("width").AsInt(); 81 | auto sm_height = sm_var_dict.Get("height").AsInt(); 82 | auto sm_data = pp::VarArrayBuffer( sm_var_dict.Get("data") ); 83 | uint8_t* sm_byteData = static_cast(sm_data.Map()); 84 | auto sm_Img = cv::Mat(sm_height, sm_width, CV_8UC4, sm_byteData ); 85 | processor->init( sm_Img ); 86 | } else if ( var_dict.HasKey( "args" ) ) { 87 | // Args key is json string that processor will parse 88 | auto json = var_dict.Get("args").AsString(); 89 | processor->init( json.c_str() ); 90 | } 91 | Process( Img ); 92 | } else if ( cmd == "test" ) { 93 | PostTest(); 94 | } else if ( cmd == "echo" ) { 95 | auto data = pp::VarArrayBuffer( var_dict.Get("data") ); 96 | // auto result = data.is_array_buffer(); 97 | pp::VarDictionary msg; 98 | msg.Set( "Type", "completed" ); 99 | msg.Set( "Data", data ); 100 | PostMessage( msg ); 101 | } else if ( cmd == "load" ) { 102 | // Load resource URL 103 | auto url = var_dict.Get( "url" ).AsString(); 104 | URLLoaderHandler* handler = URLLoaderHandler::Create(this, url); 105 | if (handler != NULL) { 106 | // Starts asynchronous download. When download is finished or when an 107 | // error occurs, |handler| posts the results back to the browser 108 | // vis PostMessage and self-destroys. 109 | handler->Start(); 110 | } 111 | } else { 112 | // Disable simulation - background thread will see this at start of 113 | // next iteration and terminate early 114 | run_simulation_ = false; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /ImageProc/image_proc.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_PROC_HPP 2 | #define IMAGE_PROC_HPP 3 | 4 | #include 5 | 6 | class ImageProc { 7 | public: 8 | explicit ImageProc() { 9 | }; 10 | virtual ~ImageProc() {}; 11 | cv::Mat process( std::function const& f, cv::Mat im ) { 12 | return f(im); 13 | }; 14 | cv::Mat process(cv::Mat im) { 15 | auto f = [](cv::Mat x){ return x; }; 16 | return process(f,im); 17 | } 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ImageProc/image_proc.nmf: -------------------------------------------------------------------------------- 1 | { "program" : 2 | { "portable" : 3 | { "pnacl-translate" : 4 | { "url" : "image_proc.pexe" 5 | } 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ImageProc/improc_instance.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IMPROC_INSTANCE 2 | #define IMPROC_INSTANCE 3 | 4 | #include "singleton_factory.hpp" 5 | #include "instance_factory.hpp" 6 | #include "image_proc.hpp" 7 | #include "ppapi/cpp/var_dictionary.h" 8 | #include "ppapi/cpp/var_array.h" 9 | #include "ppapi/cpp/var_array_buffer.h" 10 | #include "ppapi/utility/completion_callback_factory.h" 11 | #include "ppapi/utility/threading/simple_thread.h" 12 | 13 | // The ImageProcInstance that stores 14 | class ImageProcInstance : public pp::Instance { 15 | public: 16 | explicit ImageProcInstance( PP_Instance instance ) 17 | : pp::Instance(instance), callback_factory_(this), proc_thread_(this) {}; 18 | virtual ~ImageProcInstance( ){ proc_thread_.Join(); }; 19 | virtual void HandleMessage( const pp::Var& ); 20 | virtual bool Init(uint32_t /*argc*/, 21 | const char * /*argn*/ [], 22 | const char * /*argv*/ []) { 23 | proc_thread_.Start(); 24 | proc_thread_.message_loop().PostWork( 25 | callback_factory_.NewCallback( &ImageProcInstance::Version )); 26 | return true; 27 | } 28 | 29 | private: 30 | bool run_simulation_; 31 | std::string processorName; // Name of currently selected processor 32 | std::unique_ptr processor; 33 | pp::CompletionCallbackFactory callback_factory_; 34 | pp::SimpleThread proc_thread_; // Thread for image processor 35 | void Process(cv::Mat); 36 | void PostTest(); 37 | void SendStatus(const std::string& status); 38 | pp::VarDictionary PostResponse( cv::Mat ); 39 | void Version( int32_t ) { 40 | pp::VarDictionary msg; 41 | msg.Set( "Type", "version" ); 42 | msg.Set( "Version", "Image Processor 0.4.1" ); 43 | // Get processor 44 | auto processorFactory = SingletonFactory()>>::getInstance(); 45 | auto processorList = processorFactory.getNames(); 46 | pp::VarArray msgProcessorList; 47 | for ( size_t i=0; i < processorList.size(); i ++ ) { 48 | msgProcessorList.Set( i, processorList[i] ); 49 | } 50 | msg.Set( "Processors", msgProcessorList ); 51 | PostMessage( msg ); 52 | } 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /ImageProc/include/catch/LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/error/en.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_EN_H__ 16 | #define RAPIDJSON_ERROR_EN_H__ 17 | 18 | #include "error.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Maps error code of parsing into error message. 23 | /*! 24 | \ingroup RAPIDJSON_ERRORS 25 | \param parseErrorCode Error code obtained in parsing. 26 | \return the error message. 27 | \note User can make a copy of this function for localization. 28 | Using switch-case is safer for future modification of error codes. 29 | */ 30 | inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { 31 | switch (parseErrorCode) { 32 | case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); 33 | 34 | case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); 35 | case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); 36 | 37 | case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); 38 | 39 | case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); 40 | case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); 41 | case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); 42 | 43 | case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); 44 | 45 | case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); 46 | case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); 47 | case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); 48 | case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); 49 | case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); 50 | 51 | case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); 52 | case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); 53 | case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); 54 | 55 | case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); 56 | case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); 57 | 58 | default: 59 | return RAPIDJSON_ERROR_STRING("Unknown error."); 60 | } 61 | } 62 | 63 | RAPIDJSON_NAMESPACE_END 64 | 65 | #endif // RAPIDJSON_ERROR_EN_H__ 66 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/error/error.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_ERROR_ERROR_H__ 16 | #define RAPIDJSON_ERROR_ERROR_H__ 17 | 18 | #include "../rapidjson.h" 19 | 20 | /*! \file error.h */ 21 | 22 | /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // RAPIDJSON_ERROR_CHARTYPE 26 | 27 | //! Character type of error messages. 28 | /*! \ingroup RAPIDJSON_ERRORS 29 | The default character type is \c char. 30 | On Windows, user can define this macro as \c TCHAR for supporting both 31 | unicode/non-unicode settings. 32 | */ 33 | #ifndef RAPIDJSON_ERROR_CHARTYPE 34 | #define RAPIDJSON_ERROR_CHARTYPE char 35 | #endif 36 | 37 | /////////////////////////////////////////////////////////////////////////////// 38 | // RAPIDJSON_ERROR_STRING 39 | 40 | //! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. 41 | /*! \ingroup RAPIDJSON_ERRORS 42 | By default this conversion macro does nothing. 43 | On Windows, user can define this macro as \c _T(x) for supporting both 44 | unicode/non-unicode settings. 45 | */ 46 | #ifndef RAPIDJSON_ERROR_STRING 47 | #define RAPIDJSON_ERROR_STRING(x) x 48 | #endif 49 | 50 | RAPIDJSON_NAMESPACE_BEGIN 51 | 52 | /////////////////////////////////////////////////////////////////////////////// 53 | // ParseErrorCode 54 | 55 | //! Error code of parsing. 56 | /*! \ingroup RAPIDJSON_ERRORS 57 | \see GenericReader::Parse, GenericReader::GetParseErrorCode 58 | */ 59 | enum ParseErrorCode { 60 | kParseErrorNone = 0, //!< No error. 61 | 62 | kParseErrorDocumentEmpty, //!< The document is empty. 63 | kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. 64 | 65 | kParseErrorValueInvalid, //!< Invalid value. 66 | 67 | kParseErrorObjectMissName, //!< Missing a name for object member. 68 | kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. 69 | kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. 70 | 71 | kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. 72 | 73 | kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. 74 | kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. 75 | kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. 76 | kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. 77 | kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. 78 | 79 | kParseErrorNumberTooBig, //!< Number too big to be stored in double. 80 | kParseErrorNumberMissFraction, //!< Miss fraction part in number. 81 | kParseErrorNumberMissExponent, //!< Miss exponent in number. 82 | 83 | kParseErrorTermination, //!< Parsing was terminated. 84 | kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. 85 | }; 86 | 87 | //! Result of parsing (wraps ParseErrorCode) 88 | /*! 89 | \ingroup RAPIDJSON_ERRORS 90 | \code 91 | Document doc; 92 | ParseResult ok = doc.Parse("[42]"); 93 | if (!ok) { 94 | fprintf(stderr, "JSON parse error: %s (%u)", 95 | GetParseError_En(ok.Code()), ok.Offset()); 96 | exit(EXIT_FAILURE); 97 | } 98 | \endcode 99 | \see GenericReader::Parse, GenericDocument::Parse 100 | */ 101 | struct ParseResult { 102 | 103 | //! Default constructor, no error. 104 | ParseResult() : code_(kParseErrorNone), offset_(0) {} 105 | //! Constructor to set an error. 106 | ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} 107 | 108 | //! Get the error code. 109 | ParseErrorCode Code() const { return code_; } 110 | //! Get the error offset, if \ref IsError(), 0 otherwise. 111 | size_t Offset() const { return offset_; } 112 | 113 | //! Conversion to \c bool, returns \c true, iff !\ref IsError(). 114 | operator bool() const { return !IsError(); } 115 | //! Whether the result is an error. 116 | bool IsError() const { return code_ != kParseErrorNone; } 117 | 118 | bool operator==(const ParseResult& that) const { return code_ == that.code_; } 119 | bool operator==(ParseErrorCode code) const { return code_ == code; } 120 | friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } 121 | 122 | //! Reset error code. 123 | void Clear() { Set(kParseErrorNone); } 124 | //! Update error code and offset. 125 | void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } 126 | 127 | private: 128 | ParseErrorCode code_; 129 | size_t offset_; 130 | }; 131 | 132 | //! Function pointer type of GetParseError(). 133 | /*! \ingroup RAPIDJSON_ERRORS 134 | 135 | This is the prototype for \c GetParseError_X(), where \c X is a locale. 136 | User can dynamically change locale in runtime, e.g.: 137 | \code 138 | GetParseErrorFunc GetParseError = GetParseError_En; // or whatever 139 | const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); 140 | \endcode 141 | */ 142 | typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); 143 | 144 | RAPIDJSON_NAMESPACE_END 145 | 146 | #endif // RAPIDJSON_ERROR_ERROR_H__ 147 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/filereadstream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEREADSTREAM_H_ 16 | #define RAPIDJSON_FILEREADSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! File byte stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileReadStream { 28 | public: 29 | typedef char Ch; //!< Character type (byte). 30 | 31 | //! Constructor. 32 | /*! 33 | \param fp File pointer opened for read. 34 | \param buffer user-supplied buffer. 35 | \param bufferSize size of buffer in bytes. Must >=4 bytes. 36 | */ 37 | FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 38 | RAPIDJSON_ASSERT(fp_ != 0); 39 | RAPIDJSON_ASSERT(bufferSize >= 4); 40 | Read(); 41 | } 42 | 43 | Ch Peek() const { return *current_; } 44 | Ch Take() { Ch c = *current_; Read(); return c; } 45 | size_t Tell() const { return count_ + static_cast(current_ - buffer_); } 46 | 47 | // Not implemented 48 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 49 | void Flush() { RAPIDJSON_ASSERT(false); } 50 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 51 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 52 | 53 | // For encoding detection only. 54 | const Ch* Peek4() const { 55 | return (current_ + 4 <= bufferLast_) ? current_ : 0; 56 | } 57 | 58 | private: 59 | void Read() { 60 | if (current_ < bufferLast_) 61 | ++current_; 62 | else if (!eof_) { 63 | count_ += readCount_; 64 | readCount_ = fread(buffer_, 1, bufferSize_, fp_); 65 | bufferLast_ = buffer_ + readCount_ - 1; 66 | current_ = buffer_; 67 | 68 | if (readCount_ < bufferSize_) { 69 | buffer_[readCount_] = '\0'; 70 | ++bufferLast_; 71 | eof_ = true; 72 | } 73 | } 74 | } 75 | 76 | std::FILE* fp_; 77 | Ch *buffer_; 78 | size_t bufferSize_; 79 | Ch *bufferLast_; 80 | Ch *current_; 81 | size_t readCount_; 82 | size_t count_; //!< Number of characters read 83 | bool eof_; 84 | }; 85 | 86 | RAPIDJSON_NAMESPACE_END 87 | 88 | #endif // RAPIDJSON_FILESTREAM_H_ 89 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/filewritestream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_FILEWRITESTREAM_H_ 16 | #define RAPIDJSON_FILEWRITESTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | #include 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Wrapper of C file stream for input using fread(). 24 | /*! 25 | \note implements Stream concept 26 | */ 27 | class FileWriteStream { 28 | public: 29 | typedef char Ch; //!< Character type. Only support char. 30 | 31 | FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 32 | RAPIDJSON_ASSERT(fp_ != 0); 33 | } 34 | 35 | void Put(char c) { 36 | if (current_ >= bufferEnd_) 37 | Flush(); 38 | 39 | *current_++ = c; 40 | } 41 | 42 | void PutN(char c, size_t n) { 43 | size_t avail = static_cast(bufferEnd_ - current_); 44 | while (n > avail) { 45 | std::memset(current_, c, avail); 46 | current_ += avail; 47 | Flush(); 48 | n -= avail; 49 | avail = static_cast(bufferEnd_ - current_); 50 | } 51 | 52 | if (n > 0) { 53 | std::memset(current_, c, n); 54 | current_ += n; 55 | } 56 | } 57 | 58 | void Flush() { 59 | if (current_ != buffer_) { 60 | size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); 61 | if (result < static_cast(current_ - buffer_)) { 62 | // failure deliberately ignored at this time 63 | // added to avoid warn_unused_result build errors 64 | } 65 | current_ = buffer_; 66 | } 67 | } 68 | 69 | // Not implemented 70 | char Peek() const { RAPIDJSON_ASSERT(false); return 0; } 71 | char Take() { RAPIDJSON_ASSERT(false); return 0; } 72 | size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } 73 | char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 74 | size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } 75 | 76 | private: 77 | // Prohibit copy constructor & assignment operator. 78 | FileWriteStream(const FileWriteStream&); 79 | FileWriteStream& operator=(const FileWriteStream&); 80 | 81 | std::FILE* fp_; 82 | char *buffer_; 83 | char *bufferEnd_; 84 | char *current_; 85 | }; 86 | 87 | //! Implement specialized version of PutN() with memset() for better performance. 88 | template<> 89 | inline void PutN(FileWriteStream& stream, char c, size_t n) { 90 | stream.PutN(c, n); 91 | } 92 | 93 | RAPIDJSON_NAMESPACE_END 94 | 95 | #endif // RAPIDJSON_FILESTREAM_H_ 96 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/dtoa.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | // This is a C++ header-only implementation of Grisu2 algorithm from the publication: 16 | // Loitsch, Florian. "Printing floating-point numbers quickly and accurately with 17 | // integers." ACM Sigplan Notices 45.6 (2010): 233-243. 18 | 19 | #ifndef RAPIDJSON_DTOA_ 20 | #define RAPIDJSON_DTOA_ 21 | 22 | #include "itoa.h" // GetDigitsLut() 23 | #include "diyfp.h" 24 | #include "ieee754.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | namespace internal { 28 | 29 | #ifdef __GNUC__ 30 | RAPIDJSON_DIAG_PUSH 31 | RAPIDJSON_DIAG_OFF(effc++) 32 | #endif 33 | 34 | inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { 35 | while (rest < wp_w && delta - rest >= ten_kappa && 36 | (rest + ten_kappa < wp_w || /// closer 37 | wp_w - rest > rest + ten_kappa - wp_w)) { 38 | buffer[len - 1]--; 39 | rest += ten_kappa; 40 | } 41 | } 42 | 43 | inline unsigned CountDecimalDigit32(uint32_t n) { 44 | // Simple pure C++ implementation was faster than __builtin_clz version in this situation. 45 | if (n < 10) return 1; 46 | if (n < 100) return 2; 47 | if (n < 1000) return 3; 48 | if (n < 10000) return 4; 49 | if (n < 100000) return 5; 50 | if (n < 1000000) return 6; 51 | if (n < 10000000) return 7; 52 | if (n < 100000000) return 8; 53 | // Will not reach 10 digits in DigitGen() 54 | //if (n < 1000000000) return 9; 55 | //return 10; 56 | return 9; 57 | } 58 | 59 | inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { 60 | static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; 61 | const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); 62 | const DiyFp wp_w = Mp - W; 63 | uint32_t p1 = static_cast(Mp.f >> -one.e); 64 | uint64_t p2 = Mp.f & (one.f - 1); 65 | unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] 66 | *len = 0; 67 | 68 | while (kappa > 0) { 69 | uint32_t d = 0; 70 | switch (kappa) { 71 | case 9: d = p1 / 100000000; p1 %= 100000000; break; 72 | case 8: d = p1 / 10000000; p1 %= 10000000; break; 73 | case 7: d = p1 / 1000000; p1 %= 1000000; break; 74 | case 6: d = p1 / 100000; p1 %= 100000; break; 75 | case 5: d = p1 / 10000; p1 %= 10000; break; 76 | case 4: d = p1 / 1000; p1 %= 1000; break; 77 | case 3: d = p1 / 100; p1 %= 100; break; 78 | case 2: d = p1 / 10; p1 %= 10; break; 79 | case 1: d = p1; p1 = 0; break; 80 | default:; 81 | } 82 | if (d || *len) 83 | buffer[(*len)++] = static_cast('0' + static_cast(d)); 84 | kappa--; 85 | uint64_t tmp = (static_cast(p1) << -one.e) + p2; 86 | if (tmp <= delta) { 87 | *K += kappa; 88 | GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); 89 | return; 90 | } 91 | } 92 | 93 | // kappa = 0 94 | for (;;) { 95 | p2 *= 10; 96 | delta *= 10; 97 | char d = static_cast(p2 >> -one.e); 98 | if (d || *len) 99 | buffer[(*len)++] = static_cast('0' + d); 100 | p2 &= one.f - 1; 101 | kappa--; 102 | if (p2 < delta) { 103 | *K += kappa; 104 | GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast(kappa)]); 105 | return; 106 | } 107 | } 108 | } 109 | 110 | inline void Grisu2(double value, char* buffer, int* length, int* K) { 111 | const DiyFp v(value); 112 | DiyFp w_m, w_p; 113 | v.NormalizedBoundaries(&w_m, &w_p); 114 | 115 | const DiyFp c_mk = GetCachedPower(w_p.e, K); 116 | const DiyFp W = v.Normalize() * c_mk; 117 | DiyFp Wp = w_p * c_mk; 118 | DiyFp Wm = w_m * c_mk; 119 | Wm.f++; 120 | Wp.f--; 121 | DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); 122 | } 123 | 124 | inline char* WriteExponent(int K, char* buffer) { 125 | if (K < 0) { 126 | *buffer++ = '-'; 127 | K = -K; 128 | } 129 | 130 | if (K >= 100) { 131 | *buffer++ = static_cast('0' + static_cast(K / 100)); 132 | K %= 100; 133 | const char* d = GetDigitsLut() + K * 2; 134 | *buffer++ = d[0]; 135 | *buffer++ = d[1]; 136 | } 137 | else if (K >= 10) { 138 | const char* d = GetDigitsLut() + K * 2; 139 | *buffer++ = d[0]; 140 | *buffer++ = d[1]; 141 | } 142 | else 143 | *buffer++ = static_cast('0' + static_cast(K)); 144 | 145 | return buffer; 146 | } 147 | 148 | inline char* Prettify(char* buffer, int length, int k) { 149 | const int kk = length + k; // 10^(kk-1) <= v < 10^kk 150 | 151 | if (length <= kk && kk <= 21) { 152 | // 1234e7 -> 12340000000 153 | for (int i = length; i < kk; i++) 154 | buffer[i] = '0'; 155 | buffer[kk] = '.'; 156 | buffer[kk + 1] = '0'; 157 | return &buffer[kk + 2]; 158 | } 159 | else if (0 < kk && kk <= 21) { 160 | // 1234e-2 -> 12.34 161 | std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); 162 | buffer[kk] = '.'; 163 | return &buffer[length + 1]; 164 | } 165 | else if (-6 < kk && kk <= 0) { 166 | // 1234e-6 -> 0.001234 167 | const int offset = 2 - kk; 168 | std::memmove(&buffer[offset], &buffer[0], static_cast(length)); 169 | buffer[0] = '0'; 170 | buffer[1] = '.'; 171 | for (int i = 2; i < offset; i++) 172 | buffer[i] = '0'; 173 | return &buffer[length + offset]; 174 | } 175 | else if (length == 1) { 176 | // 1e30 177 | buffer[1] = 'e'; 178 | return WriteExponent(kk - 1, &buffer[2]); 179 | } 180 | else { 181 | // 1234e30 -> 1.234e33 182 | std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); 183 | buffer[1] = '.'; 184 | buffer[length + 1] = 'e'; 185 | return WriteExponent(kk - 1, &buffer[0 + length + 2]); 186 | } 187 | } 188 | 189 | inline char* dtoa(double value, char* buffer) { 190 | Double d(value); 191 | if (d.IsZero()) { 192 | if (d.Sign()) 193 | *buffer++ = '-'; // -0.0, Issue #289 194 | buffer[0] = '0'; 195 | buffer[1] = '.'; 196 | buffer[2] = '0'; 197 | return &buffer[3]; 198 | } 199 | else { 200 | if (value < 0) { 201 | *buffer++ = '-'; 202 | value = -value; 203 | } 204 | int length, K; 205 | Grisu2(value, buffer, &length, &K); 206 | return Prettify(buffer, length, K); 207 | } 208 | } 209 | 210 | #ifdef __GNUC__ 211 | RAPIDJSON_DIAG_POP 212 | #endif 213 | 214 | } // namespace internal 215 | RAPIDJSON_NAMESPACE_END 216 | 217 | #endif // RAPIDJSON_DTOA_ 218 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/ieee754.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_IEEE754_ 16 | #define RAPIDJSON_IEEE754_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | class Double { 24 | public: 25 | Double() {} 26 | Double(double d) : d_(d) {} 27 | Double(uint64_t u) : u_(u) {} 28 | 29 | double Value() const { return d_; } 30 | uint64_t Uint64Value() const { return u_; } 31 | 32 | double NextPositiveDouble() const { 33 | RAPIDJSON_ASSERT(!Sign()); 34 | return Double(u_ + 1).Value(); 35 | } 36 | 37 | bool Sign() const { return (u_ & kSignMask) != 0; } 38 | uint64_t Significand() const { return u_ & kSignificandMask; } 39 | int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } 40 | 41 | bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } 42 | bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } 43 | bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } 44 | bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } 45 | 46 | uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } 47 | int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } 48 | uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } 49 | 50 | static unsigned EffectiveSignificandSize(int order) { 51 | if (order >= -1021) 52 | return 53; 53 | else if (order <= -1074) 54 | return 0; 55 | else 56 | return (unsigned)order + 1074; 57 | } 58 | 59 | private: 60 | static const int kSignificandSize = 52; 61 | static const int kExponentBias = 0x3FF; 62 | static const int kDenormalExponent = 1 - kExponentBias; 63 | static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); 64 | static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); 65 | static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); 66 | static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); 67 | 68 | union { 69 | double d_; 70 | uint64_t u_; 71 | }; 72 | }; 73 | 74 | } // namespace internal 75 | RAPIDJSON_NAMESPACE_END 76 | 77 | #endif // RAPIDJSON_IEEE754_ 78 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/meta.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_META_H_ 16 | #define RAPIDJSON_INTERNAL_META_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | #ifdef __GNUC__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | #if defined(_MSC_VER) 25 | RAPIDJSON_DIAG_PUSH 26 | RAPIDJSON_DIAG_OFF(6334) 27 | #endif 28 | 29 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 30 | #include 31 | #endif 32 | 33 | //@cond RAPIDJSON_INTERNAL 34 | RAPIDJSON_NAMESPACE_BEGIN 35 | namespace internal { 36 | 37 | // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching 38 | template struct Void { typedef void Type; }; 39 | 40 | /////////////////////////////////////////////////////////////////////////////// 41 | // BoolType, TrueType, FalseType 42 | // 43 | template struct BoolType { 44 | static const bool Value = Cond; 45 | typedef BoolType Type; 46 | }; 47 | typedef BoolType TrueType; 48 | typedef BoolType FalseType; 49 | 50 | 51 | /////////////////////////////////////////////////////////////////////////////// 52 | // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr 53 | // 54 | 55 | template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; 56 | template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; 57 | template struct SelectIfCond : SelectIfImpl::template Apply {}; 58 | template struct SelectIf : SelectIfCond {}; 59 | 60 | template struct AndExprCond : FalseType {}; 61 | template <> struct AndExprCond : TrueType {}; 62 | template struct OrExprCond : TrueType {}; 63 | template <> struct OrExprCond : FalseType {}; 64 | 65 | template struct BoolExpr : SelectIf::Type {}; 66 | template struct NotExpr : SelectIf::Type {}; 67 | template struct AndExpr : AndExprCond::Type {}; 68 | template struct OrExpr : OrExprCond::Type {}; 69 | 70 | 71 | /////////////////////////////////////////////////////////////////////////////// 72 | // AddConst, MaybeAddConst, RemoveConst 73 | template struct AddConst { typedef const T Type; }; 74 | template struct MaybeAddConst : SelectIfCond {}; 75 | template struct RemoveConst { typedef T Type; }; 76 | template struct RemoveConst { typedef T Type; }; 77 | 78 | 79 | /////////////////////////////////////////////////////////////////////////////// 80 | // IsSame, IsConst, IsMoreConst, IsPointer 81 | // 82 | template struct IsSame : FalseType {}; 83 | template struct IsSame : TrueType {}; 84 | 85 | template struct IsConst : FalseType {}; 86 | template struct IsConst : TrueType {}; 87 | 88 | template 89 | struct IsMoreConst 90 | : AndExpr::Type, typename RemoveConst::Type>, 91 | BoolType::Value >= IsConst::Value> >::Type {}; 92 | 93 | template struct IsPointer : FalseType {}; 94 | template struct IsPointer : TrueType {}; 95 | 96 | /////////////////////////////////////////////////////////////////////////////// 97 | // IsBaseOf 98 | // 99 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS 100 | 101 | template struct IsBaseOf 102 | : BoolType< ::std::is_base_of::value> {}; 103 | 104 | #else // simplified version adopted from Boost 105 | 106 | template struct IsBaseOfImpl { 107 | RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); 108 | RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); 109 | 110 | typedef char (&Yes)[1]; 111 | typedef char (&No) [2]; 112 | 113 | template 114 | static Yes Check(const D*, T); 115 | static No Check(const B*, int); 116 | 117 | struct Host { 118 | operator const B*() const; 119 | operator const D*(); 120 | }; 121 | 122 | enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; 123 | }; 124 | 125 | template struct IsBaseOf 126 | : OrExpr, BoolExpr > >::Type {}; 127 | 128 | #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS 129 | 130 | 131 | ////////////////////////////////////////////////////////////////////////// 132 | // EnableIf / DisableIf 133 | // 134 | template struct EnableIfCond { typedef T Type; }; 135 | template struct EnableIfCond { /* empty */ }; 136 | 137 | template struct DisableIfCond { typedef T Type; }; 138 | template struct DisableIfCond { /* empty */ }; 139 | 140 | template 141 | struct EnableIf : EnableIfCond {}; 142 | 143 | template 144 | struct DisableIf : DisableIfCond {}; 145 | 146 | // SFINAE helpers 147 | struct SfinaeTag {}; 148 | template struct RemoveSfinaeTag; 149 | template struct RemoveSfinaeTag { typedef T Type; }; 150 | 151 | #define RAPIDJSON_REMOVEFPTR_(type) \ 152 | typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ 153 | < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type 154 | 155 | #define RAPIDJSON_ENABLEIF(cond) \ 156 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 157 | ::Type * = NULL 158 | 159 | #define RAPIDJSON_DISABLEIF(cond) \ 160 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 161 | ::Type * = NULL 162 | 163 | #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ 164 | typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 165 | ::Type 167 | 168 | #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ 169 | typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 170 | ::Type 172 | 173 | } // namespace internal 174 | RAPIDJSON_NAMESPACE_END 175 | //@endcond 176 | 177 | #if defined(__GNUC__) || defined(_MSC_VER) 178 | RAPIDJSON_DIAG_POP 179 | #endif 180 | 181 | #endif // RAPIDJSON_INTERNAL_META_H_ 182 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/pow10.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_POW10_ 16 | #define RAPIDJSON_POW10_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Computes integer powers of 10 in double (10.0^n). 24 | /*! This function uses lookup table for fast and accurate results. 25 | \param n non-negative exponent. Must <= 308. 26 | \return 10.0^n 27 | */ 28 | inline double Pow10(int n) { 29 | static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes 30 | 1e+0, 31 | 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 32 | 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, 33 | 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 34 | 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 35 | 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 36 | 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, 37 | 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, 38 | 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, 39 | 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, 40 | 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, 41 | 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, 42 | 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, 43 | 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, 44 | 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, 45 | 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, 46 | 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 47 | }; 48 | RAPIDJSON_ASSERT(n >= 0 && n <= 308); 49 | return e[n]; 50 | } 51 | 52 | } // namespace internal 53 | RAPIDJSON_NAMESPACE_END 54 | 55 | #endif // RAPIDJSON_POW10_ 56 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/stack.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STACK_H_ 16 | #define RAPIDJSON_INTERNAL_STACK_H_ 17 | 18 | #include "../rapidjson.h" 19 | #include "swap.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | namespace internal { 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // Stack 26 | 27 | //! A type-unsafe stack for storing different types of data. 28 | /*! \tparam Allocator Allocator for allocating stack memory. 29 | */ 30 | template 31 | class Stack { 32 | public: 33 | // Optimization note: Do not allocate memory for stack_ in constructor. 34 | // Do it lazily when first Push() -> Expand() -> Resize(). 35 | Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { 36 | RAPIDJSON_ASSERT(stackCapacity > 0); 37 | } 38 | 39 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 40 | Stack(Stack&& rhs) 41 | : allocator_(rhs.allocator_), 42 | ownAllocator_(rhs.ownAllocator_), 43 | stack_(rhs.stack_), 44 | stackTop_(rhs.stackTop_), 45 | stackEnd_(rhs.stackEnd_), 46 | initialCapacity_(rhs.initialCapacity_) 47 | { 48 | rhs.allocator_ = 0; 49 | rhs.ownAllocator_ = 0; 50 | rhs.stack_ = 0; 51 | rhs.stackTop_ = 0; 52 | rhs.stackEnd_ = 0; 53 | rhs.initialCapacity_ = 0; 54 | } 55 | #endif 56 | 57 | ~Stack() { 58 | Destroy(); 59 | } 60 | 61 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 62 | Stack& operator=(Stack&& rhs) { 63 | if (&rhs != this) 64 | { 65 | Destroy(); 66 | 67 | allocator_ = rhs.allocator_; 68 | ownAllocator_ = rhs.ownAllocator_; 69 | stack_ = rhs.stack_; 70 | stackTop_ = rhs.stackTop_; 71 | stackEnd_ = rhs.stackEnd_; 72 | initialCapacity_ = rhs.initialCapacity_; 73 | 74 | rhs.allocator_ = 0; 75 | rhs.ownAllocator_ = 0; 76 | rhs.stack_ = 0; 77 | rhs.stackTop_ = 0; 78 | rhs.stackEnd_ = 0; 79 | rhs.initialCapacity_ = 0; 80 | } 81 | return *this; 82 | } 83 | #endif 84 | 85 | void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { 86 | internal::Swap(allocator_, rhs.allocator_); 87 | internal::Swap(ownAllocator_, rhs.ownAllocator_); 88 | internal::Swap(stack_, rhs.stack_); 89 | internal::Swap(stackTop_, rhs.stackTop_); 90 | internal::Swap(stackEnd_, rhs.stackEnd_); 91 | internal::Swap(initialCapacity_, rhs.initialCapacity_); 92 | } 93 | 94 | void Clear() { stackTop_ = stack_; } 95 | 96 | void ShrinkToFit() { 97 | if (Empty()) { 98 | // If the stack is empty, completely deallocate the memory. 99 | Allocator::Free(stack_); 100 | stack_ = 0; 101 | stackTop_ = 0; 102 | stackEnd_ = 0; 103 | } 104 | else 105 | Resize(GetSize()); 106 | } 107 | 108 | // Optimization note: try to minimize the size of this function for force inline. 109 | // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. 110 | template 111 | RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { 112 | // Expand the stack if needed 113 | if (stackTop_ + sizeof(T) * count >= stackEnd_) 114 | Expand(count); 115 | 116 | T* ret = reinterpret_cast(stackTop_); 117 | stackTop_ += sizeof(T) * count; 118 | return ret; 119 | } 120 | 121 | template 122 | T* Pop(size_t count) { 123 | RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); 124 | stackTop_ -= count * sizeof(T); 125 | return reinterpret_cast(stackTop_); 126 | } 127 | 128 | template 129 | T* Top() { 130 | RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); 131 | return reinterpret_cast(stackTop_ - sizeof(T)); 132 | } 133 | 134 | template 135 | T* Bottom() { return (T*)stack_; } 136 | 137 | Allocator& GetAllocator() { return *allocator_; } 138 | bool Empty() const { return stackTop_ == stack_; } 139 | size_t GetSize() const { return static_cast(stackTop_ - stack_); } 140 | size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } 141 | 142 | private: 143 | template 144 | void Expand(size_t count) { 145 | // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. 146 | size_t newCapacity; 147 | if (stack_ == 0) { 148 | if (!allocator_) 149 | ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); 150 | newCapacity = initialCapacity_; 151 | } else { 152 | newCapacity = GetCapacity(); 153 | newCapacity += (newCapacity + 1) / 2; 154 | } 155 | size_t newSize = GetSize() + sizeof(T) * count; 156 | if (newCapacity < newSize) 157 | newCapacity = newSize; 158 | 159 | Resize(newCapacity); 160 | } 161 | 162 | void Resize(size_t newCapacity) { 163 | const size_t size = GetSize(); // Backup the current size 164 | stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); 165 | stackTop_ = stack_ + size; 166 | stackEnd_ = stack_ + newCapacity; 167 | } 168 | 169 | void Destroy() { 170 | Allocator::Free(stack_); 171 | RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack 172 | } 173 | 174 | // Prohibit copy constructor & assignment operator. 175 | Stack(const Stack&); 176 | Stack& operator=(const Stack&); 177 | 178 | Allocator* allocator_; 179 | Allocator* ownAllocator_; 180 | char *stack_; 181 | char *stackTop_; 182 | char *stackEnd_; 183 | size_t initialCapacity_; 184 | }; 185 | 186 | } // namespace internal 187 | RAPIDJSON_NAMESPACE_END 188 | 189 | #endif // RAPIDJSON_STACK_H_ 190 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/strfunc.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ 16 | #define RAPIDJSON_INTERNAL_STRFUNC_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Custom strlen() which works on different character types. 24 | /*! \tparam Ch Character type (e.g. char, wchar_t, short) 25 | \param s Null-terminated input string. 26 | \return Number of characters in the string. 27 | \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. 28 | */ 29 | template 30 | inline SizeType StrLen(const Ch* s) { 31 | const Ch* p = s; 32 | while (*p) ++p; 33 | return SizeType(p - s); 34 | } 35 | 36 | } // namespace internal 37 | RAPIDJSON_NAMESPACE_END 38 | 39 | #endif // RAPIDJSON_INTERNAL_STRFUNC_H_ 40 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/strtod.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRTOD_ 16 | #define RAPIDJSON_STRTOD_ 17 | 18 | #include "../rapidjson.h" 19 | #include "ieee754.h" 20 | #include "biginteger.h" 21 | #include "diyfp.h" 22 | #include "pow10.h" 23 | 24 | RAPIDJSON_NAMESPACE_BEGIN 25 | namespace internal { 26 | 27 | inline double FastPath(double significand, int exp) { 28 | if (exp < -308) 29 | return 0.0; 30 | else if (exp >= 0) 31 | return significand * internal::Pow10(exp); 32 | else 33 | return significand / internal::Pow10(-exp); 34 | } 35 | 36 | inline double StrtodNormalPrecision(double d, int p) { 37 | if (p < -308) { 38 | // Prevent expSum < -308, making Pow10(p) = 0 39 | d = FastPath(d, -308); 40 | d = FastPath(d, p + 308); 41 | } 42 | else 43 | d = FastPath(d, p); 44 | return d; 45 | } 46 | 47 | template 48 | inline T Min3(T a, T b, T c) { 49 | T m = a; 50 | if (m > b) m = b; 51 | if (m > c) m = c; 52 | return m; 53 | } 54 | 55 | inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { 56 | const Double db(b); 57 | const uint64_t bInt = db.IntegerSignificand(); 58 | const int bExp = db.IntegerExponent(); 59 | const int hExp = bExp - 1; 60 | 61 | int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; 62 | 63 | // Adjust for decimal exponent 64 | if (dExp >= 0) { 65 | dS_Exp2 += dExp; 66 | dS_Exp5 += dExp; 67 | } 68 | else { 69 | bS_Exp2 -= dExp; 70 | bS_Exp5 -= dExp; 71 | hS_Exp2 -= dExp; 72 | hS_Exp5 -= dExp; 73 | } 74 | 75 | // Adjust for binary exponent 76 | if (bExp >= 0) 77 | bS_Exp2 += bExp; 78 | else { 79 | dS_Exp2 -= bExp; 80 | hS_Exp2 -= bExp; 81 | } 82 | 83 | // Adjust for half ulp exponent 84 | if (hExp >= 0) 85 | hS_Exp2 += hExp; 86 | else { 87 | dS_Exp2 -= hExp; 88 | bS_Exp2 -= hExp; 89 | } 90 | 91 | // Remove common power of two factor from all three scaled values 92 | int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); 93 | dS_Exp2 -= common_Exp2; 94 | bS_Exp2 -= common_Exp2; 95 | hS_Exp2 -= common_Exp2; 96 | 97 | BigInteger dS = d; 98 | dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); 99 | 100 | BigInteger bS(bInt); 101 | bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); 102 | 103 | BigInteger hS(1); 104 | hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); 105 | 106 | BigInteger delta(0); 107 | dS.Difference(bS, &delta); 108 | 109 | return delta.Compare(hS); 110 | } 111 | 112 | inline bool StrtodFast(double d, int p, double* result) { 113 | // Use fast path for string-to-double conversion if possible 114 | // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ 115 | if (p > 22 && p < 22 + 16) { 116 | // Fast Path Cases In Disguise 117 | d *= internal::Pow10(p - 22); 118 | p = 22; 119 | } 120 | 121 | if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 122 | *result = FastPath(d, p); 123 | return true; 124 | } 125 | else 126 | return false; 127 | } 128 | 129 | // Compute an approximation and see if it is within 1/2 ULP 130 | inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { 131 | uint64_t significand = 0; 132 | size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 133 | for (; i < length; i++) { 134 | if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || 135 | (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) 136 | break; 137 | significand = significand * 10u + static_cast(decimals[i] - '0'); 138 | } 139 | 140 | if (i < length && decimals[i] >= '5') // Rounding 141 | significand++; 142 | 143 | size_t remaining = length - i; 144 | const unsigned kUlpShift = 3; 145 | const unsigned kUlp = 1 << kUlpShift; 146 | int error = (remaining == 0) ? 0 : kUlp / 2; 147 | 148 | DiyFp v(significand, 0); 149 | v = v.Normalize(); 150 | error <<= -v.e; 151 | 152 | const int dExp = (int)decimalPosition - (int)i + exp; 153 | 154 | int actualExp; 155 | DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); 156 | if (actualExp != dExp) { 157 | static const DiyFp kPow10[] = { 158 | DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 159 | DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 160 | DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 161 | DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 162 | DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 163 | DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 164 | DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 165 | }; 166 | int adjustment = dExp - actualExp - 1; 167 | RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); 168 | v = v * kPow10[adjustment]; 169 | if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit 170 | error += kUlp / 2; 171 | } 172 | 173 | v = v * cachedPower; 174 | 175 | error += kUlp + (error == 0 ? 0 : 1); 176 | 177 | const int oldExp = v.e; 178 | v = v.Normalize(); 179 | error <<= oldExp - v.e; 180 | 181 | const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); 182 | unsigned precisionSize = 64 - effectiveSignificandSize; 183 | if (precisionSize + kUlpShift >= 64) { 184 | unsigned scaleExp = (precisionSize + kUlpShift) - 63; 185 | v.f >>= scaleExp; 186 | v.e += scaleExp; 187 | error = (error >> scaleExp) + 1 + static_cast(kUlp); 188 | precisionSize -= scaleExp; 189 | } 190 | 191 | DiyFp rounded(v.f >> precisionSize, v.e + static_cast(precisionSize)); 192 | const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; 193 | const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; 194 | if (precisionBits >= halfWay + static_cast(error)) { 195 | rounded.f++; 196 | if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) 197 | rounded.f >>= 1; 198 | rounded.e++; 199 | } 200 | } 201 | 202 | *result = rounded.ToDouble(); 203 | 204 | return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); 205 | } 206 | 207 | inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { 208 | const BigInteger dInt(decimals, length); 209 | const int dExp = (int)decimalPosition - (int)length + exp; 210 | Double a(approx); 211 | int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); 212 | if (cmp < 0) 213 | return a.Value(); // within half ULP 214 | else if (cmp == 0) { 215 | // Round towards even 216 | if (a.Significand() & 1) 217 | return a.NextPositiveDouble(); 218 | else 219 | return a.Value(); 220 | } 221 | else // adjustment 222 | return a.NextPositiveDouble(); 223 | } 224 | 225 | inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { 226 | RAPIDJSON_ASSERT(d >= 0.0); 227 | RAPIDJSON_ASSERT(length >= 1); 228 | 229 | double result; 230 | if (StrtodFast(d, p, &result)) 231 | return result; 232 | 233 | // Trim leading zeros 234 | while (*decimals == '0' && length > 1) { 235 | length--; 236 | decimals++; 237 | decimalPosition--; 238 | } 239 | 240 | // Trim trailing zeros 241 | while (decimals[length - 1] == '0' && length > 1) { 242 | length--; 243 | decimalPosition--; 244 | exp++; 245 | } 246 | 247 | // Trim right-most digits 248 | const int kMaxDecimalDigit = 780; 249 | if ((int)length > kMaxDecimalDigit) { 250 | int delta = (int(length) - kMaxDecimalDigit); 251 | exp += delta; 252 | decimalPosition -= static_cast(delta); 253 | length = kMaxDecimalDigit; 254 | } 255 | 256 | // If too small, underflow to zero 257 | if (int(length) + exp < -324) 258 | return 0.0; 259 | 260 | if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) 261 | return result; 262 | 263 | // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison 264 | return StrtodBigInteger(result, decimals, length, decimalPosition, exp); 265 | } 266 | 267 | } // namespace internal 268 | RAPIDJSON_NAMESPACE_END 269 | 270 | #endif // RAPIDJSON_STRTOD_ 271 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/internal/swap.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_INTERNAL_SWAP_H_ 16 | #define RAPIDJSON_INTERNAL_SWAP_H_ 17 | 18 | #include "../rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | namespace internal { 22 | 23 | //! Custom swap() to avoid dependency on C++ header 24 | /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. 25 | \note This has the same semantics as std::swap(). 26 | */ 27 | template 28 | inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { 29 | T tmp = a; 30 | a = b; 31 | b = tmp; 32 | } 33 | 34 | } // namespace internal 35 | RAPIDJSON_NAMESPACE_END 36 | 37 | #endif // RAPIDJSON_INTERNAL_SWAP_H_ 38 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/license.txt: -------------------------------------------------------------------------------- 1 | Tencent is pleased to support the open source community by making RapidJSON available. 2 | 3 | Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | 5 | If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. 6 | If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. 7 | A copy of the MIT License is included in this file. 8 | 9 | Other dependencies and licenses: 10 | 11 | Open Source Software Licensed Under the BSD License: 12 | -------------------------------------------------------------------- 13 | 14 | The msinttypes r29 15 | Copyright (c) 2006-2013 Alexander Chemeris 16 | All rights reserved. 17 | 18 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 19 | 20 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 21 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 22 | * Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | Open Source Software Licensed Under the JSON License: 27 | -------------------------------------------------------------------- 28 | 29 | json.org 30 | Copyright (c) 2002 JSON.org 31 | All Rights Reserved. 32 | 33 | JSON_checker 34 | Copyright (c) 2002 JSON.org 35 | All Rights Reserved. 36 | 37 | 38 | Terms of the JSON License: 39 | --------------------------------------------------- 40 | 41 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 42 | 43 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 44 | 45 | The Software shall be used for Good, not Evil. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 48 | 49 | 50 | Terms of the MIT License: 51 | -------------------------------------------------------------------- 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 56 | 57 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/memorybuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYBUFFER_H_ 16 | #define RAPIDJSON_MEMORYBUFFER_H_ 17 | 18 | #include "rapidjson.h" 19 | #include "internal/stack.h" 20 | 21 | RAPIDJSON_NAMESPACE_BEGIN 22 | 23 | //! Represents an in-memory output byte stream. 24 | /*! 25 | This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. 26 | 27 | It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. 28 | 29 | Differences between MemoryBuffer and StringBuffer: 30 | 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 31 | 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. 32 | 33 | \tparam Allocator type for allocating memory buffer. 34 | \note implements Stream concept 35 | */ 36 | template 37 | struct GenericMemoryBuffer { 38 | typedef char Ch; // byte 39 | 40 | GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 41 | 42 | void Put(Ch c) { *stack_.template Push() = c; } 43 | void Flush() {} 44 | 45 | void Clear() { stack_.Clear(); } 46 | void ShrinkToFit() { stack_.ShrinkToFit(); } 47 | Ch* Push(size_t count) { return stack_.template Push(count); } 48 | void Pop(size_t count) { stack_.template Pop(count); } 49 | 50 | const Ch* GetBuffer() const { 51 | return stack_.template Bottom(); 52 | } 53 | 54 | size_t GetSize() const { return stack_.GetSize(); } 55 | 56 | static const size_t kDefaultCapacity = 256; 57 | mutable internal::Stack stack_; 58 | }; 59 | 60 | typedef GenericMemoryBuffer<> MemoryBuffer; 61 | 62 | //! Implement specialized version of PutN() with memset() for better performance. 63 | template<> 64 | inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { 65 | std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); 66 | } 67 | 68 | RAPIDJSON_NAMESPACE_END 69 | 70 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 71 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/memorystream.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_MEMORYSTREAM_H_ 16 | #define RAPIDJSON_MEMORYSTREAM_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | RAPIDJSON_NAMESPACE_BEGIN 21 | 22 | //! Represents an in-memory input byte stream. 23 | /*! 24 | This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. 25 | 26 | It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. 27 | 28 | Differences between MemoryStream and StringStream: 29 | 1. StringStream has encoding but MemoryStream is a byte stream. 30 | 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. 31 | 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). 32 | \note implements Stream concept 33 | */ 34 | struct MemoryStream { 35 | typedef char Ch; // byte 36 | 37 | MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} 38 | 39 | Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } 40 | Ch Take() { return (src_ == end_) ? '\0' : *src_++; } 41 | size_t Tell() const { return static_cast(src_ - begin_); } 42 | 43 | Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } 44 | void Put(Ch) { RAPIDJSON_ASSERT(false); } 45 | void Flush() { RAPIDJSON_ASSERT(false); } 46 | size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } 47 | 48 | // For encoding detection only. 49 | const Ch* Peek4() const { 50 | return Tell() + 4 <= size_ ? src_ : 0; 51 | } 52 | 53 | const Ch* src_; //!< Current read position. 54 | const Ch* begin_; //!< Original head of the string. 55 | const Ch* end_; //!< End of stream. 56 | size_t size_; //!< Size of the stream. 57 | }; 58 | 59 | RAPIDJSON_NAMESPACE_END 60 | 61 | #endif // RAPIDJSON_MEMORYBUFFER_H_ 62 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/msinttypes/inttypes.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant inttypes.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2013 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. Neither the name of the product nor the names of its contributors may 17 | // be used to endorse or promote products derived from this software 18 | // without specific prior written permission. 19 | // 20 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 21 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 22 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | // 31 | /////////////////////////////////////////////////////////////////////////////// 32 | 33 | // The above software in this distribution may have been modified by 34 | // THL A29 Limited ("Tencent Modifications"). 35 | // All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. 36 | 37 | #ifndef _MSC_VER // [ 38 | #error "Use this header only with Microsoft Visual C++ compilers!" 39 | #endif // _MSC_VER ] 40 | 41 | #ifndef _MSC_INTTYPES_H_ // [ 42 | #define _MSC_INTTYPES_H_ 43 | 44 | #if _MSC_VER > 1000 45 | #pragma once 46 | #endif 47 | 48 | #include "stdint.h" 49 | 50 | // miloyip: VC supports inttypes.h since VC2013 51 | #if _MSC_VER >= 1800 52 | #include 53 | #else 54 | 55 | // 7.8 Format conversion of integer types 56 | 57 | typedef struct { 58 | intmax_t quot; 59 | intmax_t rem; 60 | } imaxdiv_t; 61 | 62 | // 7.8.1 Macros for format specifiers 63 | 64 | #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 65 | 66 | // The fprintf macros for signed integers are: 67 | #define PRId8 "d" 68 | #define PRIi8 "i" 69 | #define PRIdLEAST8 "d" 70 | #define PRIiLEAST8 "i" 71 | #define PRIdFAST8 "d" 72 | #define PRIiFAST8 "i" 73 | 74 | #define PRId16 "hd" 75 | #define PRIi16 "hi" 76 | #define PRIdLEAST16 "hd" 77 | #define PRIiLEAST16 "hi" 78 | #define PRIdFAST16 "hd" 79 | #define PRIiFAST16 "hi" 80 | 81 | #define PRId32 "I32d" 82 | #define PRIi32 "I32i" 83 | #define PRIdLEAST32 "I32d" 84 | #define PRIiLEAST32 "I32i" 85 | #define PRIdFAST32 "I32d" 86 | #define PRIiFAST32 "I32i" 87 | 88 | #define PRId64 "I64d" 89 | #define PRIi64 "I64i" 90 | #define PRIdLEAST64 "I64d" 91 | #define PRIiLEAST64 "I64i" 92 | #define PRIdFAST64 "I64d" 93 | #define PRIiFAST64 "I64i" 94 | 95 | #define PRIdMAX "I64d" 96 | #define PRIiMAX "I64i" 97 | 98 | #define PRIdPTR "Id" 99 | #define PRIiPTR "Ii" 100 | 101 | // The fprintf macros for unsigned integers are: 102 | #define PRIo8 "o" 103 | #define PRIu8 "u" 104 | #define PRIx8 "x" 105 | #define PRIX8 "X" 106 | #define PRIoLEAST8 "o" 107 | #define PRIuLEAST8 "u" 108 | #define PRIxLEAST8 "x" 109 | #define PRIXLEAST8 "X" 110 | #define PRIoFAST8 "o" 111 | #define PRIuFAST8 "u" 112 | #define PRIxFAST8 "x" 113 | #define PRIXFAST8 "X" 114 | 115 | #define PRIo16 "ho" 116 | #define PRIu16 "hu" 117 | #define PRIx16 "hx" 118 | #define PRIX16 "hX" 119 | #define PRIoLEAST16 "ho" 120 | #define PRIuLEAST16 "hu" 121 | #define PRIxLEAST16 "hx" 122 | #define PRIXLEAST16 "hX" 123 | #define PRIoFAST16 "ho" 124 | #define PRIuFAST16 "hu" 125 | #define PRIxFAST16 "hx" 126 | #define PRIXFAST16 "hX" 127 | 128 | #define PRIo32 "I32o" 129 | #define PRIu32 "I32u" 130 | #define PRIx32 "I32x" 131 | #define PRIX32 "I32X" 132 | #define PRIoLEAST32 "I32o" 133 | #define PRIuLEAST32 "I32u" 134 | #define PRIxLEAST32 "I32x" 135 | #define PRIXLEAST32 "I32X" 136 | #define PRIoFAST32 "I32o" 137 | #define PRIuFAST32 "I32u" 138 | #define PRIxFAST32 "I32x" 139 | #define PRIXFAST32 "I32X" 140 | 141 | #define PRIo64 "I64o" 142 | #define PRIu64 "I64u" 143 | #define PRIx64 "I64x" 144 | #define PRIX64 "I64X" 145 | #define PRIoLEAST64 "I64o" 146 | #define PRIuLEAST64 "I64u" 147 | #define PRIxLEAST64 "I64x" 148 | #define PRIXLEAST64 "I64X" 149 | #define PRIoFAST64 "I64o" 150 | #define PRIuFAST64 "I64u" 151 | #define PRIxFAST64 "I64x" 152 | #define PRIXFAST64 "I64X" 153 | 154 | #define PRIoMAX "I64o" 155 | #define PRIuMAX "I64u" 156 | #define PRIxMAX "I64x" 157 | #define PRIXMAX "I64X" 158 | 159 | #define PRIoPTR "Io" 160 | #define PRIuPTR "Iu" 161 | #define PRIxPTR "Ix" 162 | #define PRIXPTR "IX" 163 | 164 | // The fscanf macros for signed integers are: 165 | #define SCNd8 "d" 166 | #define SCNi8 "i" 167 | #define SCNdLEAST8 "d" 168 | #define SCNiLEAST8 "i" 169 | #define SCNdFAST8 "d" 170 | #define SCNiFAST8 "i" 171 | 172 | #define SCNd16 "hd" 173 | #define SCNi16 "hi" 174 | #define SCNdLEAST16 "hd" 175 | #define SCNiLEAST16 "hi" 176 | #define SCNdFAST16 "hd" 177 | #define SCNiFAST16 "hi" 178 | 179 | #define SCNd32 "ld" 180 | #define SCNi32 "li" 181 | #define SCNdLEAST32 "ld" 182 | #define SCNiLEAST32 "li" 183 | #define SCNdFAST32 "ld" 184 | #define SCNiFAST32 "li" 185 | 186 | #define SCNd64 "I64d" 187 | #define SCNi64 "I64i" 188 | #define SCNdLEAST64 "I64d" 189 | #define SCNiLEAST64 "I64i" 190 | #define SCNdFAST64 "I64d" 191 | #define SCNiFAST64 "I64i" 192 | 193 | #define SCNdMAX "I64d" 194 | #define SCNiMAX "I64i" 195 | 196 | #ifdef _WIN64 // [ 197 | # define SCNdPTR "I64d" 198 | # define SCNiPTR "I64i" 199 | #else // _WIN64 ][ 200 | # define SCNdPTR "ld" 201 | # define SCNiPTR "li" 202 | #endif // _WIN64 ] 203 | 204 | // The fscanf macros for unsigned integers are: 205 | #define SCNo8 "o" 206 | #define SCNu8 "u" 207 | #define SCNx8 "x" 208 | #define SCNX8 "X" 209 | #define SCNoLEAST8 "o" 210 | #define SCNuLEAST8 "u" 211 | #define SCNxLEAST8 "x" 212 | #define SCNXLEAST8 "X" 213 | #define SCNoFAST8 "o" 214 | #define SCNuFAST8 "u" 215 | #define SCNxFAST8 "x" 216 | #define SCNXFAST8 "X" 217 | 218 | #define SCNo16 "ho" 219 | #define SCNu16 "hu" 220 | #define SCNx16 "hx" 221 | #define SCNX16 "hX" 222 | #define SCNoLEAST16 "ho" 223 | #define SCNuLEAST16 "hu" 224 | #define SCNxLEAST16 "hx" 225 | #define SCNXLEAST16 "hX" 226 | #define SCNoFAST16 "ho" 227 | #define SCNuFAST16 "hu" 228 | #define SCNxFAST16 "hx" 229 | #define SCNXFAST16 "hX" 230 | 231 | #define SCNo32 "lo" 232 | #define SCNu32 "lu" 233 | #define SCNx32 "lx" 234 | #define SCNX32 "lX" 235 | #define SCNoLEAST32 "lo" 236 | #define SCNuLEAST32 "lu" 237 | #define SCNxLEAST32 "lx" 238 | #define SCNXLEAST32 "lX" 239 | #define SCNoFAST32 "lo" 240 | #define SCNuFAST32 "lu" 241 | #define SCNxFAST32 "lx" 242 | #define SCNXFAST32 "lX" 243 | 244 | #define SCNo64 "I64o" 245 | #define SCNu64 "I64u" 246 | #define SCNx64 "I64x" 247 | #define SCNX64 "I64X" 248 | #define SCNoLEAST64 "I64o" 249 | #define SCNuLEAST64 "I64u" 250 | #define SCNxLEAST64 "I64x" 251 | #define SCNXLEAST64 "I64X" 252 | #define SCNoFAST64 "I64o" 253 | #define SCNuFAST64 "I64u" 254 | #define SCNxFAST64 "I64x" 255 | #define SCNXFAST64 "I64X" 256 | 257 | #define SCNoMAX "I64o" 258 | #define SCNuMAX "I64u" 259 | #define SCNxMAX "I64x" 260 | #define SCNXMAX "I64X" 261 | 262 | #ifdef _WIN64 // [ 263 | # define SCNoPTR "I64o" 264 | # define SCNuPTR "I64u" 265 | # define SCNxPTR "I64x" 266 | # define SCNXPTR "I64X" 267 | #else // _WIN64 ][ 268 | # define SCNoPTR "lo" 269 | # define SCNuPTR "lu" 270 | # define SCNxPTR "lx" 271 | # define SCNXPTR "lX" 272 | #endif // _WIN64 ] 273 | 274 | #endif // __STDC_FORMAT_MACROS ] 275 | 276 | // 7.8.2 Functions for greatest-width integer types 277 | 278 | // 7.8.2.1 The imaxabs function 279 | #define imaxabs _abs64 280 | 281 | // 7.8.2.2 The imaxdiv function 282 | 283 | // This is modified version of div() function from Microsoft's div.c found 284 | // in %MSVC.NET%\crt\src\div.c 285 | #ifdef STATIC_IMAXDIV // [ 286 | static 287 | #else // STATIC_IMAXDIV ][ 288 | _inline 289 | #endif // STATIC_IMAXDIV ] 290 | imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) 291 | { 292 | imaxdiv_t result; 293 | 294 | result.quot = numer / denom; 295 | result.rem = numer % denom; 296 | 297 | if (numer < 0 && result.rem > 0) { 298 | // did division wrong; must fix up 299 | ++result.quot; 300 | result.rem -= denom; 301 | } 302 | 303 | return result; 304 | } 305 | 306 | // 7.8.2.3 The strtoimax and strtoumax functions 307 | #define strtoimax _strtoi64 308 | #define strtoumax _strtoui64 309 | 310 | // 7.8.2.4 The wcstoimax and wcstoumax functions 311 | #define wcstoimax _wcstoi64 312 | #define wcstoumax _wcstoui64 313 | 314 | #endif // _MSC_VER >= 1800 315 | 316 | #endif // _MSC_INTTYPES_H_ ] 317 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/prettywriter.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_PRETTYWRITER_H_ 16 | #define RAPIDJSON_PRETTYWRITER_H_ 17 | 18 | #include "writer.h" 19 | 20 | #ifdef __GNUC__ 21 | RAPIDJSON_DIAG_PUSH 22 | RAPIDJSON_DIAG_OFF(effc++) 23 | #endif 24 | 25 | RAPIDJSON_NAMESPACE_BEGIN 26 | 27 | //! Writer with indentation and spacing. 28 | /*! 29 | \tparam OutputStream Type of ouptut os. 30 | \tparam SourceEncoding Encoding of source string. 31 | \tparam TargetEncoding Encoding of output stream. 32 | \tparam StackAllocator Type of allocator for allocating memory of stack. 33 | */ 34 | template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> 35 | class PrettyWriter : public Writer { 36 | public: 37 | typedef Writer Base; 38 | typedef typename Base::Ch Ch; 39 | 40 | //! Constructor 41 | /*! \param os Output stream. 42 | \param allocator User supplied allocator. If it is null, it will create a private one. 43 | \param levelDepth Initial capacity of stack. 44 | */ 45 | PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 46 | Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} 47 | 48 | //! Set custom indentation. 49 | /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). 50 | \param indentCharCount Number of indent characters for each indentation level. 51 | \note The default indentation is 4 spaces. 52 | */ 53 | PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { 54 | RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); 55 | indentChar_ = indentChar; 56 | indentCharCount_ = indentCharCount; 57 | return *this; 58 | } 59 | 60 | /*! @name Implementation of Handler 61 | \see Handler 62 | */ 63 | //@{ 64 | 65 | bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); } 66 | bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); } 67 | bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); } 68 | bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); } 69 | bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); } 70 | bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } 71 | bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } 72 | 73 | bool String(const Ch* str, SizeType length, bool copy = false) { 74 | (void)copy; 75 | PrettyPrefix(kStringType); 76 | return Base::WriteString(str, length); 77 | } 78 | 79 | #if RAPIDJSON_HAS_STDSTRING 80 | bool String(const std::basic_string& str) { 81 | return String(str.data(), SizeType(str.size())); 82 | } 83 | #endif 84 | 85 | bool StartObject() { 86 | PrettyPrefix(kObjectType); 87 | new (Base::level_stack_.template Push()) typename Base::Level(false); 88 | return Base::WriteStartObject(); 89 | } 90 | 91 | bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } 92 | 93 | bool EndObject(SizeType memberCount = 0) { 94 | (void)memberCount; 95 | RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); 96 | RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); 97 | bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; 98 | 99 | if (!empty) { 100 | Base::os_->Put('\n'); 101 | WriteIndent(); 102 | } 103 | bool ret = Base::WriteEndObject(); 104 | (void)ret; 105 | RAPIDJSON_ASSERT(ret == true); 106 | if (Base::level_stack_.Empty()) // end of json text 107 | Base::os_->Flush(); 108 | return true; 109 | } 110 | 111 | bool StartArray() { 112 | PrettyPrefix(kArrayType); 113 | new (Base::level_stack_.template Push()) typename Base::Level(true); 114 | return Base::WriteStartArray(); 115 | } 116 | 117 | bool EndArray(SizeType memberCount = 0) { 118 | (void)memberCount; 119 | RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); 120 | RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); 121 | bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; 122 | 123 | if (!empty) { 124 | Base::os_->Put('\n'); 125 | WriteIndent(); 126 | } 127 | bool ret = Base::WriteEndArray(); 128 | (void)ret; 129 | RAPIDJSON_ASSERT(ret == true); 130 | if (Base::level_stack_.Empty()) // end of json text 131 | Base::os_->Flush(); 132 | return true; 133 | } 134 | 135 | //@} 136 | 137 | /*! @name Convenience extensions */ 138 | //@{ 139 | 140 | //! Simpler but slower overload. 141 | bool String(const Ch* str) { return String(str, internal::StrLen(str)); } 142 | bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } 143 | 144 | //@} 145 | protected: 146 | void PrettyPrefix(Type type) { 147 | (void)type; 148 | if (Base::level_stack_.GetSize() != 0) { // this value is not at root 149 | typename Base::Level* level = Base::level_stack_.template Top(); 150 | 151 | if (level->inArray) { 152 | if (level->valueCount > 0) { 153 | Base::os_->Put(','); // add comma if it is not the first element in array 154 | Base::os_->Put('\n'); 155 | } 156 | else 157 | Base::os_->Put('\n'); 158 | WriteIndent(); 159 | } 160 | else { // in object 161 | if (level->valueCount > 0) { 162 | if (level->valueCount % 2 == 0) { 163 | Base::os_->Put(','); 164 | Base::os_->Put('\n'); 165 | } 166 | else { 167 | Base::os_->Put(':'); 168 | Base::os_->Put(' '); 169 | } 170 | } 171 | else 172 | Base::os_->Put('\n'); 173 | 174 | if (level->valueCount % 2 == 0) 175 | WriteIndent(); 176 | } 177 | if (!level->inArray && level->valueCount % 2 == 0) 178 | RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name 179 | level->valueCount++; 180 | } 181 | else { 182 | RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. 183 | Base::hasRoot_ = true; 184 | } 185 | } 186 | 187 | void WriteIndent() { 188 | size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; 189 | PutN(*Base::os_, indentChar_, count); 190 | } 191 | 192 | Ch indentChar_; 193 | unsigned indentCharCount_; 194 | 195 | private: 196 | // Prohibit copy constructor & assignment operator. 197 | PrettyWriter(const PrettyWriter&); 198 | PrettyWriter& operator=(const PrettyWriter&); 199 | }; 200 | 201 | RAPIDJSON_NAMESPACE_END 202 | 203 | #ifdef __GNUC__ 204 | RAPIDJSON_DIAG_POP 205 | #endif 206 | 207 | #endif // RAPIDJSON_RAPIDJSON_H_ 208 | -------------------------------------------------------------------------------- /ImageProc/include/rapidjson/stringbuffer.h: -------------------------------------------------------------------------------- 1 | // Tencent is pleased to support the open source community by making RapidJSON available. 2 | // 3 | // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 | // 5 | // Licensed under the MIT License (the "License"); you may not use this file except 6 | // in compliance with the License. You may obtain a copy of the License at 7 | // 8 | // http://opensource.org/licenses/MIT 9 | // 10 | // Unless required by applicable law or agreed to in writing, software distributed 11 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 | // specific language governing permissions and limitations under the License. 14 | 15 | #ifndef RAPIDJSON_STRINGBUFFER_H_ 16 | #define RAPIDJSON_STRINGBUFFER_H_ 17 | 18 | #include "rapidjson.h" 19 | 20 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 21 | #include // std::move 22 | #endif 23 | 24 | #include "internal/stack.h" 25 | 26 | RAPIDJSON_NAMESPACE_BEGIN 27 | 28 | //! Represents an in-memory output stream. 29 | /*! 30 | \tparam Encoding Encoding of the stream. 31 | \tparam Allocator type for allocating memory buffer. 32 | \note implements Stream concept 33 | */ 34 | template 35 | class GenericStringBuffer { 36 | public: 37 | typedef typename Encoding::Ch Ch; 38 | 39 | GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} 40 | 41 | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 42 | GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} 43 | GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { 44 | if (&rhs != this) 45 | stack_ = std::move(rhs.stack_); 46 | return *this; 47 | } 48 | #endif 49 | 50 | void Put(Ch c) { *stack_.template Push() = c; } 51 | void Flush() {} 52 | 53 | void Clear() { stack_.Clear(); } 54 | void ShrinkToFit() { 55 | // Push and pop a null terminator. This is safe. 56 | *stack_.template Push() = '\0'; 57 | stack_.ShrinkToFit(); 58 | stack_.template Pop(1); 59 | } 60 | Ch* Push(size_t count) { return stack_.template Push(count); } 61 | void Pop(size_t count) { stack_.template Pop(count); } 62 | 63 | const Ch* GetString() const { 64 | // Push and pop a null terminator. This is safe. 65 | *stack_.template Push() = '\0'; 66 | stack_.template Pop(1); 67 | 68 | return stack_.template Bottom(); 69 | } 70 | 71 | size_t GetSize() const { return stack_.GetSize(); } 72 | 73 | static const size_t kDefaultCapacity = 256; 74 | mutable internal::Stack stack_; 75 | 76 | private: 77 | // Prohibit copy constructor & assignment operator. 78 | GenericStringBuffer(const GenericStringBuffer&); 79 | GenericStringBuffer& operator=(const GenericStringBuffer&); 80 | }; 81 | 82 | //! String buffer with UTF8 encoding 83 | typedef GenericStringBuffer > StringBuffer; 84 | 85 | //! Implement specialized version of PutN() with memset() for better performance. 86 | template<> 87 | inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { 88 | std::memset(stream.stack_.Push(n), c, n * sizeof(c)); 89 | } 90 | 91 | RAPIDJSON_NAMESPACE_END 92 | 93 | #endif // RAPIDJSON_STRINGBUFFER_H_ 94 | -------------------------------------------------------------------------------- /ImageProc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OpenCV in Chrome using NaCl 5 | 6 | 7 | 8 | 9 |

OpenCV in Chrome using NaCl

10 | 11 |

This page uses 13 | Google Native Client to tie in to the C++ OpenCV computer vision library. 15 | This allows realtime image processing of the webcam feed from within the 16 | browser. 17 |
18 | NB: No data is sent back to this website. 19 |

20 | 21 |

Requires Chrome web browser version 44 or above (not Android app)

22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 32 |
33 | 34 |
35 | 36 | 37 | 38 |
39 | 40 |

Status NO-STATUS

41 | 42 | GitHub repo 43 | 44 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ImageProc/instance_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INSTANCE_FACTORY_HPP 2 | #define INSTANCE_FACTORY_HPP 3 | 4 | #include "ppapi/cpp/instance.h" 5 | #include "ppapi/cpp/module.h" 6 | #include "ppapi/cpp/var.h" 7 | 8 | // Factory method called by the browser when first loaded 9 | namespace pp { 10 | Module* CreateModule(); 11 | }; 12 | 13 | // Module used to create instance of NaCl module on webpage 14 | template 15 | class InstanceFactory : public pp::Module { 16 | public: 17 | InstanceFactory( ){}; 18 | virtual ~InstanceFactory(){}; 19 | virtual pp::Instance* CreateInstance( PP_Instance instance ) { 20 | return new T(instance); 21 | }; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /ImageProc/mmcdonne.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmcd/NaCl/56e0f6a5d45bb35f13ae63d79425b329667aba3a/ImageProc/mmcdonne.jpg -------------------------------------------------------------------------------- /ImageProc/processor.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROCESSOR_HPP 2 | #define PROCESSOR_HPP 3 | 4 | #include 5 | #include 6 | 7 | class Processor { 8 | public: 9 | virtual cv::Mat operator()(cv::Mat)=0; 10 | virtual ~Processor() {} 11 | virtual void init( cv::Mat ) {}; 12 | virtual void init( const char* ) {}; 13 | virtual std::string getParameters() { return ""; }; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /ImageProc/processor_barcode.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | class BarcodeDetectorProcessor : public Processor { 6 | public: 7 | cv::Mat operator()(cv::Mat); 8 | private: 9 | static void createOutput(cv::Mat&, cv::Mat&); 10 | }; 11 | 12 | cv::Mat BarcodeDetectorProcessor::operator()(cv::Mat im) { 13 | cv::Mat grey; 14 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 15 | cv::Mat gradX; 16 | cv::Scharr(grey, gradX, CV_32F, 1, 0); 17 | cv::Mat gradY; 18 | cv::Scharr(grey, gradY, CV_32F, 0, 1); 19 | cv::Mat gradient; 20 | cv::subtract( gradX, gradY, gradient); 21 | cv::convertScaleAbs(gradient, gradient); 22 | 23 | cv::Mat blurred; 24 | cv::blur(gradient, blurred, cv::Size(9,9)); 25 | 26 | cv::Mat thresh; 27 | cv::threshold(gradient, thresh, 225, 255, cv::THRESH_BINARY ); 28 | 29 | // Close image to convert barcode lines into filled rectangle 30 | cv::Mat kernel = cv::getStructuringElement( 31 | cv::MORPH_RECT, cv::Size(21,7)); 32 | cv::Mat closed; 33 | cv::morphologyEx( thresh, closed, cv::MORPH_CLOSE, kernel); 34 | 35 | // Remove small blobs 36 | cv::erode( closed, closed, cv::Mat(), cv::Point(-1,1), 4); 37 | cv::dilate( closed, closed, cv::Mat(), cv::Point(-1,1), 4); 38 | 39 | // Find largest area 40 | std::vector> contours; 41 | cv::findContours( closed, contours, cv::RETR_EXTERNAL, 42 | cv::CHAIN_APPROX_SIMPLE ); 43 | 44 | std::sort(contours.begin(), contours.end(), 45 | [](const std::vector a, const std::vectorb) { 46 | return (cv::contourArea(a) > cv::contourArea(b)); }); 47 | 48 | cv::RotatedRect rect = cv::minAreaRect( contours[0]); 49 | cv::Point2f vertices[4]; 50 | rect.points( vertices ); 51 | for (int i=0; i<4; i++) { 52 | cv::line( im, vertices[i], vertices[(i+1)%4], 53 | cv::Scalar(0,255,0,255), 3); 54 | } 55 | 56 | // cv::drawContours( im, outContour, -1, cv::Scalar(0,255,0), 3); 57 | 58 | // Display intermediate images for debugging 59 | // cv::Mat dest; 60 | // createOutput( closed, dest ); 61 | return im; 62 | } 63 | 64 | void BarcodeDetectorProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 65 | { 66 | // Show intermediate images - need to expand CV_8UC1 to RGBA 67 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 68 | std::vector rgba_out; 69 | rgba_out.push_back( src ); 70 | rgba_out.push_back( src ); 71 | rgba_out.push_back( src ); 72 | rgba_out.push_back( fullAlpha ); 73 | 74 | cv::merge( rgba_out, dest); 75 | } 76 | 77 | namespace { 78 | auto scProcReg = ProcessorRegister("Barcode Detector"); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /ImageProc/processor_cartoon.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | class CartoonProcessor : public Processor { 6 | public: 7 | cv::Mat operator()(cv::Mat); 8 | private: 9 | static void createOutput(cv::Mat&, cv::Mat&); 10 | }; 11 | 12 | cv::Mat CartoonProcessor::operator()(cv::Mat im) { 13 | cv::Mat grey; 14 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 15 | // Get rid of speckle first by median filter 16 | const int MEDIAN_KERNEL_SIZE = 9; 17 | cv::medianBlur(grey, grey, MEDIAN_KERNEL_SIZE); 18 | cv::Mat gradX; 19 | cv::Scharr(grey, gradX, CV_32F, 1, 0); 20 | cv::Mat gradY; 21 | cv::Scharr(grey, gradY, CV_32F, 0, 1); 22 | cv::Mat gradient; 23 | cv::subtract( gradX, gradY, gradient); 24 | cv::convertScaleAbs(gradient, gradient); 25 | 26 | cv::Mat blurred; 27 | cv::blur(gradient, blurred, cv::Size(9,9)); 28 | 29 | cv::Mat thresh; 30 | cv::threshold(gradient, thresh, 150, 255, cv::THRESH_BINARY_INV ); 31 | 32 | // Display intermediate images for debugging 33 | cv::Mat dest; 34 | createOutput( thresh, dest ); 35 | return dest; 36 | 37 | /* 38 | cv::Mat segmented, gray, edges, edgesBgr; 39 | cv::pyrMeanShiftFiltering(im, segmented, 15, 40); 40 | cv::cvtColor(segmented, gray, CV_BGR2GRAY); 41 | cv::Canny(gray, edges, 150, 150); 42 | cv::cvtColor(edges, edgesBgr, CV_GRAY2BGR); 43 | cv::Mat result = segmented - edgesBgr; 44 | return result; 45 | */ 46 | } 47 | 48 | void CartoonProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 49 | { 50 | // Show intermediate images - need to expand CV_8UC1 to RGBA 51 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 52 | std::vector rgba_out; 53 | rgba_out.push_back( src ); 54 | rgba_out.push_back( src ); 55 | rgba_out.push_back( src ); 56 | rgba_out.push_back( fullAlpha ); 57 | 58 | cv::merge( rgba_out, dest); 59 | } 60 | 61 | namespace { 62 | auto scProcReg = ProcessorRegister("Cartoon"); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /ImageProc/processor_diff.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include 3 | 4 | class DiffProcessor : public Processor { 5 | public: 6 | cv::Mat operator()(cv::Mat); 7 | private: 8 | cv::Mat prevFrame; 9 | }; 10 | 11 | cv::Mat DiffProcessor::operator()(cv::Mat im) { 12 | if ( prevFrame.empty() ) { 13 | prevFrame = im.clone(); 14 | } else { 15 | cv::Mat dest; 16 | cv::absdiff( im, prevFrame, dest); 17 | prevFrame = im.clone(); // NB: need to clone image not just copy ref 18 | // Set alpha channel 19 | cv::add( cv::Scalar(0,0,0,255), dest, im ); 20 | } 21 | return im; 22 | } 23 | 24 | namespace { 25 | auto diffProcReg = ProcessorRegister("Diff"); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /ImageProc/processor_facedetect.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROCESSOR_FACEDETECT_HPP 2 | #define PROCESSOR_FACEDETECT_HPP 3 | #include "face_detector.hpp" 4 | 5 | class FaceDetectorProcessor : public FaceDetector { 6 | public: 7 | cv::Mat operator()(cv::Mat); 8 | FaceDetectorProcessor(); 9 | virtual ~FaceDetectorProcessor(){}; 10 | // Helper method to detect faces 11 | virtual void detectFaces(const cv::Mat, std::vector&); 12 | private: 13 | cv::CascadeClassifier face_cascade; 14 | bool xmlLoaded; 15 | static void createOutput(cv::Mat&, cv::Mat&); 16 | static std::string getClassifier(); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /ImageProc/processor_gblur.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include "include/rapidjson/document.h" 4 | #include 5 | 6 | class GBlurProcessor : public Processor { 7 | public: 8 | GBlurProcessor() : level(4) {}; 9 | GBlurProcessor(int level_) : level(level_) {}; 10 | cv::Mat operator()(cv::Mat); 11 | void init(const char* json); 12 | std::string getParameters(); 13 | private: 14 | int level; 15 | }; 16 | 17 | void GBlurProcessor::init(const char* json) { 18 | // Read json string to set properties 19 | using namespace rapidjson; 20 | Document document; 21 | document.Parse(json); 22 | assert(document.IsObject()); 23 | assert(document.HasMember("level")); 24 | level = document["level"].GetInt(); 25 | } 26 | 27 | std::string GBlurProcessor::getParameters() { 28 | std::ostringstream os; 29 | os << "{\"level\":" << level << "}"; 30 | return os.str(); 31 | } 32 | 33 | cv::Mat GBlurProcessor::operator()(cv::Mat im) { 34 | cv::Mat dest; 35 | const int in_rows = im.rows; 36 | const int in_cols = im.cols; 37 | // for (auto i=0; i("Gaussian Blur"); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /ImageProc/processor_houghline.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | // OpenCV HoughLine Derivative example from doc 6 | // http://docs.opencv.org/doc/tutorials/imgtrans/sobel_derivatives/sobel_derivaties.html 7 | class HoughLineProcessor : public Processor { 8 | public: 9 | cv::Mat operator()(cv::Mat); 10 | private: 11 | static void createOutput(cv::Mat&, cv::Mat&); 12 | }; 13 | 14 | cv::Mat HoughLineProcessor::operator()(cv::Mat im) { 15 | 16 | cv::Mat grey; 17 | // Remove noise by blurring with Gaussian 18 | cv::GaussianBlur(im, im, cv::Size(3,3), 0,0, cv::BORDER_DEFAULT); 19 | 20 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 21 | 22 | // Canny edge detector 23 | int lowThreshold = 50; 24 | int ratio = 4; 25 | int kernel_size = 3; 26 | cv::Mat detected_edges; 27 | cv::Canny( grey, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size); 28 | 29 | // Hough line transform 30 | std::vector lines; 31 | int houghRho = 1; // pixel 32 | double houghTheta = CV_PI/180; //radians 33 | int houghThreshold = 100; 34 | int srn = 0; 35 | int stn = 0; 36 | cv::HoughLines( detected_edges, lines, houghRho, houghTheta, houghThreshold, srn, stn); 37 | 38 | // Display intermediate images for debugging 39 | cv::Mat dest; 40 | cv::cvtColor( detected_edges, dest, CV_GRAY2BGR); 41 | 42 | // Draw detected lines 43 | for( auto line : lines ) { 44 | float rho = line[0], theta = line[1]; 45 | cv::Point pt1, pt2; 46 | double a = cos(theta), b = sin(theta); 47 | double x0 = a*rho, y0 = b*rho; 48 | pt1.x = cvRound(x0 + 1000*(-b)); 49 | pt1.y = cvRound(y0 + 1000*(a)); 50 | pt2.x = cvRound(x0 - 1000*(-b)); 51 | pt2.y = cvRound(y0 - 1000*(a)); 52 | cv::line(dest, pt1, pt2, cv::Scalar(0,255,0), 2, CV_AA); 53 | } 54 | 55 | cv::cvtColor( dest, dest, CV_BGR2RGBA ); 56 | return dest; 57 | 58 | } 59 | 60 | void HoughLineProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 61 | { 62 | // Show intermediate images - need to expand CV_8UC1 to RGBA 63 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 64 | std::vector rgba_out; 65 | rgba_out.push_back( src ); 66 | rgba_out.push_back( src ); 67 | rgba_out.push_back( src ); 68 | rgba_out.push_back( fullAlpha ); 69 | 70 | cv::merge( rgba_out, dest); 71 | } 72 | 73 | namespace { 74 | auto scProcReg = ProcessorRegister("Hough Line Transform"); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /ImageProc/processor_id.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | 3 | class IdentityProcessor : public Processor { 4 | public: 5 | cv::Mat operator()(cv::Mat); 6 | }; 7 | 8 | cv::Mat IdentityProcessor::operator()(cv::Mat im) { 9 | return im; 10 | } 11 | 12 | namespace { 13 | auto idProcReg = ProcessorRegister("Id"); 14 | } 15 | -------------------------------------------------------------------------------- /ImageProc/processor_invert.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | 3 | class InvertProcessor : public Processor { 4 | public: 5 | cv::Mat operator()(cv::Mat); 6 | }; 7 | 8 | cv::Mat InvertProcessor::operator()(cv::Mat im) { 9 | cv::Mat dest; 10 | // Subtract the image from a constant 255 4-channel array 11 | cv::subtract( cv::Scalar(255, 255, 255, 255), im, dest ); 12 | // Set the alpha channel back to fully opaque 13 | cv::add( cv::Scalar(0,0,0,255), dest, im ); 14 | 15 | return im; 16 | } 17 | 18 | namespace { 19 | auto invertProcReg = ProcessorRegister("Invert"); 20 | } 21 | -------------------------------------------------------------------------------- /ImageProc/processor_laplacian.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | // OpenCV Laplacian Derivative example from doc 6 | // http://docs.opencv.org/doc/tutorials/imgtrans/laplace_operator/laplace_operator.html 7 | class LaplacianProcessor : public Processor { 8 | public: 9 | cv::Mat operator()(cv::Mat); 10 | private: 11 | static void createOutput(cv::Mat&, cv::Mat&); 12 | }; 13 | 14 | cv::Mat LaplacianProcessor::operator()(cv::Mat im) { 15 | 16 | cv::Mat grey; 17 | // Remove noise by blurring with Gaussian 18 | cv::GaussianBlur(im, im, cv::Size(3,3), 0,0, cv::BORDER_DEFAULT); 19 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 20 | 21 | int kernel_size = 3; 22 | int scale = 1; 23 | int delta = 0; 24 | int ddepth = CV_16S; 25 | cv::Mat lap; 26 | cv::Laplacian(grey, lap, ddepth, kernel_size, scale, delta, cv::BORDER_DEFAULT); 27 | 28 | // Scaled abs laplacian 29 | cv::Mat absLap; 30 | 31 | cv::convertScaleAbs(lap, absLap); 32 | 33 | // Display intermediate images for debugging 34 | cv::Mat dest; 35 | createOutput( absLap, dest ); 36 | return dest; 37 | } 38 | 39 | void LaplacianProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 40 | { 41 | // Show intermediate images - need to expand CV_8UC1 to RGBA 42 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 43 | std::vector rgba_out; 44 | rgba_out.push_back( src ); 45 | rgba_out.push_back( src ); 46 | rgba_out.push_back( src ); 47 | rgba_out.push_back( fullAlpha ); 48 | 49 | cv::merge( rgba_out, dest); 50 | } 51 | 52 | namespace { 53 | auto scProcReg = ProcessorRegister("Laplacian"); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /ImageProc/processor_probabilistichoughline.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | // OpenCV ProbabilisticHoughLine Derivative example from doc 6 | // http://docs.opencv.org/doc/tutorials/imgtrans/sobel_derivatives/sobel_derivaties.html 7 | class ProbabilisticHoughLineProcessor : public Processor { 8 | public: 9 | cv::Mat operator()(cv::Mat); 10 | private: 11 | static void createOutput(cv::Mat&, cv::Mat&); 12 | }; 13 | 14 | cv::Mat ProbabilisticHoughLineProcessor::operator()(cv::Mat im) { 15 | 16 | cv::Mat grey; 17 | // Remove noise by blurring with Gaussian 18 | cv::GaussianBlur(im, im, cv::Size(3,3), 0,0, cv::BORDER_DEFAULT); 19 | 20 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 21 | 22 | // Canny edge detector 23 | int lowThreshold = 50; 24 | int ratio = 4; 25 | int kernel_size = 3; 26 | cv::Mat detected_edges; 27 | cv::Canny( grey, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size); 28 | 29 | // Hough line transform 30 | std::vector lines; 31 | int houghRho = 1; // pixel 32 | double houghTheta = CV_PI/180; //radians 33 | int houghThreshold = 50; 34 | int minLineLength = 50; 35 | int maxLineGap = 10; 36 | cv::HoughLinesP( detected_edges, lines, houghRho, houghTheta, 37 | houghThreshold, minLineLength, maxLineGap); 38 | 39 | cv::Mat dest; 40 | cv::cvtColor( detected_edges, dest, CV_GRAY2BGR); 41 | 42 | // Draw detected lines 43 | for( auto line : lines ) { 44 | cv::line(dest, cv::Point(line[0],line[1]), 45 | cv::Point(line[2], line[3]), cv::Scalar(0,255,0), 2, CV_AA); 46 | } 47 | 48 | cv::cvtColor( dest, dest, CV_BGR2RGBA ); 49 | return dest; 50 | } 51 | 52 | void ProbabilisticHoughLineProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 53 | { 54 | // Show intermediate images - need to expand CV_8UC1 to RGBA 55 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 56 | std::vector rgba_out; 57 | rgba_out.push_back( src ); 58 | rgba_out.push_back( src ); 59 | rgba_out.push_back( src ); 60 | rgba_out.push_back( fullAlpha ); 61 | 62 | cv::merge( rgba_out, dest); 63 | } 64 | 65 | namespace { 66 | auto scProcReg = ProcessorRegister( 67 | "Probabilistic Hough Line Transform"); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /ImageProc/processor_pulsedetect.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | 4 | class PulseDetectionProcessor : public Processor { 5 | public: 6 | PulseDetectionProcessor() : 7 | level(4), r1(0.4), r2(0.05) // , alpha(50.0), chromAttenuation(1.0) 8 | {}; 9 | cv::Mat operator()(cv::Mat); 10 | private: 11 | int level; 12 | double r1; 13 | double r2; 14 | // double alpha; 15 | // double chromAttenuation; 16 | cv::Mat prevFrame1; 17 | cv::Mat prevFrame2; 18 | }; 19 | 20 | cv::Mat PulseDetectionProcessor::operator()(cv::Mat im) { 21 | cv::Mat dest; 22 | // Convert to YCrCb color space 23 | // cv::cvtColor( im, dest, CV_YCrCb2RGB); 24 | 25 | // Gaussian blur using image pyramid 26 | for (auto i=0; i("Pulse Detection (experimental)"); 58 | } 59 | 60 | -------------------------------------------------------------------------------- /ImageProc/processor_redchannel.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include 3 | 4 | class SingleChannelProcessor : public Processor { 5 | public: 6 | cv::Mat operator()(cv::Mat); 7 | }; 8 | 9 | cv::Mat SingleChannelProcessor::operator()(cv::Mat im) { 10 | cv::Mat dest; 11 | // Split the matrix into its channels 12 | std::vector rgba; 13 | cv::split(im, rgba); 14 | // Blank matrix for Green and Blue channels 15 | cv::Mat blank = cv::Mat( im.size(), CV_8UC1, cv::Scalar(0)); 16 | std::vector rgba_out; 17 | rgba_out.push_back( rgba[0] ); 18 | rgba_out.push_back( rgba[0] ); 19 | rgba_out.push_back( rgba[0] ); 20 | rgba_out.push_back( rgba[3] ); 21 | 22 | cv::merge( rgba_out, dest); 23 | return dest; 24 | } 25 | 26 | namespace { 27 | auto scProcReg = ProcessorRegister("Red"); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /ImageProc/processor_skindetect.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | class SkinDetectProcessor : public Processor { 6 | public: 7 | cv::Mat operator()(cv::Mat); 8 | private: 9 | static void createOutput(cv::Mat&, cv::Mat&); 10 | }; 11 | 12 | cv::Mat SkinDetectProcessor::operator()(cv::Mat im) { 13 | // SkinDetect segmentation demo from the OpenCV documentation 14 | cv::Mat converted; 15 | cv::cvtColor( im, im, CV_RGBA2BGR ); 16 | cv::cvtColor( im, converted, CV_BGR2HSV ); 17 | 18 | cv::Mat thresh; 19 | // Skin Cluster in YCbCr space from 'Explicit Image Detection using 20 | // YCbCr Space Color Model as Skin Detection' by Basilo, et al. 21 | // cv::Scalar colorLow {80, 135, 85}; 22 | // cv::Scalar colorHigh {255, 180, 135}; 23 | 24 | // HSV skin range from PyImageSearch 2014-08-18 blog post 25 | cv::Scalar colorLow {0, 48, 80}; 26 | cv::Scalar colorHigh {20, 255, 255}; 27 | 28 | cv::inRange(converted, colorLow, colorHigh, thresh); 29 | 30 | // Open image to remove noise 31 | cv::Mat kernel = cv::getStructuringElement( 32 | cv::MORPH_ELLIPSE, cv::Size(3,3)); 33 | cv::Mat skinMask; 34 | cv::morphologyEx( thresh, skinMask, cv::MORPH_OPEN, 35 | kernel, cv::Point(-1,1), 2); 36 | cv::GaussianBlur(skinMask, skinMask, cv::Size(3,3), 0, 0); 37 | 38 | 39 | cv::Mat out; 40 | cv::bitwise_and(im, im, out, skinMask); 41 | 42 | // Display intermediate images for debugging 43 | // cv::Mat dest; 44 | // createOutput( markers, dest ); 45 | cv::cvtColor( out, out, CV_BGR2RGBA ); 46 | return out; 47 | } 48 | 49 | void SkinDetectProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 50 | { 51 | // Show intermediate images - need to expand CV_8UC1 to RGBA 52 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 53 | std::vector rgba_out; 54 | rgba_out.push_back( src ); 55 | rgba_out.push_back( src ); 56 | rgba_out.push_back( src ); 57 | rgba_out.push_back( fullAlpha ); 58 | 59 | cv::merge( rgba_out, dest); 60 | } 61 | 62 | namespace { 63 | auto scProcReg = ProcessorRegister("Skin Detector"); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /ImageProc/processor_smiley.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/objdetect/objdetect.hpp" 3 | #include "opencv2/imgproc/imgproc.hpp" 4 | #include "processor_facedetect.hpp" 5 | #include 6 | #include 7 | 8 | class SmileyProcessor : public Processor { 9 | public: 10 | cv::Mat operator()(cv::Mat); 11 | SmileyProcessor(); 12 | virtual ~SmileyProcessor(){}; 13 | void init(cv::Mat); // Add image to paste 14 | private: 15 | cv::Mat smiley; 16 | static void createOutput(cv::Mat&, cv::Mat&); 17 | std::unique_ptr innerFaceDetector; 18 | }; 19 | 20 | SmileyProcessor::SmileyProcessor() { 21 | // Use inner FaceDetector processor for finding faces in image 22 | innerFaceDetector = std::unique_ptr{new FaceDetectorProcessor()}; 23 | } 24 | 25 | void SmileyProcessor::init( cv::Mat im ) { 26 | cv::cvtColor( im, im, CV_RGBA2BGR ); 27 | smiley = im; 28 | } 29 | 30 | cv::Mat SmileyProcessor::operator()(cv::Mat im) { 31 | // Smiley segmentation demo from the OpenCV documentation 32 | cv::cvtColor( im, im, CV_RGBA2BGR ); 33 | 34 | std::vector faces; 35 | innerFaceDetector->detectFaces(im, faces); 36 | 37 | for ( size_t i=0; i < faces.size(); i++ ) { 38 | cv::Mat tmp( faces[i].size(), CV_8UC4 ); 39 | cv::resize( smiley, tmp, faces[i].size()); 40 | cv::Mat roi = im( faces[i] ); 41 | cv::Mat mask( tmp.size(), CV_8UC1 ); 42 | cv::compare( tmp, cv::Scalar(100,100,100), mask, cv::CMP_NE); 43 | tmp.copyTo( roi, mask ); 44 | // cv::rectangle( im, faces[i], cv::Scalar(0,255,0), 2); 45 | } 46 | 47 | // Display intermediate images for debugging 48 | // cv::Mat dest; 49 | // createOutput( markers, dest ); 50 | cv::cvtColor( im, im, CV_BGR2RGBA ); 51 | return im; 52 | } 53 | 54 | void SmileyProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 55 | { 56 | // Show intermediate images - need to expand CV_8UC1 to RGBA 57 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 58 | std::vector rgba_out; 59 | rgba_out.push_back( src ); 60 | rgba_out.push_back( src ); 61 | rgba_out.push_back( src ); 62 | rgba_out.push_back( fullAlpha ); 63 | 64 | cv::merge( rgba_out, dest); 65 | } 66 | 67 | namespace { 68 | auto scProcReg = ProcessorRegister("Smiley!"); 69 | } 70 | -------------------------------------------------------------------------------- /ImageProc/processor_sobel.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | #include "include/rapidjson/document.h" 5 | 6 | // OpenCV Sobel Derivative example from doc 7 | // http://docs.opencv.org/doc/tutorials/imgtrans/sobel_derivatives/sobel_derivaties.html 8 | class SobelProcessor : public Processor { 9 | public: 10 | cv::Mat operator()(cv::Mat); 11 | void init(const char*); 12 | std::string getParameters(); 13 | private: 14 | static void createOutput(cv::Mat&, cv::Mat&); 15 | int ksize = CV_SCHARR; 16 | }; 17 | 18 | cv::Mat SobelProcessor::operator()(cv::Mat im) { 19 | 20 | cv::Mat grey; 21 | // Remove noise by blurring with Gaussian 22 | cv::GaussianBlur(im, im, cv::Size(3,3), 0,0, cv::BORDER_DEFAULT); 23 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 24 | 25 | int scale = 1; 26 | int delta = 0; 27 | int ddepth = CV_16S; 28 | cv::Mat gradX; 29 | cv::Sobel(grey, gradX, ddepth, 1, 0, ksize, scale, delta, cv::BORDER_DEFAULT); 30 | cv::Mat gradY; 31 | cv::Sobel(grey, gradY, ddepth, 0, 1, ksize, scale, delta, cv::BORDER_DEFAULT); 32 | 33 | // Scaled abs gradients 34 | cv::Mat gradMag; 35 | cv::addWeighted(gradX, 0.5, gradY, 0.5, 0, gradMag); 36 | 37 | double maxVal; 38 | cv::minMaxLoc( gradMag, NULL, &maxVal); 39 | cv::Mat gradient; 40 | cv::convertScaleAbs( gradMag*(255/maxVal), gradient ); 41 | 42 | // Display intermediate images for debugging 43 | cv::Mat dest; 44 | createOutput( gradient, dest ); 45 | return dest; 46 | } 47 | 48 | void SobelProcessor::init(const char* json) { 49 | // Read json string to set properties 50 | using namespace rapidjson; 51 | Document document; 52 | document.Parse(json); 53 | assert(document.IsObject()); 54 | assert(document.HasMember("ksize")); 55 | ksize = document["ksize"].GetInt(); 56 | } 57 | 58 | std::string SobelProcessor::getParameters() { 59 | std::ostringstream os; 60 | os << "{\"ksize\":" << ksize << "}"; 61 | return os.str(); 62 | } 63 | 64 | void SobelProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 65 | { 66 | // Show intermediate images - need to expand CV_8UC1 to RGBA 67 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 68 | std::vector rgba_out; 69 | rgba_out.push_back( src ); 70 | rgba_out.push_back( src ); 71 | rgba_out.push_back( src ); 72 | rgba_out.push_back( fullAlpha ); 73 | 74 | cv::merge( rgba_out, dest); 75 | } 76 | 77 | namespace { 78 | auto scProcReg = ProcessorRegister("Sobel Derivative"); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /ImageProc/processor_watershed.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include "opencv2/imgproc/imgproc.hpp" 3 | #include 4 | 5 | class WatershedProcessor : public Processor { 6 | public: 7 | cv::Mat operator()(cv::Mat); 8 | private: 9 | static void createOutput(cv::Mat&, cv::Mat&); 10 | }; 11 | 12 | cv::Mat WatershedProcessor::operator()(cv::Mat im) { 13 | // Watershed segmentation demo from the OpenCV documentation 14 | cv::Mat grey; 15 | cv::cvtColor( im, im, CV_RGBA2BGR ); 16 | cv::cvtColor( im, grey, CV_BGR2GRAY ); 17 | 18 | // We look for dark objects on a light background, as the original demo 19 | // was designed for finding coins on a table. The THRESH_OTSU flag makes 20 | // OpenCV choose the optimum threshold levels for a given image. 21 | cv::Mat thresh; 22 | cv::threshold(grey, thresh, 0, 255, 23 | cv::THRESH_BINARY_INV + cv::THRESH_OTSU ); 24 | 25 | // Open image to remove noise 26 | cv::Mat kernel = cv::getStructuringElement( 27 | cv::MORPH_RECT, cv::Size(3,3)); 28 | cv::Mat opening; 29 | cv::morphologyEx( thresh, opening, cv::MORPH_OPEN, 30 | kernel, cv::Point(-1,1), 2); 31 | 32 | // Next we want to determine where the boundary between foreground and 33 | // background lies. 34 | 35 | // Sure background area. This is created by dilating the region we've 36 | // already highlighted. Any point that is still 0 must be part of the 37 | // background. Any highlighted point could be boundary or foreground. 38 | cv::Mat sureBg; 39 | cv::dilate( opening, sureBg, kernel, cv::Point(-1,1), 3); 40 | 41 | // Sure foreground area. We apply a distance transform to give each 42 | // point a value that is its distance from the nearest 0. This means 43 | // that points near the boundary of the thresholded image get a low 44 | // value, while ones further from the boundary get a higher value. 45 | cv::Mat distTfm; 46 | cv::distanceTransform( opening, distTfm, CV_DIST_L2, 5); 47 | cv::Mat sureFg; 48 | double minVal; 49 | double maxVal; 50 | cv::Point minLoc; 51 | cv::Point maxLoc; 52 | // Thresholding the distance transform image high lights areas far from 53 | // any boundary i.e. sure foreground features 54 | cv::minMaxLoc( distTfm, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() ); 55 | cv::threshold( distTfm, sureFg, 0.7*maxVal, 255, 0); 56 | 57 | // Convert to 8 bit unsigned for further processing 58 | sureFg.convertTo( sureFg, CV_8U); 59 | 60 | // Unknown regions - parts of the sure background excluding areas we know 61 | // are the foreground regions. 62 | cv::Mat unknown; 63 | cv::subtract( sureBg, sureFg, unknown ); 64 | 65 | // Now need to create a mask for the watershed algorithm. We want to set 66 | // each foreground object to have a unique index, and give the background 67 | // another index. The region we are unsure of gets labelled with 0. 68 | std::vector> contours; 69 | std::vector hierarchy; 70 | cv::findContours( sureFg, contours, hierarchy, cv::RETR_CCOMP, 71 | cv::CHAIN_APPROX_SIMPLE ); 72 | 73 | // Go through each foreground object and draw it to the marker matrix as 74 | // a differet positive integer. 75 | cv::Mat markers( sureFg.size(), CV_32S ); 76 | int idx = 0; 77 | int compCount = 0; 78 | for (; idx >= 0; idx = hierarchy[idx][0], compCount++ ) { 79 | cv::drawContours( markers, contours, idx, cv::Scalar(compCount+1), 80 | CV_FILLED, 8, hierarchy, INT_MAX ); 81 | } 82 | // Set the marker for the background to be a different positive integer 83 | cv::add( markers, cv::Scalar(1), markers); // Non-zero background 84 | // Set all the unknown areas to 0. 85 | markers.setTo( cv::Scalar(0), unknown == 255 ); 86 | 87 | // Watershed sets all of the markers == 0 points to the closest labelled 88 | // region, and marks the boundaries with a -1. 89 | cv::watershed( im, markers ); 90 | // Highlight the boundaries on the original image 91 | im.setTo( cv::Scalar(0,0,255), markers == -1); 92 | 93 | // Used for displaying the final marker matrix 94 | // markers.convertTo( markers, CV_8U); 95 | 96 | // Display intermediate images for debugging 97 | // cv::Mat dest; 98 | // createOutput( markers, dest ); 99 | cv::cvtColor( im, im, CV_BGR2RGBA ); 100 | return im; 101 | } 102 | 103 | void WatershedProcessor::createOutput( cv::Mat& src, cv::Mat& dest ) 104 | { 105 | // Show intermediate images - need to expand CV_8UC1 to RGBA 106 | cv::Mat fullAlpha = cv::Mat( src.size(), CV_8UC1, cv::Scalar(255)); 107 | std::vector rgba_out; 108 | rgba_out.push_back( src ); 109 | rgba_out.push_back( src ); 110 | rgba_out.push_back( src ); 111 | rgba_out.push_back( fullAlpha ); 112 | 113 | cv::merge( rgba_out, dest); 114 | } 115 | 116 | namespace { 117 | auto scProcReg = ProcessorRegister("Watershed Segment"); 118 | } 119 | 120 | -------------------------------------------------------------------------------- /ImageProc/singleton_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SINGLETON_FACTORY_HPP 2 | #define SINGLETON_FACTORY_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "processor.hpp" 10 | 11 | template 12 | class SingletonFactory { 13 | public: 14 | T getObject( std::string name ) const; 15 | std::vector getNames() const; 16 | static SingletonFactory& getInstance(); 17 | void registerObject( std::string name, T fcn) ; 18 | ~SingletonFactory(){}; 19 | private: 20 | std::map SingletonCreatorFcns; 21 | SingletonFactory(){}; 22 | }; 23 | 24 | template 25 | class ObjectRegister { 26 | // Helper class to allow registration of scenes by construction of global 27 | // variables in a hidden namespace. 28 | // See p164 of Joshi "C++ design patterns for derivatives pricing" 29 | // Note that the C++11 language features make this pattern a lot simpler. 30 | 31 | public: 32 | ObjectRegister( std::string name, T fcn ) { 33 | auto& theFactory = SingletonFactory::getInstance(); 34 | theFactory.registerObject( name, fcn ); 35 | } 36 | }; 37 | 38 | // Singleton factory for registering derived Processor classes 39 | template 40 | class ProcessorRegister { 41 | public: 42 | ProcessorRegister( std::string name ) { 43 | auto& theFactory = 44 | SingletonFactory()>>::getInstance(); 45 | theFactory.registerObject( name, []() { return 46 | std::unique_ptr(new T());} ); 47 | } 48 | }; 49 | 50 | 51 | template 52 | void SingletonFactory::registerObject( std::string name, T fcn) { 53 | SingletonCreatorFcns.insert( 54 | std::pair(name, fcn)); 55 | } 56 | 57 | template 58 | T SingletonFactory::getObject( std::string name) const { 59 | auto it = SingletonCreatorFcns.find(name); 60 | if ( it == SingletonCreatorFcns.end() ) { 61 | return NULL; 62 | } 63 | return (it->second); 64 | } 65 | 66 | template 67 | std::vector SingletonFactory::getNames( ) const { 68 | std::vector names; 69 | for (auto entry : SingletonCreatorFcns ) { 70 | names.push_back( entry.first ); 71 | } 72 | return names; 73 | } 74 | 75 | template 76 | SingletonFactory& SingletonFactory::getInstance(){ 77 | static SingletonFactory theFactory; 78 | return theFactory; 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /ImageProc/smiley_200x200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmcd/NaCl/56e0f6a5d45bb35f13ae63d79425b329667aba3a/ImageProc/smiley_200x200.png -------------------------------------------------------------------------------- /ImageProc/test/Makefile: -------------------------------------------------------------------------------- 1 | all: simpledom 2 | 3 | INCLUDE_DIR = /home/mattmcd/Work/Projects/NaCl/ImageProc/include 4 | 5 | simpledom: simpledom.cpp 6 | $(CXX) simpledom.cpp -o simpledom -I$(INCLUDE_DIR) 7 | -------------------------------------------------------------------------------- /ImageProc/test/simpledom.cpp: -------------------------------------------------------------------------------- 1 | // rapidjson/example/simpledom/simpledom.cpp` 2 | #define CATCH_CONFIG_MAIN 3 | #include "catch/catch.hpp" 4 | #include "rapidjson/document.h" 5 | #include "rapidjson/writer.h" 6 | #include "rapidjson/stringbuffer.h" 7 | #include 8 | 9 | using namespace rapidjson; 10 | 11 | TEST_CASE("JSON Parsed", "[rapidjson]"){ 12 | // 1. Parse a JSON string into DOM. 13 | const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; 14 | Document d; 15 | d.Parse(json); 16 | 17 | // 2. Modify it by DOM. 18 | Value& s = d["stars"]; 19 | s.SetInt(s.GetInt() + 1); 20 | REQUIRE(s.GetInt() == 11); 21 | 22 | // 3. Stringify the DOM 23 | StringBuffer buffer; 24 | Writer writer(buffer); 25 | d.Accept(writer); 26 | 27 | // Output {"project":"rapidjson","stars":11} 28 | const std::string expectedString = "{\"project\":\"rapidjson\",\"stars\":11}"; 29 | const std::string testString = buffer.GetString(); 30 | REQUIRE( testString == expectedString ); 31 | // std::cout << buffer.GetString() << std::endl; 32 | // return 0; 33 | } 34 | -------------------------------------------------------------------------------- /ImageProc/test_display.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char* argv[]) 9 | { 10 | 11 | const char* fname = "mmcdonne.jpg"; 12 | const char* json = ""; 13 | if (argc > 1) { 14 | fname = argv[1]; 15 | } 16 | if (argc > 2) { 17 | json = argv[2]; 18 | } 19 | cv::Mat input; 20 | input = cv::imread( fname, CV_LOAD_IMAGE_COLOR ); 21 | if (!input.data) { 22 | std::cout << "Could not read image " << fname << std::endl; 23 | return -1; 24 | } 25 | // Processors expect 8UC4 26 | cv::Mat im; 27 | cv::cvtColor( input, im, CV_BGR2RGBA ); 28 | 29 | // Use first processor 30 | auto processorFactory = SingletonFactory()>>::getInstance(); 31 | auto names = processorFactory.getNames(); 32 | auto processor = processorFactory.getObject( names[0] )(); 33 | if ( names[0] == "Smiley!" ) { 34 | cv::Mat smiley; 35 | smiley = cv::imread( "smiley_200x200.png", CV_LOAD_IMAGE_UNCHANGED ); 36 | processor->init( smiley ); 37 | } 38 | if ( json != "" ) { 39 | std::cout << json << std::endl; 40 | processor->init(json); 41 | } 42 | std::cout << "Paramters:" << processor->getParameters() << std::endl; 43 | auto output = (*processor)( im ); 44 | std::cout << "In: " << input.cols<< "x" << input.rows << " " 45 | << "Out: " << output.cols << "x" << output.rows << std::endl; 46 | cv::cvtColor( output, output, CV_RGBA2BGR ); 47 | 48 | cv::namedWindow( "Input and Processed", CV_WINDOW_AUTOSIZE ); 49 | // Create large image showing original and processed side by side 50 | cv::Mat combined(std::max(input.rows,output.rows), 51 | input.cols + output.cols + input.cols, input.type()); 52 | cv::Mat roiLeft = combined(cv::Rect(0,0,input.cols,input.rows)); 53 | cv::Mat roiCentre = combined(cv::Rect(input.cols,0,output.cols,output.rows)); 54 | cv::Mat roiRight = combined(cv::Rect(2*input.cols,0,output.cols,output.rows)); 55 | input.copyTo( roiLeft ); 56 | output.copyTo( roiRight ); 57 | // Create abs diff image 58 | cv::Mat diff; 59 | cv::absdiff(input, output, diff); 60 | cv::convertScaleAbs(diff, diff); 61 | diff.copyTo( roiCentre ); 62 | 63 | cv::imshow( "Input and Processed", combined); 64 | cv::moveWindow( "Input and Processed", 100, 100 ); 65 | cv::waitKey(); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /ImageProc/test_processor.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | cv::Mat input = cv::Mat( 2, 2, CV_8UC4, cv::Scalar(128,192,216,255)); 8 | std::cout << "Input = " << std::endl << input << std::endl << std::endl; 9 | 10 | auto processorName = "Invert"; 11 | if (argc > 1) { 12 | processorName = argv[1]; 13 | } 14 | auto processorFactory = SingletonFactory()>>::getInstance(); 15 | auto processor = processorFactory.getObject( processorName )(); 16 | auto output = (*processor)( input ); 17 | 18 | std::cout << "Output = " << std::endl << output << std::endl << std::endl; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /ImageProc/url_loader_handler.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | #include "ppapi/c/pp_errors.h" 8 | #include "ppapi/c/ppb_instance.h" 9 | #include "ppapi/cpp/module.h" 10 | #include "ppapi/cpp/var.h" 11 | #include "ppapi/cpp/var_dictionary.h" 12 | #include "ppapi/cpp/file_io.h" 13 | #include "ppapi/cpp/file_ref.h" 14 | 15 | #include "url_loader_handler.hpp" 16 | 17 | #ifdef WIN32 18 | #undef min 19 | #undef max 20 | #undef PostMessage 21 | 22 | // Allow 'this' in initializer list 23 | #pragma warning(disable : 4355) 24 | #endif 25 | 26 | URLLoaderHandler* URLLoaderHandler::Create(pp::Instance* instance, 27 | const std::string& url) { 28 | return new URLLoaderHandler(instance, url); 29 | } 30 | 31 | URLLoaderHandler::URLLoaderHandler(pp::Instance* instance, 32 | const std::string& url) 33 | : instance_(instance), 34 | url_(url), 35 | url_request_(instance), 36 | url_loader_(instance), 37 | buffer_(new char[READ_BUFFER_SIZE]), 38 | cc_factory_(this) { 39 | url_request_.SetURL(url); 40 | url_request_.SetMethod("GET"); 41 | url_request_.SetRecordDownloadProgress(true); 42 | } 43 | 44 | URLLoaderHandler::~URLLoaderHandler() { 45 | delete[] buffer_; 46 | buffer_ = NULL; 47 | } 48 | 49 | void URLLoaderHandler::Start() { 50 | pp::CompletionCallback cc = 51 | cc_factory_.NewCallback(&URLLoaderHandler::OnOpen); 52 | url_loader_.Open(url_request_, cc); 53 | } 54 | 55 | void URLLoaderHandler::OnOpen(int32_t result) { 56 | if (result != PP_OK) { 57 | ReportResultAndDie(url_, "pp::URLLoader::Open() failed", false); 58 | return; 59 | } 60 | // Here you would process the headers. A real program would want to at least 61 | // check the HTTP code and potentially cancel the request. 62 | // pp::URLResponseInfo response = loader_.GetResponseInfo(); 63 | 64 | // Try to figure out how many bytes of data are going to be downloaded in 65 | // order to allocate memory for the response body in advance (this will 66 | // reduce heap traffic and also the amount of memory allocated). 67 | // It is not a problem if this fails, it just means that the 68 | // url_response_body_.insert() call in URLLoaderHandler::AppendDataBytes() 69 | // will allocate the memory later on. 70 | int64_t bytes_received = 0; 71 | int64_t total_bytes_to_be_received = 0; 72 | if (url_loader_.GetDownloadProgress(&bytes_received, 73 | &total_bytes_to_be_received)) { 74 | if (total_bytes_to_be_received > 0) { 75 | url_response_body_.reserve(total_bytes_to_be_received); 76 | } 77 | } 78 | // We will not use the download progress anymore, so just disable it. 79 | url_request_.SetRecordDownloadProgress(false); 80 | 81 | // Start streaming. 82 | ReadBody(); 83 | } 84 | 85 | void URLLoaderHandler::AppendDataBytes(const char* buffer, int32_t num_bytes) { 86 | if (num_bytes <= 0) 87 | return; 88 | // Make sure we don't get a buffer overrun. 89 | num_bytes = std::min(READ_BUFFER_SIZE, num_bytes); 90 | // Note that we do *not* try to minimally increase the amount of allocated 91 | // memory here by calling url_response_body_.reserve(). Doing so causes a 92 | // lot of string reallocations that kills performance for large files. 93 | url_response_body_.insert( 94 | url_response_body_.end(), buffer, buffer + num_bytes); 95 | } 96 | 97 | void URLLoaderHandler::OnRead(int32_t result) { 98 | if (result == PP_OK) { 99 | // Streaming the file is complete, delete the read buffer since it is 100 | // no longer needed. 101 | delete[] buffer_; 102 | buffer_ = NULL; 103 | ReportResultAndDie(url_, url_response_body_, true); 104 | } else if (result > 0) { 105 | // The URLLoader just filled "result" number of bytes into our buffer. 106 | // Save them and perform another read. 107 | AppendDataBytes(buffer_, result); 108 | ReadBody(); 109 | } else { 110 | // A read error occurred. 111 | ReportResultAndDie( 112 | url_, "pp::URLLoader::ReadResponseBody() result<0", false); 113 | } 114 | } 115 | 116 | void URLLoaderHandler::ReadBody() { 117 | // Note that you specifically want an "optional" callback here. This will 118 | // allow ReadBody() to return synchronously, ignoring your completion 119 | // callback, if data is available. For fast connections and large files, 120 | // reading as fast as we can will make a large performance difference 121 | // However, in the case of a synchronous return, we need to be sure to run 122 | // the callback we created since the loader won't do anything with it. 123 | pp::CompletionCallback cc = 124 | cc_factory_.NewOptionalCallback(&URLLoaderHandler::OnRead); 125 | int32_t result = PP_OK; 126 | do { 127 | result = url_loader_.ReadResponseBody(buffer_, READ_BUFFER_SIZE, cc); 128 | // Handle streaming data directly. Note that we *don't* want to call 129 | // OnRead here, since in the case of result > 0 it will schedule 130 | // another call to this function. If the network is very fast, we could 131 | // end up with a deeply recursive stack. 132 | if (result > 0) { 133 | AppendDataBytes(buffer_, result); 134 | } 135 | } while (result > 0); 136 | 137 | if (result != PP_OK_COMPLETIONPENDING) { 138 | // Either we reached the end of the stream (result == PP_OK) or there was 139 | // an error. We want OnRead to get called no matter what to handle 140 | // that case, whether the error is synchronous or asynchronous. If the 141 | // result code *is* COMPLETIONPENDING, our callback will be called 142 | // asynchronously. 143 | cc.Run(result); 144 | } 145 | } 146 | 147 | void URLLoaderHandler::ReportResultAndDie(const std::string& fname, 148 | const std::string& text, 149 | bool success) { 150 | ReportResult(fname, text, success); 151 | delete this; 152 | } 153 | 154 | void URLLoaderHandler::ReportResult(const std::string& fname, 155 | const std::string& text, 156 | bool success) { 157 | std::string status; 158 | if (success) { 159 | printf("URLLoaderHandler::ReportResult(Ok).\n"); 160 | status = "Loaded URL OK"; 161 | } else { 162 | printf("URLLoaderHandler::ReportResult(Err). %s\n", text.c_str()); 163 | status = "URL load failed: " + text; 164 | } 165 | fflush(stdout); 166 | if (instance_) { 167 | pp::VarDictionary msg; 168 | msg.Set( "Type", "resource_loaded" ); 169 | msg.Set( "Message", status ); 170 | msg.Set( "Data", text ); 171 | instance_->PostMessage( msg ); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /ImageProc/url_loader_handler.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #ifndef URL_LOADER_HANDLER_H_ 6 | #define URL_LOADER_HANDLER_H_ 7 | 8 | #include 9 | #include "ppapi/cpp/completion_callback.h" 10 | #include "ppapi/cpp/instance.h" 11 | #include "ppapi/cpp/url_loader.h" 12 | #include "ppapi/cpp/url_request_info.h" 13 | #include "ppapi/utility/completion_callback_factory.h" 14 | #define READ_BUFFER_SIZE 32768 15 | 16 | // URLLoaderHandler is used to download data from |url|. When download is 17 | // finished or when an error occurs, it posts a message back to the browser 18 | // with the results encoded in the message as a string and self-destroys. 19 | // 20 | // pp::URLLoader.GetDownloadProgress() is used to to allocate the memory 21 | // required for url_response_body_ before the download starts. (This is not so 22 | // much of a performance improvement, but it saves some memory since 23 | // std::string.insert() typically grows the string's capacity by somewhere 24 | // between 50% to 100% when it needs more memory, depending on the 25 | // implementation.) Other performance improvements made as outlined in this 26 | // bug: http://code.google.com/p/chromium/issues/detail?id=103947 27 | // 28 | // EXAMPLE USAGE: 29 | // URLLoaderHandler* handler* = URLLoaderHandler::Create(instance,url); 30 | // handler->Start(); 31 | // 32 | class URLLoaderHandler { 33 | public: 34 | // Creates instance of URLLoaderHandler on the heap. 35 | // URLLoaderHandler objects shall be created only on the heap (they 36 | // self-destroy when all data is in). 37 | static URLLoaderHandler* Create(pp::Instance* instance_, 38 | const std::string& url); 39 | // Initiates page (URL) download. 40 | void Start(); 41 | 42 | private: 43 | URLLoaderHandler(pp::Instance* instance_, const std::string& url); 44 | ~URLLoaderHandler(); 45 | 46 | // Callback for the pp::URLLoader::Open(). 47 | // Called by pp::URLLoader when response headers are received or when an 48 | // error occurs (in response to the call of pp::URLLoader::Open()). 49 | // Look at and 50 | // for more information about pp::URLLoader. 51 | void OnOpen(int32_t result); 52 | 53 | // Callback for the pp::URLLoader::ReadResponseBody(). 54 | // |result| contains the number of bytes read or an error code. 55 | // Appends data from this->buffer_ to this->url_response_body_. 56 | void OnRead(int32_t result); 57 | 58 | // Reads the response body (asynchronously) into this->buffer_. 59 | // OnRead() will be called when bytes are received or when an error occurs. 60 | void ReadBody(); 61 | 62 | // Append data bytes read from the URL onto the internal buffer. Does 63 | // nothing if |num_bytes| is 0. 64 | void AppendDataBytes(const char* buffer, int32_t num_bytes); 65 | 66 | // Post a message back to the browser with the download results. 67 | void ReportResult(const std::string& fname, 68 | const std::string& text, 69 | bool success); 70 | // Post a message back to the browser with the download results and 71 | // self-destroy. |this| is no longer valid when this method returns. 72 | void ReportResultAndDie(const std::string& fname, 73 | const std::string& text, 74 | bool success); 75 | 76 | pp::Instance* instance_; // Weak pointer. 77 | std::string url_; // URL to be downloaded. 78 | pp::URLRequestInfo url_request_; 79 | pp::URLLoader url_loader_; // URLLoader provides an API to download URLs. 80 | char* buffer_; // Temporary buffer for reads. 81 | std::string url_response_body_; // Contains accumulated downloaded data. 82 | pp::CompletionCallbackFactory cc_factory_; 83 | 84 | URLLoaderHandler(const URLLoaderHandler&); 85 | void operator=(const URLLoaderHandler&); 86 | }; 87 | 88 | #endif // URL_LOADER_HANDLER_H_ 89 | -------------------------------------------------------------------------------- /ImageProc/video.js: -------------------------------------------------------------------------------- 1 | // Global handle to module 2 | var ImageProcModule = null; 3 | 4 | // Global status message 5 | var statusText = 'NO-STATUS'; 6 | var lastClick = null; 7 | 8 | var isRunning = false; 9 | var isReadyToReceive = false; 10 | 11 | var startTime; 12 | var endTime; 13 | var averageFramePeriod; 14 | var ewmaSmooth = 0.3; 15 | 16 | var videoSourceId; 17 | var selectedSource; 18 | 19 | var imageData; 20 | var cachedSmiley; 21 | 22 | var view; 23 | 24 | // Parameters for current processor 25 | var parameters; 26 | 27 | function pageDidLoad() { 28 | var src = make_image_source(); 29 | view = make_image_source_view(src); 30 | view.init("live", "display", "camera"); 31 | var camera = document.getElementById("camera"); 32 | camera.hidden = true; 33 | var listener = document.getElementById("listener"); 34 | listener.addEventListener("load", moduleDidLoad, true ); 35 | listener.addEventListener("message", handleMessage, true ); 36 | if ( ImageProcModule == null ) { 37 | updateStatus( 'LOADING...' ); 38 | } else { 39 | updateStatus(); 40 | } 41 | 42 | } 43 | 44 | function loadResource() { 45 | var cmd = { cmd: "load", 46 | url: "smiley_col.bmp" }; 47 | ImageProcModule.postMessage( cmd ); 48 | } 49 | 50 | function sendImage() { 51 | if ( isRunning && isReadyToReceive ) { 52 | // Get the current frame from canvas and send to NaCl 53 | // drawImage( pixels ); 54 | var imData = view.getImageData(); 55 | 56 | var theCommand = "process"; //"echo"; // test, process 57 | var selectedProcessor = getSelectedProcessor(); 58 | var cmd = { cmd: theCommand, 59 | width: imData.width, 60 | height: imData.height, 61 | data: imData.data, 62 | processor: selectedProcessor }; 63 | if ( selectedProcessor === "Smiley!" ) { 64 | cmd.args = cachedSmiley; 65 | } else if ( parameters ) { 66 | cmd.args = JSON.stringify( parameters ); 67 | } 68 | startTime = performance.now(); 69 | ImageProcModule.postMessage( cmd ); 70 | isReadyToReceive = false; // Don't send any more frames until ready 71 | } else if (isRunning ) { 72 | // Do nothing 73 | } else { 74 | updateStatus( 'Stopped' ); 75 | } 76 | setTimeout( sendImage, view.getSamplePeriod() ); 77 | } 78 | 79 | function drawImage(pixels){ 80 | var processed = document.getElementById("processed"); 81 | var ctx = processed.getContext( "2d" ); 82 | var imData = ctx.getImageData(0,0,processed.width,processed.height); 83 | var buf8 = new Uint8ClampedArray( pixels ); 84 | imData.data.set( buf8 ); 85 | ctx.putImageData( imData, 0, 0); 86 | } 87 | 88 | function moduleDidLoad() { 89 | ImageProcModule = document.getElementById( "image_proc" ); 90 | updateStatus( "OK" ); 91 | // Load image resource 92 | // loadResource(); 93 | var cv = document.getElementById( "smiley_canvas" ); 94 | var ctx = cv.getContext( "2d" ); 95 | var smiley = document.getElementById( "smiley" ); 96 | ctx.drawImage(smiley, 0, 0); 97 | imageData = ctx.getImageData( 0, 0, smiley.width, smiley.height); 98 | cachedSmiley = view.getImageData("smiley_canvas"); 99 | 100 | var run = document.getElementById( "run" ); 101 | run.onclick = toggleSending; 102 | 103 | var stream = document.getElementById("stream"); 104 | stream.onclick = toggleStream; 105 | stream.value = "On"; 106 | stream.textContent = stream.value; 107 | stream.hidden = false; 108 | 109 | var camera = document.getElementById("camera"); 110 | camera.hidden = false; 111 | run.hidden = false; 112 | } 113 | 114 | function toggleStream() { 115 | // Toggle input video stream on/off 116 | var stream = document.getElementById("stream"); 117 | if (stream.value === 'On') { 118 | // Stop camera 119 | stream.value = 'Off'; 120 | view.stop(); 121 | } else { 122 | // Start camera 123 | stream.value = 'On'; 124 | view.start(); 125 | } 126 | stream.textContent = stream.value; 127 | } 128 | 129 | function toggleSending() { 130 | var run = document.getElementById( "run" ); 131 | if (isRunning) { 132 | // Stop processing 133 | isRunning = false; 134 | isReadyToReceive = false; 135 | run.value = "Go"; 136 | } else { 137 | // Start processing 138 | isRunning = true; 139 | isReadyToReceive = true; 140 | run.value = "Stop"; 141 | } 142 | run.textContent = run.value; 143 | sendImage(); 144 | } 145 | 146 | function handleMessage(message_event) { 147 | var res = message_event.data; 148 | if ( res.Type == "version" ) { 149 | updateStatus( res.Version ); 150 | updateProcessors( res.Processors ); 151 | } 152 | if ( res.Type == "completed" ) { 153 | if ( res.Data ) { 154 | // updateStatus( "Received array buffer"); 155 | // Display processed image 156 | endTime = performance.now(); 157 | if (typeof averageFramePeriod === 'undefined' ) { 158 | averageFramePeriod = view.getSamplePeriod(); 159 | } 160 | averageFramePeriod = (1-ewmaSmooth)*averageFramePeriod + ewmaSmooth*(endTime-startTime); 161 | updateStatus( 'Frame rate is ' + (averageFramePeriod).toFixed(1) + 'ms per frame' ); 162 | drawImage( res.Data ); 163 | isReadyToReceive = true; 164 | } else { 165 | updateStatus( "Received something unexpected"); 166 | } 167 | if ( res.Parameters ) { 168 | parameters = JSON.parse( res.Parameters ); 169 | } else { 170 | parameters = ""; 171 | } 172 | 173 | // Display processed image 174 | //drawImage( res.Data ); 175 | } 176 | if ( res.Type == "status" ) { 177 | // updateStatus( res.Message ); 178 | } 179 | if ( res.Type == "resource_loaded" ) { 180 | // Load image from server 181 | updateStatus( res.Message ); 182 | imageData = res.Data; 183 | } 184 | } 185 | 186 | function updateStatus( optMessage ) { 187 | if (optMessage) 188 | statusText = optMessage; 189 | var statusField = document.getElementById("statusField"); 190 | if (statusField) { 191 | statusField.innerHTML = " : " + statusText; 192 | } 193 | } 194 | 195 | function updateProcessors( processorNames ) { 196 | var processors = document.getElementById( "processor" ); 197 | for (i=0; i 2 | 3 | 4 | Monte Carlo simulation 5 | 6 | 7 | 8 | 9 |

Monte Carlo simulation using NaCl

10 | 11 |

This page uses 13 | Google Native Client to perform a 15 | Monte Carlo simulation that estimates the fraction of points in the 16 | unit square falling below the selected curve by random sampling using the 17 | selected number of points. The simulation runs in 18 | portable native code, taking around 1 second per million points.

19 | 20 |

Requires Chrome web browser version 31 or above (not Android app)

21 | 22 |
23 | 24 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 |

Status NO-STATUS

34 | 35 |
36 | 37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /MonteCarlo/instance_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INSTANCE_FACTORY_HPP 2 | #define INSTANCE_FACTORY_HPP 3 | 4 | #include "ppapi/cpp/instance.h" 5 | #include "ppapi/cpp/module.h" 6 | #include "ppapi/cpp/var.h" 7 | 8 | // Factory method called by the browser when first loaded 9 | namespace pp { 10 | Module* CreateModule(); 11 | }; 12 | 13 | // Module used to create instance of NaCl module on webpage 14 | template 15 | class InstanceFactory : public pp::Module { 16 | public: 17 | InstanceFactory( ){}; 18 | virtual ~InstanceFactory(){}; 19 | virtual pp::Instance* CreateInstance( PP_Instance instance ) { 20 | return new T(instance); 21 | }; 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /MonteCarlo/mcView.js: -------------------------------------------------------------------------------- 1 | // Global handle to module 2 | var MonteCarloModule = null; 3 | 4 | // Global status message 5 | var statusText = 'NO-STATUS'; 6 | 7 | var lastClick = null; 8 | 9 | var nPtsSim = null; 10 | 11 | var results = new Array(); 12 | 13 | function pageDidLoad() { 14 | var listener = document.getElementById("listener"); 15 | listener.addEventListener("load", moduleDidLoad, true ); 16 | listener.addEventListener("message", handleMessage, true ); 17 | if ( MonteCarloModule == null ) { 18 | updateStatus( 'LOADING...' ); 19 | } else { 20 | updateStatus(); 21 | } 22 | } 23 | 24 | function moduleDidLoad() { 25 | MonteCarloModule = document.getElementById( "monte_carlo" ); 26 | updateStatus( "OK" ); 27 | var go = document.getElementById( "go" ); 28 | var nPts = document.getElementById( "nPts" ); 29 | var modelList = document.getElementById( "model" ); 30 | go.onclick = function() { 31 | nPtsSim = Number( nPts.value ); 32 | console.log( "Sending " + nPtsSim); 33 | updateStatus( "Sending " + nPtsSim); 34 | lastClick = Date.now(); 35 | // clear results 36 | results.length = 0; 37 | var model = modelList[ modelList.selectedIndex ].text; 38 | var cmd = { cmd: "sim", nPts: nPtsSim, model: model }; 39 | MonteCarloModule.postMessage( cmd ); 40 | updateControls_SimRunning(); 41 | }; 42 | // Stop button 43 | var stop = document.getElementById( "stop" ); 44 | stop.onclick = function() { 45 | console.log( "Stop sent" ); 46 | MonteCarloModule.postMessage( { cmd: "stop" } ); 47 | } 48 | updateControls_SimStopped(); 49 | } 50 | 51 | function handleMessage(message_event) { 52 | var res = message_event.data; 53 | if ( res.Type == "version" ) { 54 | updateStatus( res.Version ); 55 | updateModels( res.Models ); 56 | } else if ( res.Type == "partial" ) { 57 | var pctComplete = 100*res.Samples/nPtsSim; 58 | if ( Math.floor( pctComplete/10 ) > results.length ) { 59 | results[results.length] = res; // Add result to list of results 60 | } 61 | updateStatus( "Received: " + res.Mean.toFixed(7) 62 | + " +/- " + res.StdError.toFixed(7) 63 | + " after " + pctComplete.toFixed(1) + "% completion" ); 64 | } 65 | if ( res.Type == "completed" ) { 66 | if ( results.length > 0 ) { 67 | // Show the full table and plot 68 | console.log( "Received " + results.length + " results" ); 69 | var tDiff = Date.now() - lastClick; 70 | updateStatus( "Received: " + results[results.length-1].Mean.toFixed(7) 71 | + " +/- " + results[results.length-1].StdError.toFixed(7) 72 | + " after " + tDiff + "ms" + " for " + results[results.length-1].Samples + " points" ); 73 | updateTable( results ); 74 | updatePlot( results ); 75 | } else { 76 | // Simulation stopped before any data received 77 | updateStatus( "Stopped" ); 78 | } 79 | updateControls_SimStopped(); 80 | } 81 | } 82 | 83 | function updateStatus( optMessage ) { 84 | if (optMessage) 85 | statusText = optMessage; 86 | var statusField = document.getElementById("statusField"); 87 | if (statusField) { 88 | statusField.innerHTML = " : " + statusText; 89 | } 90 | } 91 | 92 | function updateModels( models ) { 93 | // Add model names to listbox 94 | var modelList = d3.select("#model"); 95 | var options = modelList.selectAll("option") 96 | .data( models ).enter().append("option") 97 | .text( function (d) {return d; }); 98 | } 99 | 100 | function updateTable( res ) { 101 | // D3 visualization 102 | d3.select("#results table").remove(); // Remove old data 103 | var table = d3.select("#results").append("table"); 104 | var th = table.selectAll("th") 105 | .data(["Samples","Total","Mean","Std Error"]) 106 | .enter().append("th").text( function (d) { return d; }); 107 | var tr = table.selectAll("tr") 108 | .data( res ) 109 | .enter().append("tr"); 110 | var td = tr.selectAll("td") 111 | .data( function (d) { 112 | return [d.Samples, d.Total, d.Mean.toFixed(7), d.StdError.toFixed(7)]; }) 113 | .enter().append("td"); 114 | td.text( function (d) { return d; }); 115 | } 116 | 117 | function updatePlot( res ){ 118 | d3.select("#plot svg").remove(); 119 | var w=320, h=200; 120 | var x = d3.scale.linear().domain([0, res[res.length-1].Samples]).range( [0, w]); 121 | var y = d3.scale.linear().domain([0, 1]).range([0, h]); 122 | var chart = d3.select("#plot").append("svg").attr("width", w).attr("height", h); 123 | var rect = chart.selectAll("rect").data( res ); 124 | var barWidth = 10; 125 | rect.enter() 126 | .append("rect") 127 | .attr("x", function (d,i) { return x(d.Samples) - barWidth;}) 128 | .attr("y", function (d,i) { return h - y(d.Mean + d.StdError/2); }) 129 | .attr("width", function (d,i) { return barWidth; }) 130 | .attr("height", function (d,i) { return Math.max( y( d.StdError ), 1); }) 131 | .style("fill", "steelblue"); 132 | chart.append("line").attr("x1", 0).attr("x2",w).attr("y1",h).attr("y2",h).style("stroke","#000000"); 133 | chart.append("line").attr("x1", 0).attr("x2",0).attr("y1",h).attr("y2",0).style("stroke","#000000"); 134 | } 135 | 136 | function updateControls_SimRunning() { 137 | d3.select("#results table").remove(); // Remove old data 138 | d3.select("#plot svg").remove(); // Remove old data 139 | var go = document.getElementById( "go" ); 140 | var nPts = document.getElementById( "nPts" ); 141 | var model = document.getElementById( "model" ); 142 | var stop = document.getElementById( "stop" ); 143 | go.disabled = true; 144 | nPts.disabled = true; 145 | model.disabled = true; 146 | stop.disabled = false; 147 | } 148 | 149 | function updateControls_SimStopped() { 150 | var go = document.getElementById( "go" ); 151 | var nPts = document.getElementById( "nPts" ); 152 | var model = document.getElementById( "model" ); 153 | var stop = document.getElementById( "stop" ); 154 | go.disabled = false; 155 | nPts.disabled = false; 156 | model.disabled = false; 157 | stop.disabled = true; 158 | } 159 | -------------------------------------------------------------------------------- /MonteCarlo/mc_instance.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MC_INSTANCE 2 | #define MC_INSTANCE 3 | 4 | #include "singleton_factory.hpp" 5 | #include "instance_factory.hpp" 6 | #include "monte_carlo.hpp" 7 | #include "ppapi/cpp/var_dictionary.h" 8 | #include "ppapi/cpp/var_array.h" 9 | #include "ppapi/utility/completion_callback_factory.h" 10 | #include "ppapi/utility/threading/simple_thread.h" 11 | 12 | // The MonteCarloInstance that stores 13 | class MonteCarloInstance : public pp::Instance { 14 | public: 15 | explicit MonteCarloInstance( PP_Instance instance ) 16 | : pp::Instance(instance), callback_factory_(this), sim_thread_(this) {}; 17 | virtual ~MonteCarloInstance( ){ sim_thread_.Join(); }; 18 | virtual void HandleMessage( const pp::Var& ); 19 | virtual bool Init(uint32_t /*argc*/, 20 | const char * /*argn*/ [], 21 | const char * /*argv*/ []) { 22 | sim_thread_.Start(); 23 | sim_thread_.message_loop().PostWork( 24 | callback_factory_.NewCallback( &MonteCarloInstance::Version )); 25 | return true; 26 | } 27 | 28 | private: 29 | bool run_simulation_; 30 | MonteCarlo mc; 31 | pp::CompletionCallbackFactory callback_factory_; 32 | pp::SimpleThread sim_thread_; // Thread for MC simulations 33 | void Simulate(int32_t, std::function, unsigned int N); 34 | pp::VarDictionary PostResponse( len_t runningTotal, len_t i); 35 | void Version( int32_t ) { 36 | pp::VarDictionary msg; 37 | msg.Set( "Type", "version" ); 38 | msg.Set( "Version", "Monte Carlo Version 0.2.1" ); 39 | // Get models 40 | auto modelFactory = SingletonFactory>::getInstance(); 41 | auto modelList = modelFactory.getNames(); 42 | pp::VarArray msgModelList; 43 | for ( size_t i=0; i < modelList.size(); i ++ ) { 44 | msgModelList.Set( i, modelList[i] ); 45 | } 46 | msg.Set( "Models", msgModelList ); 47 | PostMessage( msg ); 48 | } 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /MonteCarlo/model_circle.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | 3 | namespace { 4 | auto circleReg = ObjectRegister >("Circle", 5 | [](double x, double y){ return x*x + y*y < 1 ? 1 : 0; }); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /MonteCarlo/model_parabola.cpp: -------------------------------------------------------------------------------- 1 | #include "singleton_factory.hpp" 2 | 3 | namespace { 4 | auto parabolaReg = ObjectRegister >("Parabola", 5 | [](double x, double y){ return y < x*x ? 1 : 0; }); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /MonteCarlo/monte_carlo.cpp: -------------------------------------------------------------------------------- 1 | #include "mc_instance.hpp" 2 | #include "singleton_factory.hpp" 3 | #include 4 | #include 5 | #include 6 | 7 | pp::Module* pp::CreateModule() { 8 | return new InstanceFactory(); 9 | } 10 | 11 | void MonteCarloInstance::Simulate( int32_t /*result*/, 12 | std::function model, unsigned int N) { 13 | // Run the simulation in 10 parts or max 1e6 points at a time 14 | const len_t nParts = 10; 15 | auto step = N/nParts; 16 | step = step > 0 ? step : 1; 17 | step = step < 1e6 ? step : 1e6; 18 | len_t runningTotal = 0; 19 | unsigned int count=0; 20 | for( len_t i=step; i<=N; i += step) { 21 | if ( run_simulation_ ) { 22 | auto res = mc.sim(model, step); 23 | runningTotal += res.Total; 24 | auto outData = PostResponse( runningTotal, i); 25 | count++; 26 | } 27 | } 28 | pp::VarDictionary msg; 29 | msg.Set( "Type", "completed" ); 30 | PostMessage( msg ); 31 | } 32 | 33 | pp::VarDictionary MonteCarloInstance::PostResponse( len_t runningTotal, len_t i){ 34 | pp::VarDictionary outData; 35 | outData.Set( "Type", "partial" ); 36 | outData.Set( "Samples", static_cast(i) ); 37 | outData.Set( "Total", static_cast(runningTotal) ); 38 | auto runningMean = 1.0*runningTotal/i; 39 | outData.Set( "Mean", runningMean ); 40 | outData.Set( "StdError", sqrt( runningMean*(1.0-runningMean)/i)); 41 | PostMessage( outData ); // For progress measurement 42 | return outData; 43 | } 44 | 45 | void MonteCarloInstance::HandleMessage( const pp::Var& var_message ) { 46 | // Interface: receive a { cmd: ..., args... } dictionary 47 | // - sim, nPts = start simulation with that number of runs 48 | // - receive anything else = stop the simulation 49 | pp::VarDictionary var_dict( var_message ); 50 | auto cmd = var_dict.Get( "cmd" ).AsString(); 51 | if ( cmd == "sim" ) { 52 | // Message is number of simulations to run 53 | auto N = var_dict.Get("nPts").AsInt(); 54 | auto modelFactory = SingletonFactory>::getInstance(); 55 | auto model = modelFactory.getObject( var_dict.Get("model").AsString() ); 56 | // Enable simulation 57 | run_simulation_ = true; 58 | // Start simulation on background thread 59 | sim_thread_.message_loop().PostWork( 60 | callback_factory_.NewCallback( &MonteCarloInstance::Simulate, model, N)); 61 | } else { 62 | // Disable simulation - background thread will see this at start of 63 | // next iteration and terminate early 64 | run_simulation_ = false; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /MonteCarlo/monte_carlo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MONTE_CARLO_HPP 2 | #define MONTE_CARLO_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef long unsigned int len_t; 9 | 10 | struct result { 11 | double Mean; 12 | double StDev; 13 | len_t Total; // Total number of points 14 | len_t PointCount; // Number that passed 15 | }; 16 | 17 | class MonteCarlo { 18 | public: 19 | explicit MonteCarlo() : unifdist(0.0,1.0) { 20 | }; 21 | virtual ~MonteCarlo() {}; 22 | result sim( std::function const& f, len_t N) { 23 | // Bind the generator to the first argument of distribution so that 24 | // we can call with rng() instead of dist(gen). 25 | // auto rng = std::bind( unifdist, generator ); 26 | 27 | len_t sum = 0; 28 | for( len_t i=0; i unifdist; 47 | 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /MonteCarlo/monte_carlo.nmf: -------------------------------------------------------------------------------- 1 | { "program" : 2 | { "portable" : 3 | { "pnacl-translate" : 4 | { "url" : "monte_carlo.pexe" 5 | } 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MonteCarlo/monte_carlo.pexe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmcd/NaCl/56e0f6a5d45bb35f13ae63d79425b329667aba3a/MonteCarlo/monte_carlo.pexe -------------------------------------------------------------------------------- /MonteCarlo/singleton_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SINGLETON_FACTORY_HPP 2 | #define SINGLETON_FACTORY_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | template 10 | class SingletonFactory { 11 | public: 12 | T getObject( std::string name ) const; 13 | std::vector getNames() const; 14 | static SingletonFactory& getInstance(); 15 | void registerObject( std::string name, T fcn) ; 16 | ~SingletonFactory(){}; 17 | private: 18 | std::map SingletonCreatorFcns; 19 | SingletonFactory(){}; 20 | }; 21 | 22 | template 23 | class ObjectRegister { 24 | // Helper class to allow registration of scenes by construction of global 25 | // variables in a hidden namespace. 26 | // See p164 of Joshi "C++ design patterns for derivatives pricing" 27 | // Note that the C++11 language features make this pattern a lot simpler. 28 | 29 | public: 30 | ObjectRegister( std::string name, T fcn ) { 31 | SingletonFactory& theFactory = SingletonFactory::getInstance(); 32 | theFactory.registerObject( name, fcn ); 33 | } 34 | }; 35 | 36 | template 37 | void SingletonFactory::registerObject( std::string name, T fcn) { 38 | SingletonCreatorFcns.insert( 39 | std::pair(name, fcn)); 40 | } 41 | 42 | template 43 | T SingletonFactory::getObject( std::string name) const { 44 | auto it = SingletonCreatorFcns.find(name); 45 | if ( it == SingletonCreatorFcns.end() ) { 46 | return NULL; 47 | } 48 | return (it->second); 49 | } 50 | 51 | template 52 | std::vector SingletonFactory::getNames( ) const { 53 | std::vector names; 54 | for (auto entry : SingletonCreatorFcns ) { 55 | names.push_back( entry.first ); 56 | } 57 | return names; 58 | } 59 | 60 | template 61 | SingletonFactory& SingletonFactory::getInstance(){ 62 | static SingletonFactory theFactory; 63 | return theFactory; 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /MonteCarlo/test_mc.cpp: -------------------------------------------------------------------------------- 1 | #include "monte_carlo.hpp" 2 | #include 3 | 4 | int main(int argc, char* argv[]) 5 | { 6 | MonteCarlo mc; 7 | 8 | // Function to estimate 9 | auto f = [](double x, double y){ return x*x + y*y < 1 ? 1 : 0; }; 10 | 11 | len_t nPts = 10; 12 | for (int i=0; i<6; ++i ) { 13 | auto res = mc.sim( f, nPts ); 14 | std::cout << nPts << ": Pi = " 15 | << 4.0*res.Mean << " +/- " 16 | << 4.0*res.StDev/sqrt(nPts) << std::endl; 17 | nPts *= 10; 18 | } 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NaCl 2 | ==== 3 | 4 | A collection of Google Native Client examples designed primarily to help me learn the platform. 5 | Development history so far: 6 | 7 | - Counter - simple example to get the build chain working. 8 | - Monte Carlo - a more complicated example to use user input and background threads. 9 | - ImageProc - use OpenCV naclport for image processing in the browser. 10 | - Simple - found out there are some example files in the distribution 11 | that simplify things. This is why it can be a good idea to read the doc 12 | occasionally. 13 | 14 | Setup 15 | ----- 16 | Please see setup.txt for steps needed to install NaCl SDK and naclports on Ubuntu 14.04. 17 | This works on Amazon AWS t2.micro instance so should be easy to get up and running. 18 | -------------------------------------------------------------------------------- /Simple/Makefile: -------------------------------------------------------------------------------- 1 | # Project Build flags 2 | WARNINGS := -Wno-long-long -Wall -Wswitch-enum -pedantic -Werror 3 | CXXFLAGS := -pthread -std=gnu++11 $(WARNINGS) 4 | 5 | # 6 | # Compute tool paths 7 | # 8 | GETOS := python $(NACL_SDK_ROOT)/tools/getos.py 9 | OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py 10 | OSNAME := $(shell $(GETOS)) 11 | RM := $(OSHELPERS) rm 12 | 13 | PNACL_TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain/$(OSNAME)_pnacl) 14 | PNACL_CXX := $(PNACL_TC_PATH)/bin/pnacl-clang++ 15 | PNACL_FINALIZE := $(PNACL_TC_PATH)/bin/pnacl-finalize 16 | PNACL_CXXFLAGS := -I$(NACL_SDK_ROOT)/include $(CXXFLAGS) 17 | PNACL_LDFLAGS := -L$(NACL_SDK_ROOT)/lib/pnacl/Release -lppapi_simple -lnacl_io -lppapi_cpp -lppapi -lpthread 18 | 19 | IMPROC_HEADERS := simple_template.cpp 20 | 21 | # Declare the ALL target first, to make the 'all' target the default build 22 | all: simple_template.pexe 23 | 24 | 25 | clean: 26 | $(RM) simple_template.pexe simple_template.bc 27 | 28 | #$(PROC_OBJECTS): $(PROCESSORS) singleton_factory.hpp 29 | # $(PNACL_CXX) -o $@ $< -O2 $(CXXFLAGS) $(LDFLAGS) 30 | 31 | simple_template.bc: $(IMPROC_HEADERS) $(PROCESSORS) 32 | $(PNACL_CXX) -o $@ $< -O2 $(PNACL_CXXFLAGS) $(PNACL_LDFLAGS) 33 | 34 | simple_template.pexe: simple_template.bc 35 | $(PNACL_FINALIZE) -o $@ $< 36 | 37 | serve: 38 | python -m SimpleHTTPServer 8000 39 | -------------------------------------------------------------------------------- /Simple/README.md: -------------------------------------------------------------------------------- 1 | PPAPI Simple 2 | ============ 3 | The PPAPI Simple library in the NaCl SDK allows a simplified method of 4 | construction of the NaCl components. 5 | -------------------------------------------------------------------------------- /Simple/example.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // Once we load, hide the plugin 6 | function moduleDidLoad() { 7 | common.hideModule(); 8 | } 9 | 10 | // Add event listeners 11 | function attachListeners() { 12 | document.getElementById('go').addEventListener( 'click', 13 | function() { 14 | common.naclModule.postMessage({'message':'hello'}); 15 | }); 16 | document.getElementById('quit').addEventListener( 'click', 17 | function() { 18 | common.naclModule.postMessage({'message':'quit'}); 19 | }); 20 | } 21 | 22 | // Called by the common.js module. 23 | // nacl_io/ppapi_simple generates two different types of messages: 24 | // - messages from /dev/tty (prefixed with PS_TTY_PREFIX) 25 | // - exit message (prefixed with PS_EXIT_MESSAGE) 26 | function handleMessage(message) { 27 | if (message.data.indexOf("exit:") == 0) { 28 | // When we receive the exit message we post an empty reply back to 29 | // confirm, at which point the module will exit. 30 | message.srcElement.postMessage({"exit" : ""}); 31 | } else if (message.data.indexOf("tty:") == 0) { 32 | common.logMessage(message.data.slice("tty:".length)); 33 | } else { 34 | console.log("Unhandled message: " + message.data); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Simple/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattmcd/NaCl/56e0f6a5d45bb35f13ae63d79425b329667aba3a/Simple/favicon.ico -------------------------------------------------------------------------------- /Simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | PPAPI Simple Template 12 | 13 | 14 | 15 | 16 |

PPAPI Simple Template

17 |

Simple template for communication between front end and NaCl backend 18 | using PPAPI Simple library. This example is a cut down combination of 19 | demos/voronoi and tutorials/using_simple_ppapi in the NaCl SDK examples. 20 |

Status: NO-STATUS

21 | 22 | 23 | 24 | 26 |

Output:

27 |

28 |   
29 | 30 | 31 | -------------------------------------------------------------------------------- /Simple/simple_template.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ppapi_simple/ps_interface.h" 10 | #include "ppapi_simple/ps_main.h" 11 | 12 | // The main object that runs SimpleTemplate simulation. 13 | class SimpleTemplate { 14 | public: 15 | SimpleTemplate(); 16 | virtual ~SimpleTemplate() {}; 17 | // Handle event from user, or message from JS. 18 | void HandleEvent(PSEvent* ps_event); 19 | bool isRunning() { return !quit_; }; 20 | 21 | private: 22 | // Helper to post small update messages to JS. 23 | void PostUpdateMessage(const char* message_name, double value); 24 | bool quit_; 25 | 26 | }; 27 | 28 | SimpleTemplate::SimpleTemplate() { 29 | quit_ = false; 30 | PSEventSetFilter(PSE_ALL); 31 | } 32 | 33 | // Handle input events from the user and messages from JS. 34 | void SimpleTemplate::HandleEvent(PSEvent* ps_event) { 35 | if (ps_event->type == PSE_INSTANCE_HANDLEMESSAGE) { 36 | // Convert Pepper Simple message to PPAPI C++ var 37 | pp::Var var(ps_event->as_var); 38 | if (var.is_dictionary()) { 39 | pp::VarDictionary dictionary(var); 40 | std::string message = dictionary.Get("message").AsString(); 41 | if (message == "hello") { 42 | printf("Hello world!\n"); 43 | } 44 | else if (message == "quit") { 45 | printf("Exiting\n"); 46 | quit_ = true; 47 | } 48 | } 49 | } 50 | } 51 | 52 | // PostUpdateMessage() helper function for sendimg small messages to JS. 53 | void SimpleTemplate::PostUpdateMessage(const char* message_name, double value) { 54 | pp::VarDictionary message; 55 | message.Set("message", message_name); 56 | message.Set("value", value); 57 | PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), message.pp_var()); 58 | } 59 | 60 | // Starting point for the module. We do not use main since it would 61 | // collide with main in libppapi_cpp. 62 | int app_main(int argc, char* argv[]) { 63 | SimpleTemplate app; 64 | 65 | while (app.isRunning()) { 66 | PSEvent* ps_event; 67 | // Consume all available events. 68 | while ((ps_event = PSEventTryAcquire()) != NULL) { 69 | app.HandleEvent(ps_event); 70 | PSEventRelease(ps_event); 71 | } 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | // Register the function to call once the Instance Object is initialized. 78 | // see: pappi_simple/ps_main.h 79 | PPAPI_SIMPLE_REGISTER_MAIN(app_main); 80 | -------------------------------------------------------------------------------- /Simple/simple_template.nmf: -------------------------------------------------------------------------------- 1 | { "program" : 2 | { "portable" : 3 | { "pnacl-translate" : 4 | { "url" : "simple_template.pexe" 5 | } 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /setup.txt: -------------------------------------------------------------------------------- 1 | # Title: 'Install steps for OpenCV NaCl development on Ubuntu 14.04' 2 | # Date: 20151104 3 | # Author: Matt McDonnell (matt@matt-mcdonnell.com) 4 | # Description: Steps for setting up a development environment for OpenCV 5 | # using Google Native Client (NaCl) on a bare Ubuntu 14.04 instance. 6 | # Tested on Amazon EC2 using a t2.micro instance running Ubuntu Server 7 | # 14.04 LTS. 8 | # 9 | 10 | # Install packages needed for NaCl SDK and naclports 11 | # Note that the NaCl SDK uses 32 bit versions of some libraries so these 12 | # need to be installed as well as the 64 bit versions. If a particular 13 | # naclport fails to build check for missing 32 bit library first. 14 | sudo apt-get update 15 | sudo apt-get install unzip 16 | sudo apt-get install libc6-i386 17 | sudo apt-get install git 18 | sudo apt-get install build-essential 19 | sudo apt-get install lib32stdc++6 20 | sudo apt-get install cmake 21 | sudo apt-get install curl 22 | 23 | # Install python 24 | # My preference is to use the Anaconda distribution 25 | # but apt-get will also work. 26 | 27 | # Create directory structure for external code files (NaCl SDK, etc) 28 | # This directory structure is a personal preference so feel free to modify 29 | # (and change the paths in the rest of this script) 30 | mkdir Work 31 | mkdir Work/ExternCode 32 | cd Work/ExternCode/ 33 | 34 | # Install NaCl SDK 35 | curl -O https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip 36 | unzip nacl_sdk.zip 37 | cd nacl_sdk/ 38 | ./naclsdk list 39 | ./naclsdk update 40 | 41 | # Install depo-tools needed to install naclports 42 | cd ~/Work/ExternCode 43 | git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git 44 | 45 | # Add depot_tools to path and set NACL_SDK_ROOT 46 | vim ~/.bashrc 47 | # Add lines below (without #) to .bashrc, modifying for location and SDK version if necessary 48 | # export PATH="/home/ubuntu/Work/ExternCode/depot_tools":"$PATH" 49 | # export NACL_SDK_ROOT="/home/ubuntu/Work/ExternCode/nacl_sdk/pepper_46/" 50 | exit # Logout and login again to pick up new environment settings 51 | 52 | # Install NaCl ports 53 | cd Work/ExternCode/ 54 | mkdir naclports 55 | cd naclports/ 56 | gclient config --name=src https://chromium.googlesource.com/webports 57 | gclient clean 58 | gclient sync 59 | cd src/ 60 | # Set up git config with your name and email 61 | git config --global user.email "user@example.com" 62 | git config --global user.name "User Name" 63 | # Make opencv and dependencies (takes about 20 minutes) 64 | NACL_ARCH=pnacl make opencv 65 | 66 | # (optional) Clone my NaCl demos 67 | cd 68 | cd Work/ 69 | mkdir Projects 70 | cd Projects/ 71 | git clone https://github.com/mattmcd/NaCl.git 72 | cd NaCl/ImageProc/ 73 | make 74 | make serve # Expose port 8000 and try it out 75 | --------------------------------------------------------------------------------