
@ -1,592 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- Generated with glade 3.37.0 --> |
||||
<interface> |
||||
<requires lib="gtk+" version="3.20"/> |
||||
<object class="GtkAdjustment" id="control_adj"> |
||||
<property name="upper">100</property> |
||||
<property name="step-increment">1</property> |
||||
<property name="page-increment">10</property> |
||||
</object> |
||||
<object class="GtkWindow" id="window"> |
||||
<property name="can-focus">False</property> |
||||
<property name="title" translatable="yes">Camera</property> |
||||
<property name="default-width">360</property> |
||||
<property name="default-height">640</property> |
||||
<child> |
||||
<object class="GtkStack" id="main_stack"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<child> |
||||
<object class="GtkBox" id="page_main"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="orientation">vertical</property> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="orientation">vertical</property> |
||||
<child> |
||||
<object class="GtkGLArea" id="preview"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<style> |
||||
<class name="black"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox" id="control_box"> |
||||
<property name="can-focus">False</property> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="margin-start">10</property> |
||||
<property name="margin-end">10</property> |
||||
<property name="margin-top">10</property> |
||||
<property name="margin-bottom">10</property> |
||||
<child> |
||||
<object class="GtkLabel" id="control_name"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="margin-end">10</property> |
||||
<property name="label" translatable="yes">ISO</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkScale" id="control_slider"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="adjustment">control_adj</property> |
||||
<property name="round-digits">1</property> |
||||
<property name="draw-value">False</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkToggleButton" id="control_auto"> |
||||
<property name="label" translatable="yes">Auto</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<property name="margin-start">10</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="pack-type">end</property> |
||||
<property name="position">2</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<style> |
||||
<class name="controlbox"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox" id="controls_box"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<child type="center"> |
||||
<object class="GtkButton" id="shutter"> |
||||
<property name="width-request">48</property> |
||||
<property name="height-request">48</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<property name="always-show-image">True</property> |
||||
<child> |
||||
<object class="GtkImage"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="resource">/org/postmarketos/Megapixels/shutter-button.svg</property> |
||||
</object> |
||||
</child> |
||||
<style> |
||||
<class name="circular"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">2</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="margin-top">8</property> |
||||
<property name="margin-bottom">8</property> |
||||
<property name="spacing">10</property> |
||||
<child> |
||||
<object class="GtkButton" id="settings"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<child> |
||||
<object class="GtkImage"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="resource">/org/postmarketos/Megapixels/settings-symbolic.svg</property> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkButton" id="switch_camera"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<child> |
||||
<object class="GtkImage"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="resource">/org/postmarketos/Megapixels/switch-camera.svg</property> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="padding">10</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="margin-top">8</property> |
||||
<property name="margin-bottom">8</property> |
||||
<property name="spacing">10</property> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
<child> |
||||
<object class="GtkButton" id="open_directory"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<child> |
||||
<object class="GtkImage"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="resource">/org/postmarketos/Megapixels/folder-symbolic.svg</property> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="pack-type">end</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkButton" id="open_last"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<child> |
||||
<object class="GtkStack" id="open_last_stack"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<child> |
||||
<object class="GtkImage" id="thumb_last"> |
||||
<property name="width-request">24</property> |
||||
<property name="height-request">24</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkSpinner" id="process_spinner"> |
||||
<property name="width-request">24</property> |
||||
<property name="height-request">24</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="pack-type">end</property> |
||||
<property name="position">2</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="padding">10</property> |
||||
<property name="pack-type">end</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="padding">10</property> |
||||
<property name="pack-type">end</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox" id="error_box"> |
||||
<property name="can-focus">False</property> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="margin-start">10</property> |
||||
<property name="margin-end">10</property> |
||||
<property name="margin-top">10</property> |
||||
<property name="margin-bottom">10</property> |
||||
<property name="spacing">10</property> |
||||
<child> |
||||
<object class="GtkLabel" id="error_message"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="halign">start</property> |
||||
<property name="label" translatable="yes">No error</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkButton" id="error_close"> |
||||
<property name="label">gtk-close</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<property name="use-stock">True</property> |
||||
<property name="always-show-image">True</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">True</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<style> |
||||
<class name="errorbox"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">2</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="name">main</property> |
||||
<property name="title" translatable="yes">page0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkScrolledWindow" id="page_settings"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="shadow-type">in</property> |
||||
<child> |
||||
<object class="GtkViewport"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="shadow-type">none</property> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="margin-start">10</property> |
||||
<property name="margin-end">10</property> |
||||
<property name="margin-top">10</property> |
||||
<property name="margin-bottom">10</property> |
||||
<property name="orientation">vertical</property> |
||||
<property name="spacing">10</property> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<child> |
||||
<object class="GtkButton" id="settings_back"> |
||||
<property name="label" translatable="yes">Back</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">True</property> |
||||
<property name="margin-start">10</property> |
||||
<property name="margin-end">10</property> |
||||
<style> |
||||
<class name="suggested-action"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkLabel"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="label" translatable="yes">Settings aren't functional yet</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="orientation">vertical</property> |
||||
<property name="spacing">4</property> |
||||
<child> |
||||
<object class="GtkLabel"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="halign">start</property> |
||||
<property name="label" translatable="yes">Photos</property> |
||||
<style> |
||||
<class name="heading"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkFrame"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="label-xalign">0</property> |
||||
<property name="shadow-type">in</property> |
||||
<child> |
||||
<object class="GtkAlignment"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="left-padding">12</property> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="orientation">vertical</property> |
||||
<property name="spacing">6</property> |
||||
<child> |
||||
<object class="GtkLabel"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="halign">start</property> |
||||
<property name="label" translatable="yes">Resolution</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkComboBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
<child> |
||||
<object class="GtkLabel"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="halign">start</property> |
||||
<property name="label" translatable="yes">Storage mode</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">4</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">False</property> |
||||
<property name="orientation">vertical</property> |
||||
<child> |
||||
<object class="GtkRadioButton" id="store_vng"> |
||||
<property name="label" translatable="yes">Debayer with VNG (slowest)</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">False</property> |
||||
<property name="active">True</property> |
||||
<property name="draw-indicator">True</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">0</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkRadioButton" id="store_simple"> |
||||
<property name="label" translatable="yes">Debayer with linear interpolation</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">False</property> |
||||
<property name="draw-indicator">True</property> |
||||
<property name="group">store_vng</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<object class="GtkRadioButton" id="store_raw"> |
||||
<property name="label" translatable="yes">Raw</property> |
||||
<property name="visible">True</property> |
||||
<property name="can-focus">True</property> |
||||
<property name="receives-default">False</property> |
||||
<property name="draw-indicator">True</property> |
||||
<property name="group">store_vng</property> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">2</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">5</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
<child type="label_item"> |
||||
<placeholder/> |
||||
</child> |
||||
<style> |
||||
<class name="view"/> |
||||
</style> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="expand">False</property> |
||||
<property name="fill">True</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
<child> |
||||
<placeholder/> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
<packing> |
||||
<property name="name">settings</property> |
||||
<property name="title" translatable="yes">page1</property> |
||||
<property name="position">1</property> |
||||
</packing> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</interface> |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,15 @@
|
||||
resources = gnome.compile_resources('megapixels-resources', |
||||
'org.postmarketos.Megapixels.gresource.xml') |
||||
|
||||
install_data(['org.postmarketos.Megapixels.desktop'], |
||||
install_dir: get_option('datadir') / 'applications') |
||||
|
||||
install_data(['org.postmarketos.Megapixels.metainfo.xml'], |
||||
install_dir: get_option('datadir') / 'metainfo') |
||||
|
||||
install_data('org.postmarketos.Megapixels.svg', |
||||
install_dir: join_paths(get_option('datadir'), 'icons/hicolor/scalable/apps')) |
||||
|
||||
install_data(['postprocess.sh'], |
||||
install_dir: get_option('datadir') / 'megapixels/', |
||||
install_mode: 'rwxr-xr-x') |
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<gresources> |
||||
<gresource prefix="/org/postmarketos/Megapixels"> |
||||
<file preprocess="xml-stripblanks">camera.ui</file> |
||||
<file>camera.css</file> |
||||
<file preprocess="xml-stripblanks">switch-camera.svg</file> |
||||
<file preprocess="xml-stripblanks">shutter-button.svg</file> |
||||
<file preprocess="xml-stripblanks">folder-symbolic.svg</file> |
||||
<file preprocess="xml-stripblanks">settings-symbolic.svg</file> |
||||
<file>blit.vert</file> |
||||
<file>blit.frag</file> |
||||
<file>debayer.vert</file> |
||||
<file>debayer.frag</file> |
||||
</gresource> |
||||
</gresources> |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@ -1,207 +0,0 @@
|
||||
#include "camera.h" |
||||
#include "gl_quickpreview.h" |
||||
#include "gl_utils.h" |
||||
#include <stdlib.h> |
||||
|
||||
|
||||
#define VERTEX_ATTRIBUTE 0 |
||||
#define TEX_COORD_ATTRIBUTE 1 |
||||
|
||||
struct _GLQuickPreview { |
||||
GLuint frame_buffer; |
||||
GLuint program; |
||||
GLuint uniform_transform; |
||||
GLuint uniform_pixel_size; |
||||
GLuint uniform_half_image_size; |
||||
GLuint uniform_texture; |
||||
GLuint uniform_pixel_layout; |
||||
GLuint uniform_srgb_map; |
||||
GLuint uniform_color_matrix; |
||||
|
||||
GLuint pixel_layout_texture_id; |
||||
uint32_t pixel_layout_texture_width; |
||||
uint32_t pixel_layout_texture_height; |
||||
MPPixelFormat pixel_layout_texture_format; |
||||
}; |
||||
|
||||
GLQuickPreview *gl_quick_preview_new() |
||||
{ |
||||
GLuint frame_buffer; |
||||
glGenFramebuffers(1, &frame_buffer); |
||||
check_gl(); |
||||
|
||||
GLuint shaders[] = { |
||||
gl_load_shader("data/debayer.vert", GL_VERTEX_SHADER), |
||||
gl_load_shader("data/debayer.frag", GL_FRAGMENT_SHADER), |
||||
}; |
||||
|
||||
GLuint program = gl_link_program(shaders, 2); |
||||
glBindAttribLocation(program, VERTEX_ATTRIBUTE, "vert"); |
||||
glBindAttribLocation(program, TEX_COORD_ATTRIBUTE, "tex_coord"); |
||||
check_gl(); |
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
||||
check_gl(); |
||||
|
||||
GLuint pixel_layout_texture_id; |
||||
glGenTextures(1, &pixel_layout_texture_id); |
||||
check_gl(); |
||||
|
||||
GLQuickPreview *self = malloc(sizeof(GLQuickPreview)); |
||||
self->frame_buffer = frame_buffer; |
||||
self->program = program; |
||||
|
||||
self->uniform_transform = glGetUniformLocation(self->program, "transform"); |
||||
self->uniform_pixel_size = glGetUniformLocation(self->program, "pixel_size"); |
||||
self->uniform_half_image_size = glGetUniformLocation(self->program, "half_image_size"); |
||||
self->uniform_texture = glGetUniformLocation(self->program, "texture"); |
||||
self->uniform_pixel_layout = glGetUniformLocation(self->program, "pixel_layout"); |
||||
self->uniform_color_matrix = glGetUniformLocation(self->program, "color_matrix"); |
||||
self->uniform_srgb_map = glGetUniformLocation(self->program, "srgb_map"); |
||||
check_gl(); |
||||
|
||||
self->pixel_layout_texture_id = pixel_layout_texture_id; |
||||
self->pixel_layout_texture_width = 0; |
||||
self->pixel_layout_texture_height = 0; |
||||
self->pixel_layout_texture_format = MP_PIXEL_FMT_BGGR8; |
||||
|
||||
return self; |
||||
} |
||||
|
||||
void gl_quick_preview_free(GLQuickPreview *self) |
||||
{ |
||||
glDeleteFramebuffers(1, &self->frame_buffer); |
||||
|
||||
free(self); |
||||
} |
||||
|
||||
bool |
||||
ql_quick_preview_supports_format(GLQuickPreview *self, const MPPixelFormat format) |
||||
{ |
||||
return format == MP_PIXEL_FMT_BGGR8; |
||||
} |
||||
|
||||
bool |
||||
gl_quick_preview(GLQuickPreview *self, |
||||
GLuint dst_id, |
||||
const uint32_t dst_width, const uint32_t dst_height, |
||||
GLuint source_id, |
||||
const uint32_t src_width, const uint32_t src_height, |
||||
const MPPixelFormat format, |
||||
const uint32_t rotation, |
||||
const bool mirrored, |
||||
const float *colormatrix, |
||||
const uint8_t blacklevel) |
||||
{ |
||||
// Generate pixel layout image
|
||||
if (src_width != self->pixel_layout_texture_width |
||||
|| src_height != self->pixel_layout_texture_height |
||||
|| format != self->pixel_layout_texture_format) { |
||||
|
||||
glBindTexture(GL_TEXTURE_2D, self->pixel_layout_texture_id); |
||||
|
||||
uint16_t *buffer = malloc(src_width * src_height * sizeof(uint16_t)); |
||||
for (size_t y = 0; y < src_height; ++y) { |
||||
for (size_t x = 0; x < src_width; ++x) { |
||||
buffer[x + y * src_width] = |
||||
(y % 2) == 0 |
||||
? ((x % 2) == 0 ? 0b1111 << 4 : 0b1111 << 8) |
||||
: ((x % 2) == 0 ? 0b1111 << 8 : 0b1111 << 12); |
||||
} |
||||
} |
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src_width, src_height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, buffer); |
||||
check_gl(); |
||||
free(buffer); |
||||
|
||||
self->pixel_layout_texture_width = src_width; |
||||
self->pixel_layout_texture_height = src_height; |
||||
self->pixel_layout_texture_format = format; |
||||
glBindTexture(GL_TEXTURE_2D, 0); |
||||
check_gl(); |
||||
} |
||||
|
||||
assert(ql_quick_preview_supports_format(self, format)); |
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->frame_buffer); |
||||
glBindTexture(GL_TEXTURE_2D, dst_id); |
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_id, 0); |
||||
check_gl(); |
||||
|
||||
glViewport(0, 0, dst_width, dst_height); |
||||
check_gl(); |
||||
|
||||
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); |
||||
|
||||
glUseProgram(self->program); |
||||
check_gl(); |
||||
|
||||
GLfloat rotation_list[4] = { 0, -1, 0, 1 }; |
||||
int rotation_index = 4 - rotation / 90; |
||||
|
||||
GLfloat sin_rot = rotation_list[rotation_index]; |
||||
GLfloat cos_rot = rotation_list[(rotation_index + 1) % 4]; |
||||
GLfloat scale_x = mirrored ? 1 : -1; |
||||
GLfloat matrix[9] = { |
||||
cos_rot * scale_x, sin_rot, 0, |
||||
-sin_rot * scale_x, cos_rot, 0, |
||||
0, 0, 1, |
||||
}; |
||||
glUniformMatrix3fv(self->uniform_transform, 1, GL_FALSE, matrix); |
||||
check_gl(); |
||||
|
||||
glUniform2f(self->uniform_half_image_size, src_width / 2, src_height / 2); |
||||
check_gl(); |
||||
|
||||
GLfloat pixel_size_x = 1.0f / src_width; |
||||
GLfloat pixel_size_y = 1.0f / src_height; |
||||
glUniform2f(self->uniform_pixel_size, pixel_size_x, pixel_size_y); |
||||
check_gl(); |
||||
|
||||
glActiveTexture(GL_TEXTURE0); |
||||
glBindTexture(GL_TEXTURE_2D, source_id); |
||||
glUniform1i(self->uniform_texture, 0); |
||||
check_gl(); |
||||
|
||||
glActiveTexture(GL_TEXTURE1); |
||||
glBindTexture(GL_TEXTURE_2D, self->pixel_layout_texture_id); |
||||
glUniform1i(self->uniform_pixel_layout, 1); |
||||
check_gl(); |
||||
|
||||
if (colormatrix) |
||||
{ |
||||
GLfloat transposed[9]; |
||||
for (int i = 0; i < 3; ++i) |
||||
for (int j = 0; j < 3; ++j) |
||||
transposed[i + j * 3] = colormatrix[j + i * 3]; |
||||
|
||||
glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, transposed); |
||||
} |
||||
else |
||||
{ |
||||
static const GLfloat identity[9] = { |
||||
1, 0, 0, |
||||
0, 1, 0, |
||||
0, 0, 1, |
||||
}; |
||||
glUniformMatrix3fv(self->uniform_color_matrix, 1, GL_FALSE, identity); |
||||
} |
||||
|
||||
glVertexAttribPointer(VERTEX_ATTRIBUTE, 2, GL_FLOAT, 0, 0, gl_quad_vertices); |
||||
glEnableVertexAttribArray(VERTEX_ATTRIBUTE); |
||||
glVertexAttribPointer(TEX_COORD_ATTRIBUTE, 2, GL_FLOAT, 0, 0, gl_quad_texcoords); |
||||
glEnableVertexAttribArray(TEX_COORD_ATTRIBUTE); |
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
||||
check_gl(); |
||||
|
||||
// TODO: Render
|
||||
// glClearColor(0, 0, 1, 0);
|
||||
// glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// glBindTexture(GL_TEXTURE_2D, 0);
|
||||
// glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return true; |
||||
} |
@ -1,21 +0,0 @@
|
||||
#include "quickpreview.h" |
||||
#include <assert.h> |
||||
#include <stdio.h> |
||||
#include <GLES2/gl2.h> |
||||
|
||||
typedef struct _GLQuickPreview GLQuickPreview; |
||||
|
||||
GLQuickPreview* gl_quick_preview_new(); |
||||
void gl_quick_preview_free(GLQuickPreview *self); |
||||
|
||||
bool ql_quick_preview_supports_format(GLQuickPreview *self, const MPPixelFormat format); |
||||
bool gl_quick_preview(GLQuickPreview *self, |
||||
GLuint dst_id, |
||||
const uint32_t dst_width, const uint32_t dst_height, |
||||
GLuint source_id, |
||||
const uint32_t src_width, const uint32_t src_height, |
||||
const MPPixelFormat format, |
||||
const uint32_t rotation, |
||||
const bool mirrored, |
||||
const float *colormatrix, |
||||
const uint8_t blacklevel); |
@ -1,128 +0,0 @@
|
||||
#include "gl_utils.h" |
||||
|
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <assert.h> |
||||
|
||||
void __check_gl(const char *file, int line) |
||||
{ |
||||
GLenum error = glGetError(); |
||||
|
||||
const char *name; |
||||
switch (error) { |
||||
case GL_NO_ERROR: |
||||
return; // no error
|
||||
case GL_INVALID_ENUM: |
||||
name = "GL_INVALID_ENUM"; |
||||
break; |
||||
case GL_INVALID_VALUE: |
||||
name = "GL_INVALID_VALUE"; |
||||
break; |
||||
case GL_INVALID_OPERATION: |
||||
name = "GL_INVALID_OPERATION"; |
||||
break; |
||||
case GL_INVALID_FRAMEBUFFER_OPERATION: |
||||
name = "GL_INVALID_FRAMEBUFFER_OPERATION"; |
||||
break; |
||||
case GL_OUT_OF_MEMORY: |
||||
name = "GL_OUT_OF_MEMORY"; |
||||
break; |
||||
default: |
||||
name = "UNKNOWN ERROR!"; |
||||
break; |
||||
} |
||||
|
||||
printf("GL error at %s:%d - %s\n", file, line, name); |
||||
} |
||||
|
||||
const GLfloat gl_quad_vertices[] = { |
||||
-1, -1, |
||||
1, -1, |
||||
-1, 1, |
||||
1, 1, |
||||
}; |
||||
|
||||
const GLfloat gl_quad_texcoords[] = { |
||||
0, 0, |
||||
1, 0, |
||||
0, 1, |
||||
1, 1, |
||||
}; |
||||
|
||||
GLuint |
||||
gl_load_shader(const char *path, GLenum type) |
||||
{ |
||||
check_gl(); |
||||
|
||||
FILE *f = fopen(path, "r"); |
||||
|
||||
fseek(f, 0, SEEK_END); |
||||
GLint size = ftell(f); |
||||
char *source = malloc(sizeof(char) * size); |
||||
|
||||
fseek(f, 0, SEEK_SET); |
||||
if (fread(source, size, 1, f) == 0) { |
||||
printf("Failed to read shader file\n"); |
||||
return 0; |
||||
} |
||||
|
||||
GLuint shader = glCreateShader(type); |
||||
assert(shader != 0); |
||||
glShaderSource(shader, 1, (const GLchar * const*)&source, &size); |
||||
glCompileShader(shader); |
||||
check_gl(); |
||||
|
||||
// Check compile status
|
||||
GLint success; |
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success); |
||||
if (success == GL_FALSE) { |
||||
printf("Shader compilation failed for %s\n", path); |
||||
} |
||||
|
||||
GLint log_length; |
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); |
||||
if (log_length > 0) { |
||||
char *log = malloc(sizeof(char) * log_length); |
||||
glGetShaderInfoLog(shader, log_length - 1, &log_length, log); |
||||
|
||||
printf("Shader %s log: %s\n", path, log); |
||||
free(log); |
||||
} |
||||
|
||||
free(source); |
||||
|
||||
return shader; |
||||
} |
||||
|
||||
GLuint |
||||
gl_link_program(GLuint *shaders, size_t num_shaders) |
||||
{ |
||||
GLuint program = glCreateProgram(); |
||||
|
||||
for (size_t i = 0; i < num_shaders; ++i) { |
||||
glAttachShader(program, shaders[i]); |
||||
} |
||||
|
||||
glLinkProgram(program); |
||||
check_gl(); |
||||
|
||||
GLint success; |
||||
glGetProgramiv(program, GL_LINK_STATUS, &success); |
||||
if (success == GL_FALSE) { |
||||
printf("Program linking failed\n"); |
||||
} |
||||
|
||||
GLint log_length; |
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); |
||||
if (log_length > 0) { |
||||
char *log = malloc(sizeof(char) * log_length); |
||||
glGetProgramInfoLog(program, log_length - 1, &log_length, log); |
||||
|
||||
printf("Program log: %s\n", log); |
||||
free(log); |
||||
} |
||||
check_gl(); |
||||
|
||||
return program; |
||||
} |
@ -1,13 +0,0 @@
|
||||
#pragma once |
||||
|
||||
#include <GLES2/gl2.h> |
||||
#include <stddef.h> |
||||
|
||||
#define check_gl() __check_gl(__FILE__, __LINE__) |
||||
void __check_gl(const char *file, int line); |
||||
|
||||
extern const GLfloat gl_quad_vertices[8]; |
||||
extern const GLfloat gl_quad_texcoords[8]; |
||||
|
||||
GLuint gl_load_shader(const char *path, GLenum type); |
||||
GLuint gl_link_program(GLuint *shaders, size_t num_shaders); |
@ -1,78 +1,76 @@
|
||||
project('megapixels', 'c') |
||||
|
||||
gnome = import('gnome') |
||||
gtkdep = dependency('gtk4') |
||||
tiff = dependency('libtiff-4') |
||||
zbar = dependency('zbar') |
||||
threads = dependency('threads') |
||||
gl = dependency('gl') |
||||
egl = dependency('egl') |
||||
# gl = dependency('gl') |
||||
epoxy = dependency('epoxy') |
||||
|
||||
cc = meson.get_compiler('c') |
||||
libm = cc.find_library('m', required: false) |
||||
|
||||
resources = gnome.compile_resources('megapixels-resources', 'org.postmarketos.Megapixels.gresource.xml') |
||||
subdir('data') |
||||
|
||||
conf = configuration_data() |
||||
conf.set_quoted('DATADIR', join_paths(get_option('prefix'), get_option('datadir'))) |
||||
conf.set_quoted('SYSCONFDIR', get_option('sysconfdir')) |
||||
configure_file( |
||||
output: 'config.h', |
||||
configuration: conf ) |
||||
configuration: conf) |
||||
|
||||
# Define DEBUG for debug builds only (debugoptimized is not included on this one) |
||||
if get_option('buildtype') == 'debug' |
||||
add_global_arguments('-DDEBUG', language: 'c') |
||||
endif |
||||
|
||||
# Workaround for libtiff having ABI changes but not changing the internal version number |
||||
# Workaround for libtiff having ABI changes but not changing the internal |
||||
# version number |
||||
if get_option('tiffcfapattern') |
||||
add_global_arguments('-DLIBTIFF_CFA_PATTERN', language: 'c') |
||||
endif |
||||
|
||||
executable('megapixels', |
||||
'main.c', |
||||
'ini.c', |
||||
'quickpreview.c', |
||||
'gl_quickpreview.c', |
||||
'gl_utils.c', |
||||
'camera.c', |
||||
'device.c', |
||||
'pipeline.c', |
||||
'camera_config.c', |
||||
'io_pipeline.c', |
||||
'process_pipeline.c', |
||||
'zbar_pipeline.c', |
||||
'matrix.c', |
||||
resources, |
||||
dependencies : [gtkdep, libm, tiff, zbar, threads, gl, egl], |
||||
install : true, |
||||
link_args : '-Wl,-ldl') |
||||
|
||||
install_data(['data/org.postmarketos.Megapixels.desktop'], |
||||
install_dir : get_option('datadir') / 'applications') |
||||
|
||||
install_data(['data/org.postmarketos.Megapixels.metainfo.xml'], |
||||
install_dir : get_option('datadir') / 'metainfo') |
||||
'src/main.c', |
||||
'src/ini.c', |
||||
'src/gles2_debayer.c', |
||||
'src/gl_util.c', |
||||
'src/camera.c', |
||||
'src/device.c', |
||||
'src/pipeline.c', |
||||
'src/camera_config.c', |
||||
'src/io_pipeline.c', |
||||
'src/process_pipeline.c', |
||||
'src/zbar_pipeline.c', |
||||
'src/matrix.c', |
||||
resources, |
||||
include_directories: 'src/', |
||||
dependencies: [gtkdep, libm, tiff, zbar, threads, epoxy], |
||||
install: true, |
||||
link_args: '-Wl,-ldl') |
||||
|
||||
install_data('data/org.postmarketos.Megapixels.svg', |
||||
install_dir: join_paths(get_option('datadir'), 'icons/hicolor/scalable/apps') |
||||
) |
||||
|
||||
install_data([ |
||||
'config/pine64,pinephone-1.0.ini', |
||||
'config/pine64,pinephone-1.1.ini', |
||||
'config/pine64,pinephone-1.2.ini', |
||||
'config/pine64,pinetab.ini', |
||||
install_data( |
||||
[ |
||||
'config/pine64,pinephone-1.0.ini', |
||||
'config/pine64,pinephone-1.1.ini', |
||||
'config/pine64,pinephone-1.2.ini', |
||||
'config/pine64,pinetab.ini', |
||||
], |
||||
install_dir : get_option('datadir') / 'megapixels/config/') |
||||
|
||||
install_data(['postprocess.sh'], |
||||
install_dir : get_option('datadir') / 'megapixels/', |
||||
install_mode: 'rwxr-xr-x') |
||||
install_dir: get_option('datadir') / 'megapixels/config/') |
||||
|
||||
# Tools |
||||
executable('megapixels-list-devices', 'tools/list_devices.c', 'device.c', dependencies: [gtkdep], install: true) |
||||
executable('megapixels-camera-test', 'tools/camera_test.c', 'camera.c', 'device.c', dependencies: [gtkdep], install: true) |
||||
executable('megapixels-list-devices', |
||||
'tools/list_devices.c', |
||||
'src/device.c', |
||||
include_directories: 'src/', |
||||
dependencies: [gtkdep], |
||||
install: true) |
||||
|
||||
test_quickpreview = executable('test_quickpreview', 'tests/test_quickpreview.c', 'quickpreview.c', 'camera.c', dependencies: [gtkdep]) |
||||
test('quickpreview', test_quickpreview) |
||||
executable('megapixels-camera-test', |
||||
'tools/camera_test.c', |
||||
'src/camera.c', |
||||
'src/device.c', |
||||
include_directories: 'src/', |
||||
dependencies: [gtkdep], |
||||
install: true) |
||||
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<gresources> |
||||
<gresource prefix="/org/postmarketos/Megapixels"> |
||||
<file>camera.glade</file> |
||||
<file>camera.css</file> |
||||
<file>switch-camera.svg</file> |
||||
<file>shutter-button.svg</file> |
||||
<file>folder-symbolic.svg</file> |
||||
<file>settings-symbolic.svg</file> |
||||
</gresource> |
||||
</gresources> |
@ -1,351 +0,0 @@
|
||||
/*
|
||||
* Fast but bad debayer method that scales and rotates by skipping source |
||||
* pixels and doesn't interpolate any values at all |
||||
*/ |
||||
|
||||
#include "quickpreview.h" |
||||
#include <assert.h> |
||||
#include <stdio.h> |
||||
|
||||
/* Linear -> sRGB lookup table */ |
||||
static const uint8_t srgb[] = { |
||||
0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, |
||||
73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, |
||||
102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, |
||||
120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, |
||||
135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, |
||||
148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, |
||||
160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, |
||||
171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, |
||||
181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, |
||||
190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, |
||||
199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, |
||||
207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, |
||||
215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, |
||||
222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, |
||||
230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, |
||||
237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, |
||||
243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, |
||||
250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255 |
||||
}; |
||||
|
||||
static inline uint32_t |
||||
pack_rgb(uint8_t r, uint8_t g, uint8_t b) |
||||
{ |
||||
return (r << 16) | (g << 8) | b; |
||||
} |
||||
|
||||
static inline uint32_t |
||||
convert_yuv_to_srgb(uint8_t y, uint8_t u, uint8_t v) |
||||
{ |
||||
uint32_t r = 1.164f * y + 1.596f * (v - 128); |
||||
uint32_t g = 1.164f * y - 0.813f * (v - 128) - 0.391f * (u - 128); |
||||
uint32_t b = 1.164f * y + 2.018f * (u - 128); |
||||
return pack_rgb(r, g, b); |
||||
} |
||||
|
||||
static inline uint32_t |
||||
apply_colormatrix(uint32_t color, const float *colormatrix) |
||||
{ |
||||
if (!colormatrix) { |
||||
return color; |
||||
} |
||||
|
||||
uint32_t r = (color >> 16) * colormatrix[0] + |
||||
((color >> 8) & 0xFF) * colormatrix[1] + |
||||
(color & 0xFF) * colormatrix[2]; |
||||
uint32_t g = (color >> 16) * colormatrix[3] + |
||||
((color >> 8) & 0xFF) * colormatrix[4] + |
||||
(color & 0xFF) * colormatrix[5]; |
||||
uint32_t b = (color >> 16) * colormatrix[6] + |
||||
((color >> 8) & 0xFF) * colormatrix[7] + |
||||
(color & 0xFF) * colormatrix[8]; |
||||
|
||||
// Clip colors
|
||||
if (r > 0xFF) |
||||
r = 0xFF; |
||||
if (g > 0xFF) |
||||
g = 0xFF; |
||||
if (b > 0xFF) |
||||
b = 0xFF; |
||||
return pack_rgb(r, g, b); |
||||
} |
||||
|
||||
static inline uint32_t |
||||
coord_map(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int rotation, |
||||
bool mirrored) |
||||
{ |
||||
uint32_t x_r, y_r; |
||||
if (rotation == 0) { |
||||
x_r = x; |
||||
y_r = y; |
||||
} else if (rotation == 90) { |
||||
x_r = y; |
||||
y_r = height - x - 1; |
||||
} else if (rotation == 270) { |
||||
x_r = width - y - 1; |
||||
y_r = x; |
||||
} else { |
||||
x_r = width - x - 1; |
||||
y_r = height - y - 1; |
||||
} |
||||
|
||||
if (mirrored) { |
||||
x_r = width - x_r - 1; |
||||
} |
||||
|
||||
uint32_t index = y_r * width + x_r; |
||||
#ifdef DEBUG |
||||
assert(index < width * height); |
||||
#endif |
||||
return index; |
||||
} |
||||
|
||||
static void |
||||
quick_preview_rggb8(uint32_t *dst, const uint32_t dst_width, |
||||
const uint32_t dst_height, const uint8_t *src, |
||||
const uint32_t src_width, const uint32_t src_height, |
||||
const MPPixelFormat format, const uint32_t rotation, |
||||
const bool mirrored, const float *colormatrix, |
||||
const uint8_t blacklevel, const uint32_t skip) |
||||
{ |
||||
uint32_t src_y = 0, dst_y = 0; |
||||
while (src_y < src_height) { |
||||
uint32_t src_x = 0, dst_x = 0; |
||||
while (src_x < src_width) { |
||||
uint32_t src_i = src_y * src_width + src_x; |
||||
|
||||
uint8_t b0 = srgb[src[src_i] - blacklevel]; |
||||
uint8_t b1 = srgb[src[src_i + 1] - blacklevel]; |
||||
uint8_t b2 = srgb[src[src_i + src_width + 1] - blacklevel]; |
||||
|
||||