-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
3,695 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
cmake_minimum_required(VERSION 3.10) | ||
|
||
# Project name and version | ||
project(CameraProject VERSION 1.0 LANGUAGES CXX) | ||
|
||
# Set C++ standard | ||
set(CMAKE_CXX_STANDARD 17) | ||
set(CMAKE_CXX_STANDARD_REQUIRED True) | ||
|
||
# Define include directories | ||
set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include) | ||
|
||
# Define source files for the Camera library | ||
if (WIN32) | ||
set(LIBRARY_SOURCES | ||
src/CameraWindows.cpp | ||
src/CameraPreviewWindows.cpp | ||
) | ||
elseif (UNIX AND NOT APPLE) | ||
set(LIBRARY_SOURCES | ||
src/CameraLinux.cpp | ||
src/CameraPreviewLinux.cpp | ||
) | ||
elseif (APPLE) | ||
set(LIBRARY_SOURCES | ||
src/CameraMacOS.mm | ||
src/CameraPreviewMacOS.mm | ||
) | ||
endif() | ||
|
||
# Define source files for the executable | ||
set(EXECUTABLE_SOURCES | ||
src/main.cpp | ||
) | ||
|
||
# Add the Camera shared library | ||
add_library(Camera SHARED ${LIBRARY_SOURCES}) | ||
|
||
# Set include directories for the Camera library | ||
target_include_directories(Camera PUBLIC ${INCLUDE_DIR}) | ||
|
||
# Define the CAMERA_EXPORTS macro for the shared library | ||
target_compile_definitions(Camera PRIVATE CAMERA_EXPORTS) | ||
|
||
# Platform-specific dependencies for the Camera library | ||
if (UNIX AND NOT APPLE) | ||
find_package(X11 REQUIRED) | ||
if (X11_FOUND) | ||
target_include_directories(Camera PUBLIC ${X11_INCLUDE_DIR}) | ||
target_link_libraries(Camera PRIVATE ${X11_LIBRARIES} pthread) | ||
endif() | ||
elseif (APPLE) | ||
find_library(COCOA_LIBRARY Cocoa) | ||
find_library(AVFOUNDATION_LIBRARY AVFoundation) | ||
target_link_libraries(Camera PRIVATE ${AVFOUNDATION_LIBRARY}) | ||
elseif (WIN32) | ||
target_link_libraries(Camera PRIVATE ole32 uuid mfplat mf mfreadwrite mfuuid) | ||
endif() | ||
|
||
# Add the camera_capture executable | ||
add_executable(camera_capture ${EXECUTABLE_SOURCES}) | ||
|
||
# Link the Camera library to the executable | ||
target_link_libraries(camera_capture PRIVATE Camera) | ||
|
||
# Include the shared library's headers in the executable | ||
target_include_directories(camera_capture PRIVATE ${INCLUDE_DIR}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# LiteCam | ||
|
||
LiteCam is a lightweight, cross-platform library for capturing RGB frames from cameras and displaying them. Designed with simplicity and ease of integration in mind, LiteCam supports Windows and Linux platforms. | ||
|
||
## Features | ||
|
||
- Capture RGB frames from video devices. | ||
- Display live frames in a window. | ||
- Draw contours and text directly on the displayed frames. | ||
- Simple API for quick integration. | ||
|
||
## Supported Platforms | ||
|
||
- **Windows**: Uses Media Foundation for video capture. | ||
- **Linux**: Uses Video4Linux (V4L2) and X11 for video capture and rendering. | ||
|
||
## Requirements | ||
|
||
- CMake | ||
|
||
### Windows | ||
- Visual Studio 2019 or later | ||
- Media Foundation (included with Windows) | ||
|
||
### Linux | ||
- GCC or Clang | ||
- Development libraries for: | ||
- Video4Linux2 (libv4l2) | ||
- X11 (libX11) | ||
|
||
## Installation | ||
|
||
1. Clone the repository: | ||
```bash | ||
git clone https://github.com/yushulx/cmake-cpp-barcode-qrcode-mrz.git | ||
cd litecam | ||
``` | ||
|
||
2. Build the library: | ||
|
||
```bash | ||
mkdir build && cd build | ||
cmake .. | ||
cmake --build . | ||
``` | ||
|
||
3. Link the library to your project. | ||
|
||
## Usage | ||
|
||
### Basic Example | ||
|
||
```cpp | ||
#include "Camera.h" | ||
#include "CameraPreview.h" | ||
int main() | ||
{ | ||
Camera camera; | ||
if (!camera.Open(0)) { | ||
std::cerr << "Failed to open camera." << std::endl; | ||
return -1; | ||
} | ||
CameraWindow window(640, 480, "LiteCam Preview"); | ||
if (!window.Create()) { | ||
std::cerr << "Failed to create window." << std::endl; | ||
return -1; | ||
} | ||
window.Show(); | ||
while (window.WaitKey('q')) { | ||
FrameData frame = camera.CaptureFrame(); | ||
if (frame.rgbData) { | ||
window.ShowFrame(frame.rgbData, frame.width, frame.height); | ||
camera.ReleaseFrame(frame); | ||
} | ||
} | ||
camera.Release(); | ||
return 0; | ||
} | ||
``` | ||
### API Overview | ||
#### Camera | ||
- **`bool Open(int cameraIndex)`**: Opens the camera with the specified index. | ||
- **`FrameData CaptureFrame()`**: Captures a single RGB frame. | ||
- **`void ReleaseFrame(FrameData &frame)`**: Releases the memory allocated for a frame. | ||
- **`void Release()`**: Closes the camera and releases resources. | ||
- **`void saveFrameAsJPEG(const char *filename, const unsigned char *rgbData, int width, int height)`**: Saves the frame as a JPEG image. | ||
#### CameraWindow | ||
- **`bool Create()`**: Initializes and creates a window. | ||
- **`void Show()`**: Displays the window. | ||
- **`bool WaitKey(char key)`**: Waits for user input; returns `false` if the specified key is pressed or the window is closed. | ||
- **`void ShowFrame(const unsigned char *rgbData, int width, int height)`**: Displays an RGB frame. | ||
- **`void DrawContour(const std::vector<std::pair<int, int>> &points)`**: Draws contours on the frame. | ||
- **`void DrawText(const std::string &text, int x, int y, int fontSize, const Color &color)`**: Draws text on the frame. | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
#ifndef CAMERA_H | ||
#define CAMERA_H | ||
|
||
#include <vector> | ||
#include <string> | ||
#include <iostream> | ||
#include <cstdint> | ||
|
||
// Export macro for shared library | ||
#ifdef _WIN32 | ||
#ifdef CAMERA_EXPORTS | ||
#define CAMERA_API __declspec(dllexport) | ||
#else | ||
#define CAMERA_API __declspec(dllimport) | ||
#endif | ||
#elif defined(__linux__) || defined(__APPLE__) | ||
#define CAMERA_API __attribute__((visibility("default"))) | ||
#else | ||
#define CAMERA_API | ||
#endif | ||
|
||
// Platform-specific includes | ||
#ifdef _WIN32 | ||
#include <windows.h> | ||
#include <mfapi.h> | ||
#include <mfidl.h> | ||
#include <mfobjects.h> | ||
#include <mfreadwrite.h> | ||
#include <wrl/client.h> | ||
#include <dshow.h> | ||
|
||
#pragma comment(lib, "mfplat.lib") | ||
#pragma comment(lib, "mf.lib") | ||
#pragma comment(lib, "mfreadwrite.lib") | ||
#pragma comment(lib, "mfuuid.lib") | ||
|
||
using Microsoft::WRL::ComPtr; | ||
#elif __linux__ | ||
#include <linux/videodev2.h> | ||
#include <fcntl.h> | ||
#include <unistd.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/mman.h> | ||
|
||
struct Buffer | ||
{ | ||
void *start; | ||
size_t length; | ||
}; | ||
|
||
#elif __APPLE__ | ||
#include <AVFoundation/AVFoundation.h> | ||
#endif | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
// Save a frame as a JPEG image using the STB library | ||
// https://github.com/nothings/stb/blob/master/stb_image_write.h | ||
#define STB_IMAGE_WRITE_IMPLEMENTATION | ||
#include "stb_image_write.h" | ||
void saveFrameAsJPEG(const unsigned char *data, int width, int height, const std::string &filename) | ||
{ | ||
// Simple image saving using STB library or another JPEG encoding method | ||
if (stbi_write_jpg(filename.c_str(), width, height, 3, data, 90)) | ||
{ | ||
std::cout << "Saved frame to " << filename << std::endl; | ||
} | ||
else | ||
{ | ||
std::cerr << "Error saving frame as JPEG." << std::endl; | ||
} | ||
} | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
unsigned char clamp(double value, double min, double max) | ||
{ | ||
if (value < min) | ||
return static_cast<unsigned char>(min); | ||
if (value > max) | ||
return static_cast<unsigned char>(max); | ||
return static_cast<unsigned char>(value); | ||
} | ||
|
||
void ConvertYUY2ToRGB(const unsigned char *yuy2Data, unsigned char *rgbData, int width, int height) | ||
{ | ||
int rgbIndex = 0; | ||
for (int i = 0; i < width * height * 2; i += 4) | ||
{ | ||
// Extract YUV values | ||
unsigned char y1 = yuy2Data[i]; | ||
unsigned char u = yuy2Data[i + 1]; | ||
unsigned char y2 = yuy2Data[i + 2]; | ||
unsigned char v = yuy2Data[i + 3]; | ||
|
||
#ifdef _WIN32 | ||
// Convert first pixel (Y1, U, V) to RGB | ||
rgbData[rgbIndex++] = clamp(y1 + 1.772 * (u - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y1 - 0.344136 * (u - 128) - 0.714136 * (v - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y1 + 1.402 * (v - 128), 0.0, 255.0); | ||
|
||
// Convert second pixel (Y2, U, V) to RGB | ||
rgbData[rgbIndex++] = clamp(y2 + 1.772 * (u - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y2 - 0.344136 * (u - 128) - 0.714136 * (v - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y2 + 1.402 * (v - 128), 0.0, 255.0); | ||
#else | ||
// Convert first pixel (Y1, U, V) to RGB | ||
rgbData[rgbIndex++] = clamp(y1 + 1.402 * (v - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y1 - 0.344136 * (u - 128) - 0.714136 * (v - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y1 + 1.772 * (u - 128), 0.0, 255.0); | ||
|
||
// Convert second pixel (Y2, U, V) to RGB | ||
rgbData[rgbIndex++] = clamp(y2 + 1.402 * (v - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y2 - 0.344136 * (u - 128) - 0.714136 * (v - 128), 0.0, 255.0); | ||
rgbData[rgbIndex++] = clamp(y2 + 1.772 * (u - 128), 0.0, 255.0); | ||
#endif | ||
} | ||
} | ||
|
||
// Struct definitions | ||
struct CAMERA_API FrameData | ||
{ | ||
unsigned char *rgbData; // RGB pixel data | ||
int width; // Frame width | ||
int height; // Frame height | ||
size_t size; | ||
}; | ||
|
||
struct CAMERA_API MediaTypeInfo | ||
{ | ||
uint32_t width; | ||
uint32_t height; | ||
#ifdef _WIN32 | ||
wchar_t subtypeName[512]; // Wide characters for Windows | ||
#else | ||
char subtypeName[512]; // Narrow characters for Linux/macOS | ||
#endif | ||
}; | ||
|
||
struct CAMERA_API CaptureDeviceInfo | ||
{ | ||
|
||
#ifdef _WIN32 | ||
wchar_t friendlyName[512]; | ||
#else | ||
char friendlyName[512]; // Narrow characters for Linux/macOS | ||
#endif | ||
}; | ||
|
||
// Exported functions | ||
CAMERA_API std::vector<CaptureDeviceInfo> ListCaptureDevices(); | ||
|
||
// Camera class | ||
class CAMERA_API Camera | ||
{ | ||
public: | ||
#ifdef _WIN32 | ||
Camera(); | ||
~Camera(); | ||
#elif __linux__ | ||
Camera() : fd(-1), frameWidth(640), frameHeight(480), buffers(nullptr), bufferCount(0) {} | ||
~Camera() { Release(); } | ||
#endif | ||
|
||
bool Open(int cameraIndex); | ||
void Release(); | ||
|
||
std::vector<MediaTypeInfo> ListSupportedMediaTypes(); | ||
FrameData CaptureFrame(); | ||
void ReleaseFrame(FrameData &frame); | ||
bool SetResolution(int width, int height); | ||
|
||
uint32_t frameWidth; | ||
uint32_t frameHeight; | ||
|
||
private: | ||
#ifdef _WIN32 | ||
ComPtr<IMFSourceReader> reader; | ||
|
||
bool initialized; | ||
void InitializeMediaFoundation(); | ||
void ShutdownMediaFoundation(); | ||
#endif | ||
|
||
#ifdef __linux__ | ||
int fd; | ||
Buffer *buffers; | ||
unsigned int bufferCount; | ||
|
||
bool InitDevice(); | ||
void UninitDevice(); | ||
bool StartCapture(); | ||
void StopCapture(); | ||
#endif | ||
|
||
#ifdef __APPLE__ | ||
void *captureSession; // AVFoundation session object | ||
#endif | ||
}; | ||
|
||
#endif // CAMERA_H |
Oops, something went wrong.