Improve website

website
Mattia Iavarone 5 years ago
parent 9c984f0c21
commit b6947c6267
  1. 79
      docs/_config.yml
  2. 5
      docs/_includes/footer.html
  3. 11
      docs/_includes/google_analytics.html
  4. 21
      docs/_includes/head.html
  5. 24
      docs/_includes/header.html
  6. 41
      docs/_includes/navigation.html
  7. 117
      docs/_layouts/default.html
  8. 49
      docs/_layouts/landing.html
  9. 37
      docs/_layouts/main.html
  10. 12
      docs/_layouts/page.html
  11. 3
      docs/_posts/2018-12-20-camera-events.md
  12. 1
      docs/_posts/2018-12-20-capture-size.md
  13. 10
      docs/_posts/2018-12-20-capturing-media.md
  14. 28
      docs/_posts/2018-12-20-changelog.md
  15. 6
      docs/_posts/2018-12-20-contributing.md
  16. 11
      docs/_posts/2018-12-20-controls.md
  17. 1
      docs/_posts/2018-12-20-frame-processing.md
  18. 1
      docs/_posts/2018-12-20-gestures.md
  19. 9
      docs/_posts/2018-12-20-getting-started.md
  20. 3
      docs/_posts/2018-12-20-install.md
  21. 1
      docs/_posts/2018-12-20-more-features.md
  22. 9
      docs/_posts/2018-12-20-preview-size.md
  23. 1
      docs/_posts/2018-12-20-previews.md
  24. 3
      docs/_posts/2018-12-20-runtime-permissions.md
  25. 7
      docs/_posts/2018-12-20-v1-migration-guide.md
  26. 4
      docs/_posts/2018-12-21-donate.md
  27. 1
      docs/_posts/2019-02-24-snapshot-size.md
  28. 1
      docs/_posts/2019-07-14-watermarks-and-overlays.md
  29. 9
      docs/_posts/2019-08-06-filters.md
  30. 7
      docs/_posts/2019-09-04-metering.md
  31. 2
      docs/_posts/2019-12-04-home.md
  32. 65
      docs/css/colors.css
  33. 33
      docs/css/fonts.css
  34. 34
      docs/css/fonts_responsive.css
  35. 38
      docs/css/landing.css
  36. 334
      docs/css/main.css
  37. 137
      docs/css/syntax.css
  38. 10
      docs/icons/github.svg
  39. 7
      docs/icons/menu.svg
  40. 2
      docs/index.md
  41. 107
      docs/script/new-page

@ -3,69 +3,38 @@
# Source site: http://bruth.github.io/jekyll-docs-template/
# Ref guide: https://visualstudiomagazine.com/Articles/2015/03/01/GitHub-Pages.aspx?Page=2
# Used by us
title: CameraView
# subtitle is used by ourselves, description is used by seo tag.
subtitle: A well documented, high-level Android interface that makes capturing pictures and videos easy, addressing all of the common issues and needs.
description: A well documented, high-level Android interface that makes capturing pictures and videos easy, addressing all of the common issues and needs.
# Can't remember what this does.
github: [metadata]
# Should be used by some plugins but we're not using any,
author:
name: Mattia Iavarone
email: mat.iavarone@gmail.com
github: natario1
# Add head tags.
plugins:
- jekyll-seo-tag
# if you wish to integrate disqus on pages set your shortname here
color: '#f76c16'
description: A well documented, high-level Android interface that makes capturing pictures and videos easy, addressing all of the common issues and needs. # used by ourselves and by seo tag.
disqus_shortname: 'cameraview'
# if you use google analytics, add your tracking id here
google_analytics_id: 'UA-155077779-1'
# Enable/show navigation. There are there options:
# 0 - always hide
# 1 - always show
# 2 - show only if posts are present
navigation: 2
# URL to source code, used in _includes/footer.html
codeurl: 'https://github.com/natario1/CameraView'
# relative URL for donations, used in footer.html
donateurl: '/extra/donate.html'
# Default categories (in order) to appear in the navigation
# (Missing: DOCS and DONATE info)
google_site_verification: '4x49i17ABIrSvUl52SeL0-t0341aTnWWaC62-FYCRT4'
github: [metadata] # TODO What's this?
github_repo: CameraView
github_version: 2.6.0
donateurl: '/extra/donate' # relative URL for donations, used in footer.html
baseurl: '/CameraView' # Keep as an empty string if served up at the root
sections: [
['about', 'Overview'],
['docs', 'Documentation'],
['extra', 'More']
]
# Keep as an empty string if served up at the root. If served up at a specific
# path (e.g. on GitHub pages) leave off the trailing slash, e.g. /my-project
baseurl: '/CameraView'
# Ensure permalinks have no date nor extension
permalink: /:categories/:title
# Syntax highlighting
highlighter: rouge
# Since these are pages, it doesn't really matter
future: true
# Exclude non-site files
exclude: ['script', 'README.md']
# Jekyll specific stuff
author:
name: Mattia Iavarone # Should appear in <head>.
email: mat.iavarone@gmail.com
github: natario1
website: https://natario.dev
plugins:
- jekyll-seo-tag # Add SEO tags
permalink: /:categories/:title # Ensure permalinks have no date nor extension
exclude: ['script', 'README.md'] # Exclude non-site files
# Use the kramdown Markdown renderer
markdown: kramdown
highlighter: rouge # Syntax highlighting
future: true # What's this?
markdown: kramdown # Use the kramdown Markdown renderer
redcarpet:
extensions: [
'no_intra_emphasis',
@ -77,7 +46,5 @@ redcarpet:
'tables',
'hardwrap'
]
# Use Github Flavored Markdown
kramdown:
input: GFM
input: GFM # Use Github Flavored Markdown

@ -1 +1,4 @@
View on GitHub: <a href="{% if site.codeurl %}{{ site.codeurl }}{% else %}{{ site.baseurl }}{% endif %}">{{ site.title }}</a> or <a href="{{ site.baseurl }}{{ site.donateurl }}">donate</a>
<footer class="text-center py-3 border-top has-divider">
<span>View on <a href="https://github.com/{{ site.author.github }}/{{ site.github_repo }}">GitHub</a> or become <a href="{{ site.baseurl }}{{ site.donateurl }}">a sponsor</a>!</span>
<span class="d-block">Made by <a href="{{ site.author.website }}">{{ site.author.name }}</a></span>
</footer>

@ -1,8 +1,7 @@
<script async src="https://www.googletagmanager.com/gtag/js?id={{ site.google_analytics_id }}"></script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '{{ site.google_analytics_id }}', 'auto');
ga('send', 'pageview');
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ site.google_analytics_id }}');
</script>

@ -0,0 +1,21 @@
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="{{ site.color }}">
<meta name="msapplication-navbutton-color" content="{{ site.color }}">
<meta name="msapplication-TileColor" content="{{ site.color }}">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="description" content="{{ site.description }}">
<meta name="google-site-verification" content="{{ site.google_site_verification }}" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
{% seo %}
{% if site.google_analytics_id != "" %}
{% include google_analytics.html %}
{% endif %}

@ -1,3 +1,21 @@
<h4><a class="brand" href="{{ site.baseurl }}/home">{{ site.title }}</a>
{% if site.subtitle %}<small>{{ site.subtitle }}</small>{% endif %}
</h4>
<header class="text-center py-3 border-bottom has-divider">
<!-- center -->
<img class="logo align-middle" alt="Logo" src="{{ site.baseurl }}/static/icon_foreground.png"/>
<a class="h3 mx-2 align-middle text-decoration-none" href="{{ site.baseurl }}/home">{{ site.title }}</a>
<!-- left -->
<div class="left align-middle">
<img class="drawer-toggle p-2 mx-2 d-md-none"
alt="Menu toggle"
src="{{ site.baseurl }}/icons/menu.svg"
onclick="document.getElementById('drawer').classList.toggle('drawer-closed');"/>
</div>
<!-- right -->
<div class="right align-middle">
<span class="version d-none d-sm-inline-block">latest: v{{ site.github_version }}</span>
<a class="p-2 mx-2" href="https://github.com/{{ site.author.github }}/{{ site.github_repo }}">
<img alt="GitHub" src="{{ site.baseurl }}/icons/github.svg">
</a>
</div>
</header>

@ -1,16 +1,41 @@
<ul class="nav nav-pills nav-stacked">
<ul id="navigation" class="py-4">
<li><a href="{{ site.baseurl }}/home">Home</a></li>
{% for section in site.sections %}
{% assign attr = section[0] %}
{% assign label = section[1] %}
<li class="mt-3"><h5 class="mt-0 mb-1">{{ label }}</h5>
<ul>
{% for page in site.categories[attr] %}
{% if forloop.first %}
<li class="nav-header">{{ label }}</li>
{% endif %}
<li data-order="{{ page.order }}"><a href="{{ site.baseurl }}{{ page.url }}">{{ page.title }}</a></li>
<li class="pt-2 pb-2" data-order="{{ page.order }}">
<a href="{{ site.baseurl }}{{ page.url }}">{{ page.title }}</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
<!-- List additional links. It is recommended to add a divider
e.g. <li class="divider"></li> first to break up the content. -->
</ul>
<script>
/* find current item and make it active */
const current = document.location.href;
const links = document.querySelectorAll('#navigation a');
links.forEach((link) => {
if (current && link && current.endsWith(link.getAttribute('href'))) {
link.parentElement.classList.add('active')
}
});
/* reorder elements */
const sections = document.querySelectorAll('#navigation ul');
sections.forEach((section) => {
const entries = section.querySelectorAll('li');
const ordered = [];
entries.forEach((entry) => {
const order = entry.getAttribute('data-order');
ordered.push([entry, order]);
});
ordered.sort((a, b) => a[1] - b[1]);
ordered.forEach((entry) => {
section.appendChild(entry[0]);
})
});
</script>

@ -1,117 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>{{ site.title }}{% if page.title %} | {{ page.title }}{% endif %}</title>
<meta name="description" content="{{ site.subtitle }}">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="{{ site.baseurl }}/css/syntax.css">
<link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
{% seo %}
</head>
<body>
<div class="container">
<div class="row">
<div id="header" class="col-sm-12">
{% include header.html %}
</div>
</div>
<div class="row">
{% assign post_count = site.posts|size %}
{% if site.navigation != 0 and site.navigation == 1 or post_count > 0 %}
<div id="navigation" class="col-sm-2">
{% include navigation.html %}
</div>
<div id="content" class="col-sm-10">
{{ content }}
</div>
{% else %}
<div id="content" class="col-sm-12">
{{ content }}
</div>
{% endif %}
</div>
{% if page.disqus == 1 %}
<div class="row">
{% if site.navigation == 1 or post_count > 0 %}
<div id="navigation" class="col-sm-2"></div>
<div id="disqus" class="col-sm-10">
{% include disqus.html %}
</div>
{% else %}
<div id="disqus" class="col-sm-12">
{% include disqus.html %}
</div>
{% endif %}
</div>
{% endif %}
<div class="row">
<div id="footer" class="col-sm-12">
{% include footer.html %}
</div>
</div>
</div>
<script>
function orderNav() {
var list,
section,
header,
sections = [],
lists = {},
headers = {};
var locationObj = document.location.href;
var navUl = document.querySelectorAll('#navigation ul')[0],
navLis = document.querySelectorAll('#navigation ul li');
if (!navUl) return;
for (var i = 0; i < navLis.length; i++) {
var order, li = navLis[i];
if (li.classList.contains('nav-header')) {
section = li.textContent || li.innerText;
sections.push(section);
headers[section] = li;
continue;
}
var link = li.childNodes[0];
if (locationObj && link && locationObj.endsWith(link.getAttribute('href'))) {
li.classList.add('active');
}
if (!lists[section]) {
lists[section] = [];
}
order = parseFloat(li.getAttribute('data-order'))
lists[section].push([order, li]);
}
for (var i = 0; i < sections.length; i++) {
section = sections[i];
list = lists[section].sort(function(a, b) {
return a[0] - b[0];
});
if (header = headers[section]) {
navUl.appendChild(header);
}
for (var j = 0; j < list.length; j++) {
navUl.appendChild(list[j][1]);
}
}
}
if (document.querySelectorAll) orderNav();
</script>
{% if site.google_analytics_id != "" %}
{% include google_analytics.html %}
{% endif %}
</body>
</html>

@ -1,43 +1,30 @@
<!DOCTYPE html>
<html style="height:100%;width:100%;margin:0px;">
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
{% include head.html %}
<title>{{ site.title }}</title>
<meta name="description" content="{{ site.subtitle }}">
<meta name="google-site-verification" content="4x49i17ABIrSvUl52SeL0-t0341aTnWWaC62-FYCRT4" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <link rel="stylesheet" href="{{ site.baseurl }}/css/syntax.css">
<link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
{% seo %}
<link rel="stylesheet" href="{{ site.baseurl }}/css/landing.css">
<link rel="stylesheet" href="{{ site.baseurl }}/css/fonts_responsive.css">
</head>
<body id="landing">
<div class="container" align="center">
<div>
<img src="static/icon_foreground.png" width="45%" style="max-width:400px">
</div>
<div id="content">
<body>
<div class="container p-5">
<img class="d-block mx-auto" id="logo" src="{{ site.baseurl }}/static/icon_foreground.png" alt="Logo">
<div class="text-center">
<h1 id="title" class="display-2 font-weight-bold mt-2">{{ site.title }}</h1>
{{ content }}
</div>
<div class="row justify-content-sm-center">
<div class="col-xs-12 col-sm-auto"><a href="home">Documentation</a></div>
<div class="col-xs-12 col-sm-auto"><a href="about/changelog">Changelog</a></div>
<div class="col-xs-12 col-sm-auto"><a href="{{ site.codeurl }}">GitHub</a></div>
<div class="col-xs-12 col-sm-auto"><a href="extra/donate">Support</a></div>
<div class="text-center">
<a class="btn rounded-pill px-3 py-2 mx-2 mt-2" href="{{ site.baseurl }}/home">Documentation</a>
<a class="btn rounded-pill px-3 py-2 mx-2 mt-2" href="{{ site.baseurl }}/about/changelog">Changelog</a>
<a class="btn rounded-pill px-3 py-2 mx-2 mt-2" href="https://github.com/{{ site.author.github }}/{{ site.github_repo }}">GitHub</a>
<a class="btn rounded-pill px-3 py-2 mx-2 mt-2" href="{{ site.baseurl }}{{ site.donateurl }}">Support</a>
</div>
<br/>
<div class="row" id="screenshots">
<div class="col-sm-4"><img src="static/screen1.png"></div>
<div class="col-sm-4"><img src="static/screen2.png"></div>
<div class="col-sm-4"><img src="static/screen3.png"></div>
<div class="row">
<div class="col-12 col-sm-4 mt-4"><img class="img-fluid" src="{{ site.baseurl }}/static/screen1.png" alt="Screenshot 1"></div>
<div class="col-12 col-sm-4 mt-4"><img class="img-fluid" src="{{ site.baseurl }}/static/screen2.png" alt="Screenshot 2"></div>
<div class="col-12 col-sm-4 mt-4"><img class="img-fluid" src="{{ site.baseurl }}/static/screen3.png" alt="Screenshot 3"></div>
</div>
</div>
{% if site.google_analytics_id != "" %}
{% include google_analytics.html %}
{% endif %}
</body>
</html>

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
{% include head.html %}
<title>{{ site.title }}{% if page.title %} | {{ page.title }}{% endif %}</title>
<link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
<link rel="stylesheet" href="{{ site.baseurl }}/css/fonts_responsive.css">
</head>
<body>
{% include header.html %}
<div class="container-fluid container-md">
<div class="row">
<div id="drawer" class="col-md-3 px-4 border-right has-divider drawer drawer-closed">
{% include navigation.html %}
</div>
<div class="col-12 col-md-9">
<div class="content py-3 px-2">
{{ content }}
</div>
{% if page.disqus == 1 %}
<div class="mt-4">
{% include disqus.html %}
</div>
{% endif %}
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-12 p-0">
{% include footer.html %}
</div>
</div>
</div>
</body>
</html>

@ -1,11 +1,11 @@
---
layout: default
layout: main
---
<div class="page-header">
<h2>{{ page.title }}
{% if page.subtitle %}<small class="page-subtitle">{{ page.subtitle }}</small>{% endif %}
</h2>
<div class="page-header border-bottom has-divider pb-3">
<h1 class="d-inline-block mt-1 mb-0 mr-2">{{ page.title }}</h1>
{% if page.description %}<span>{{ page.description }}</span>{% endif %}
</div>
<div class="page mt-4">
{{ content }}
</div>

@ -1,8 +1,7 @@
---
layout: page
title: "Camera Events"
subtitle: "Events and lifecycle"
description: "Events and lifecycle"
description: "Dealing with the camera lifecycle and callbacks"
category: docs
date: 2018-12-20 20:02:08
order: 1

@ -1,7 +1,6 @@
---
layout: page
title: "Capture Size"
subtitle: "Set size of output media"
description: "Set size of output media"
category: docs
order: 9

@ -1,8 +1,7 @@
---
layout: page
title: "Capturing Media"
subtitle: "Taking pictures and videos"
description: "Taking pictures and videos"
description: "Understanding pictures, videos and the snapshot concept"
category: docs
order: 3
date: 2018-12-20 20:53:17
@ -49,10 +48,9 @@ resulting snapshots are square as well, no matter what the sensor available size
|`takePictureSnapshot()`|Pictures|Snapshot|`yes`|`yes`|`yes`|That of the preview stream, [or less](snapshot-size)|
|`takeVideoSnapshot(File)`|Videos|Snapshot|`yes`|`yes`|`yes`|That of the preview stream, [or less](snapshot-size)|
Please note that the video snaphot features requires:
- API 18. If called before, it throws
- An OpenGL preview (see [previews](previews)). If not, it throws
> Please note that the video snaphot features requires:
> - API 18. If called before, it throws
> - An OpenGL preview (see [previews](previews)). If not, it throws
### Capturing pictures while recording

@ -8,7 +8,7 @@ order: 3
New versions are released through GitHub, so the reference page is the [GitHub Releases](https://github.com/natario1/CameraView/releases) page.
Starting from 2.4.0, you can now [support development](https://github.com/sponsors/natario1) through the GitHub Sponsors program.
> Starting from 2.4.0, you can now [support development](https://github.com/sponsors/natario1) through the GitHub Sponsors program.
Companies can share a tiny part of their revenue and get private support hours in return. Thanks!
## v2.6.0
@ -54,7 +54,7 @@ This change greatly improved the FPS performance, which is what matters the most
<https://github.com/natario1/CameraView/compare/v2.3.1...v2.4.0>
### v2.3.1
#### v2.3.1
- <small>[Video]</small> Improvement: better timing for `onVideoRecordingStart()` thanks to [@agrawalsuneet][agrawalsuneet] ([#632][632])
- <small>[Video, Camera1]</small> Fix: fixed video errors when starting on specific devices ([#617][617])
@ -110,7 +110,7 @@ Please read the documentation page for usage instructions.
<https://github.com/natario1/CameraView/compare/v2.0.0-rc2...v2.0.0>
### v2.0.0-rc2
#### v2.0.0-rc2
- Fix: crashes when stopping video snapshots ([#513][513])
- Fix: dependencies missing, leading to runtime crashes ([#517][517])
@ -131,7 +131,7 @@ This is likely to be the last release before v2.0.0.
<https://github.com/natario1/CameraView/compare/v2.0.0-beta06...v2.0.0-rc1>
### v2.0.0-beta06
#### v2.0.0-beta06
- New: Full featured Camera2 integration! Use `cameraExperimental="true"` and `cameraEngine="camera2"` to test this out. ([#490][490])
- Improvement: we now choose a video recording profile that is compatible with the chosen size. Should fix some video recording issues. ([#477][477])
@ -147,7 +147,7 @@ If you were using `focusWithMarker`, you can [add back the old marker](../docs/m
<https://github.com/natario1/CameraView/compare/v2.0.0-beta05...v2.0.0-beta06>
### v2.0.0-beta05
#### v2.0.0-beta05
- Fixed `FrameProcessor` freeze and release behavior, was broken ([#431][431])
- New: new api `setAutoFocusResetDelay` to control the delay to reset the focus after autofocus was performed, thanks to [@cneuwirt][cneuwirt] ([#435][435])
@ -156,21 +156,21 @@ If you were using `focusWithMarker`, you can [add back the old marker](../docs/m
<https://github.com/natario1/CameraView/compare/v2.0.0-beta04...v2.0.0-beta05>
### v2.0.0-beta04
#### v2.0.0-beta04
- Renames setPreviewSize to setPreviewStreamSize (previewSize suggests it is related to the view size but it's not) ([#393][393])
- Added new APIs `setSnapshotMaxWidth` and `setSnapshotMaxHeight` ([#393][393]). You can now have a good looking preview but still take low-res snapshots using these snapshot constraints. Before this, the two sizes were coupled.
<https://github.com/natario1/CameraView/compare/v2.0.0-beta03...v2.0.0-beta04>
### v2.0.0-beta03
#### v2.0.0-beta03
- Fixed a few bugs ([#392][392])
- Important fixes to video snapshot recording ([#374][374])
<https://github.com/natario1/CameraView/compare/v2.0.0-beta02...v2.0.0-beta03>
### v2.0.0-beta02
#### v2.0.0-beta02
- Fixed important bugs ([#356][356])
- Picture snapshots are now flipped when front camera is used ([#360][360])
@ -182,7 +182,7 @@ If you were using `focusWithMarker`, you can [add back the old marker](../docs/m
This is the first beta release. For changes with respect to v1, please take a look at the [migration guide](../extra/v1-migration-guide).
### v1.6.1
#### v1.6.1
This is the last release before v2.
@ -204,7 +204,7 @@ This is the last release before v2.
<https://github.com/natario1/CameraView/compare/v1.5.1...v1.6.0>
### v1.5.1
#### v1.5.1
- Bug: byte array length for Frames was incorrect thanks to [@ssakhavi][ssakhavi] ([#205][205])
- Bug: gestures were crashing in some conditions ([#222][222])
@ -223,7 +223,7 @@ This is the last release before v2.
<https://github.com/natario1/CameraView/compare/v1.4.2...v1.5.0>
### v1.4.2
#### v1.4.2
- Add prefix to XML resources so they don't collide, thanks to [@RocketRider][RocketRider] ([#162][162])
- Add `videoMaxSize` API and XML attribute, to set max size video in bytes, thanks to [@chaitanyaraghav][chaitanyaraghav] ([#104][104])
@ -232,7 +232,7 @@ This is the last release before v2.
<https://github.com/natario1/CameraView/compare/v1.4.1...v1.4.2>
### v1.4.1
#### v1.4.1
- Fixed a bug that would flip the front camera preview on some devices ([#112][112])
- Two new `CameraOptions` APIs: `o.getSupportedPictureSizes()` and `o.getSupportedPictureAspectRatios()` ([#101][101])
@ -264,7 +264,7 @@ This is the last release before v2.
<https://github.com/natario1/CameraView/compare/v1.3.2...v1.4.0>
### v1.3.2
#### v1.3.2
- Fixed a memory leak thanks to [@andrewmunn][andrewmunn] ([#92][92])
- Reduced memory usage when using cropOutput thanks to [@RobertoMorelos][RobertoMorelos] ([#93][93])
@ -272,7 +272,7 @@ This is the last release before v2.
<https://github.com/natario1/CameraView/compare/v1.3.1...v1.3.2>
### v1.3.1
#### v1.3.1
- Fixed a bug that would make setFacing and other APIs freeze the camera ([#86][86])
- Fixed ConcurrentModificationExceptions during CameraListener callbacks ([#88][88])

@ -12,7 +12,7 @@ although it has reached a high level of stability.
We are grateful to anyone who has contributed with fixes, features or feature requests. If you don't
want to get involved but still want to support the project, please [consider donating](donate).
## Bug reports
### Bug reports
Please make sure to fill the bug report issue template on GitHub.
We highly recommend to try to reproduce the bug in the demo app, as this helps a lot in debugging
@ -31,7 +31,7 @@ Recommended extras:
- LogCat logs (use `CameraLogger.setLogLevel(LEVEL_VERBOSE)` to print all)
- Link to a GitHub repo where the bug is reproducible
## Pull Requests
### Pull Requests
Please open an issue first.
@ -43,7 +43,7 @@ Please write tests.
Unless the code was already not covered by tests, updated tests are required for merging. The lib
has a few unit tests and more robust tests in the `androidTest` folder, which can be run by Android Studio.
## License
### License
CameraView was formally born as a fork of [CameraKit-Android](https://github.com/wonderkiln/CameraKit-Android)
and [Google's CameraView](https://github.com/google/cameraview), but has been completely rewritten since.

@ -1,8 +1,7 @@
---
layout: page
title: "Controls"
subtitle: "Output parameters and capture options"
description: "Output parameters and capture options"
description: "Configuring output parameters and capture options"
category: docs
order: 2
date: 2018-12-20 21:08:53
@ -41,7 +40,6 @@ or `CameraOptions.supports(Control)` to see if it is supported.
Which camera to use, either back facing or front facing.
Defaults to the first available value (tries `BACK` first).
The available values are exposed through the `CameraOptions` object.
```java
@ -52,7 +50,6 @@ cameraView.setFacing(Facing.FRONT);
##### cameraFlash
Flash mode, either off, on, auto or torch. Defaults to `OFF`.
The available values are exposed through the `CameraOptions` object.
```java
@ -66,7 +63,6 @@ cameraView.setFlash(Flash.TORCH);
Sets the encoder for video recordings. Defaults to `DEVICE_DEFAULT`,
which should typically be H_264.
The available values are exposed through the `CameraOptions` object.
```java
@ -79,7 +75,6 @@ cameraView.setVideoCodec(VideoCodec.H_264);
Sets the desired white balance for the current session.
Defaults to `AUTO`.
The available values are exposed through the `CameraOptions` object.
```java
@ -93,7 +88,6 @@ cameraView.setWhiteBalance(WhiteBalance.CLOUDY);
##### cameraHdr
Turns on or off HDR captures. Defaults to `OFF`.
The available values are exposed through the `CameraOptions` object.
```java
@ -106,7 +100,6 @@ cameraView.setHdr(Hdr.ON);
The format for pictures taken with `takePicture()`. Does not apply to picture snapshots taken
with `takePictureSnapshot()`. The `JPEG` value is always supported, while for other values
support might change depending on the engine and the device sensor.
The available values are exposed through the `CameraOptions` object.
```java
@ -118,7 +111,6 @@ cameraView.setPictureFormat(PictureFormat.DNG);
Turns on or off audio stream while recording videos.
Defaults to `ON`.
The available values are exposed through the `CameraOptions` object.
```java
@ -183,7 +175,6 @@ cameraView.setPreviewFrameRate(0F);
The preview frame rate is an important parameter because it will also
control (broadly) the rate at which frame processor frames are dispatched,
the video snapshots frame rate, and the rate at which real-time filters are invoked.
The available values are exposed through the `CameraOptions` object:
```java

@ -1,7 +1,6 @@
---
layout: page
title: "Frame Processing"
subtitle: "Process each frame in real time"
description: "Process each frame in real time"
category: docs
order: 6

@ -1,7 +1,6 @@
---
layout: page
title: "Gestures"
subtitle: "Gestures control"
description: "Gestures control"
category: docs
order: 5

@ -1,7 +1,6 @@
---
layout: page
title: "Getting Started"
subtitle: "Simple guide to take your first picture"
description: "Simple guide to take your first picture"
category: about
date: 2018-12-20 17:48:58
@ -64,9 +63,9 @@ camera.addCameraListener(new CameraListener() {
})
```
### Take a picture
### Taking a picture
We're done. To take a picture upon user input, just call `takePicture()`.
To take a picture upon user input, just call `takePicture()`.
```java
camera.addCameraListener(new CameraListener() {
@ -90,7 +89,7 @@ camera.takePicture();
Read the docs about `takePictureSnapshot()` for a super fast, lower quality alternative.
### Take a video
### Taking a video
Taking a video is just the same thing, except that you must make sure that camera is in `Mode.VIDEO` mode,
and that you have write permissions to write the file:
@ -122,7 +121,7 @@ This was it, but there is a ton of other options available to customize the came
to control the sensor, the UI appearance, the quality and size of the output, or to live process
frames. Keep reading the documentation!
For runtime permissions and Manifest setup, please read the [permissions page](../docs/runtime-permissions).
> For runtime permissions and Manifest setup, please read the [permissions page](../docs/runtime-permissions).
### Without support libraries

@ -1,7 +1,6 @@
---
layout: page
title: "Install"
subtitle: "Integrate in your project"
description: "Integrate in your project"
category: about
order: 1
@ -24,7 +23,7 @@ allprojects {
Then simply download the latest version:
```groovy
api 'com.otaliastudios:cameraview:2.6.0'
api 'com.otaliastudios:cameraview:{{ site.github_version }}'
```
No other configuration steps are needed.

@ -1,7 +1,6 @@
---
layout: page
title: "More features"
subtitle: "Undocumented features & more"
description: "Undocumented features & more"
category: docs
order: 16

@ -1,7 +1,6 @@
---
layout: page
title: "Preview Size"
subtitle: "Measuring behavior"
description: "Measuring behavior"
category: docs
order: 8
@ -22,7 +21,7 @@ This means that your visible preview can be of any size, not just the presets.
Whatever you do, the preview will never be distorted - it can only be cropped
if needed.
## Examples
### Examples
##### Center Inside
@ -55,11 +54,11 @@ This means that part of the preview might be hidden, and the output might contai
that were not visible during the capture, **unless it is taken as a snapshot, since snapshots account for cropping**.
## Advanced feature: Preview Stream Size Selection
### Advanced feature: Preview Stream Size Selection
*Only do this if you know what you are doing. This is typically not needed - prefer picture/video size selectors,
> Only do this if you know what you are doing. This is typically not needed - prefer picture/video size selectors,
as they will drive the preview stream size selection and, eventually, the view size. If what you want is just
choose an aspect ratio, do so with [Capture Size](capture-size) selection.*
choose an aspect ratio, do so with [Capture Size](capture-size) selection.
As said, `WRAP_CONTENT` adapts the view boundaries to the preview stream size. The preview stream size must be determined
based on the sizes that the device sensor & hardware actually support. This operation is done automatically

@ -1,7 +1,6 @@
---
layout: page
title: "Engine and Previews"
subtitle: "Camera engine and preview implementations"
description: "Camera engine and preview implementations"
category: docs
order: 7

@ -1,7 +1,6 @@
---
layout: page
title: "Runtime Permissions"
subtitle: "Permissions and Manifest setup"
description: "Permissions and Manifest setup"
category: docs
order: 13
@ -9,7 +8,7 @@ date: 2018-12-20 20:03:03
disqus: 1
---
`CameraView` needs two permissions:
CameraView needs two permissions:
- `android.permission.CAMERA` : required for capturing pictures and videos
- `android.permission.RECORD_AUDIO` : required for capturing videos with `Audio.ON` (the default)

@ -1,7 +1,6 @@
---
layout: page
title: "v1 Migration Guide"
subtitle: "Breaking Changes & new concepts"
description: "Breaking Changes & new concepts"
category: extra
date: 2018-12-20 19:01:55
@ -77,7 +76,7 @@ The engine will use the video size selector when mode is `VIDEO`, and the pictur
### Picture and videos
#### Take, not capture
##### Take, not capture
- `capturePicture()` is now `takePicture()`
- `captureSnapshot()` is now `takePictureSnapshot()`
@ -86,7 +85,7 @@ The engine will use the video size selector when mode is `VIDEO`, and the pictur
The new `isTakingPicture()` method was added for symmetry with videos.
#### Snapshots
##### Snapshots
This is the major improvement over v1. There are now 4 capture APIs, two for pictures and two for videos.
- Standard APIs: `takePicture()` and `takeVideo()`. These take a high quality picture or video, depending
@ -111,7 +110,7 @@ which makes it a powerful tool. The drawback is that it needs:
- API 18. If called before, it throws
- An OpenGL preview (see below). If not, it throws
#### Video capturing
##### Video capturing
Some new APIs were introduced, which are respected by both standard videos and snapshot videos:
- `setAudioBitRate()` and `cameraAudioBitRate`: sets the audio bit rate in bit/s

@ -17,13 +17,13 @@ according to the GitHub Sponsors tier you choose and the Open Collective rules.
Thank you for any contribution!
## Project Backers
### Project Backers
Thanks to all the project backers! [Become a backer.](https://opencollective.com/cameraview#backer)
<a href="https://opencollective.com/cameraview#backers" target="_blank"><img src="https://opencollective.com/cameraview/backers.svg?width=890"></a>
## Project Sponsors
### Project Sponsors
Thanks to all the project sponsors! [Become a sponsor](https://opencollective.com/cameraview#sponsor) and have your logo here.

@ -1,7 +1,6 @@
---
layout: page
title: "Snapshot Size"
subtitle: "Sizing the snapshots output"
description: "Sizing the snapshots output"
category: docs
order: 10

@ -1,7 +1,6 @@
---
layout: page
title: "Watermarks and Overlays"
subtitle: "Static and animated overlays"
description: "Static and animated overlays"
category: docs
order: 11

@ -1,7 +1,6 @@
---
layout: page
title: "Real-time Filters"
subtitle: "Apply filters to preview and snapshots"
description: "Apply filters to preview and snapshots"
category: docs
order: 12
@ -37,8 +36,8 @@ cameraView.setFilter(Filters.SEPIA.newInstance());
```
All of the filters stored in the `Filters` class have an XML string resource that you can use
to quickly setup the camera view. For example, `Filters.BLACK_AND_WHITE` can be set by using
`app:cameraFilter="@string/cameraview_filter_black_and_white`.
to quickly setup the camera view. For example, `Filters.BLACK_AND_WHITE` can be used by setting
`app:cameraFilter` to `"@string/cameraview_filter_black_and_white"`.
The default filter is called `NoFilter` (`Filters.NONE`) and can be used to clear up any other
filter that was previously set and return back to normal.
@ -115,7 +114,7 @@ There are some technical caveats when using a `MultiFilter`:
Advanced users with OpenGL experience can create their own filters by implementing the `Filter` interface
and passing in a fragment shader and a vertex shader that will be used for drawing.
#### Simple filters
##### Simple filters
For very simple filters that have a static fragment shader, you can create a working filter
implementation by simply creating an instance of `SimpleFilter`:
@ -124,7 +123,7 @@ implementation by simply creating an instance of `SimpleFilter`:
Filter filter = new SimpleFilter(myFragmentShader);
```
#### More complex filters
##### More complex filters
We recommend:

@ -1,7 +1,6 @@
---
layout: page
title: "Metering"
subtitle: "Exposure and metering controls"
description: "Exposure and metering controls"
category: docs
order: 4
@ -28,8 +27,8 @@ as the device moves or the scene changes.
### Picture Metering
*In Camera1, picture metering is always enabled for pictures, and always disabled for picture snapshots.
The following applies to Camera2 only.*
> In Camera1, picture metering is always enabled for pictures, and always disabled for picture snapshots.
The following applies to Camera2 only.
The camera engine will try to trigger metering when a picture is requested, either with `takePicture()`
or `takePictureSnapshot()`. This has two obvious consequences:
@ -106,7 +105,7 @@ cameraView.setAutoFocusMarker(new DefaultAutoFocusMarker());
##### Touch Metering Reset Delay
You control control how a touch metering operation is reset after completed.
Setting a value <= 0 or == Long.MAX_VALUE will not reset the metering values.
Setting a negative value (or 0, or `Long.MAX_VALUE`) will not reset the metering values.
This is useful for low end devices that have slow auto-focus capabilities.
Defaults to 3 seconds.

@ -1,5 +1,5 @@
---
layout: default
layout: main
title: "CameraView"
---

@ -0,0 +1,65 @@
:root {
--color-primary: #f76c16;
--color-primary-active: #e75c16;
--color-primary-hover: #d74c16;
--color-secondary: #f7a816;
--color-accent: #0e95e3;
--color-accent-light: #f5fcff;
--color-accent-dark: #0e3375;
--color-background: #FFFFFF;
--color-code: var(--color-primary);
--color-code-background: #f8f8f8;
--color-text-muted: #6c757d;
}
body {
background-color: var(--color-background);
}
a {
color: var(--color-primary);
}
code, pre {
background-color: var(--color-code-background);
}
:not(pre) > code {
color: var(--color-code);
}
a:hover {
color: var(--color-primary-hover) !important;
}
.btn-primary {
background-color: var(--color-primary) !important;
border-color: var(--color-primary) !important;
color: white !important;
}
.btn-primary.active, .btn-primary:active {
background-color: var(--color-primary-active) !important;
border-color: var(--color-primary-active) !important;
}
.btn-primary:hover {
background-color: var(--color-primary-hover) !important;
border-color: var(--color-primary-hover) !important;
color: white !important;
}
.btn-outline-primary {
border-color: var(--color-primary) !important;
}
.btn-outline-primary.active, .btn-outline-primary:active {
background-color: var(--color-primary-active) !important;
border-color: var(--color-primary-active) !important;
}
.btn-outline-primary:hover {
border-color: var(--color-primary-hover) !important;
background-color: var(--color-primary-hover) !important;
color: white !important;
}

@ -0,0 +1,33 @@
@import url('https://fonts.googleapis.com/css?family=Lobster+Two:400i,700i|Roboto+Mono|Source+Sans+Pro:400,700&display=swap');
@import "fonts_responsive.css";
:root {
--font-mono: 'Roboto Mono';
--font-sans: 'Source Sans Pro';
--font-display: 'Lobster Two';
}
* {
font-family: var(--font-sans), sans-serif;
font-weight: 400;
}
h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
font-family: var(--font-display), cursive;
font-style: italic;
font-weight: 700 !important;
}
h4, .h4, h5, .h5, h6, .h6 {
font-weight: 400;
}
button, .btn {
font-family: var(--font-display), cursive !important;
font-style: italic !important;
font-weight: 700 !important;
}
code, code * {
font-family: var(--font-mono) !important;
}

@ -0,0 +1,34 @@
/* https://christianoliff.com/blog/bootstrap-with-rfs */
/* either apply after everything else or add !important here */
@media (max-width: 1200px) {
legend {
font-size: calc(1.275rem + 0.3vw);
}
h1, .h1 {
font-size: calc(1.375rem + 1.5vw);
}
h2, .h2 {
font-size: calc(1.325rem + 0.9vw);
}
h3, .h3 {
font-size: calc(1.3rem + 0.6vw);
}
h4, .h4 {
font-size: calc(1.275rem + 0.3vw);
}
.display-1 {
font-size: calc(1.725rem + 5.7vw);
}
.display-2 {
font-size: calc(1.675rem + 5.1vw);
}
.display-3 {
font-size: calc(1.575rem + 3.9vw);
}
.display-4 {
font-size: calc(1.475rem + 2.7vw);
}
.close {
font-size: calc(1.275rem + 0.3vw);
}
}

@ -0,0 +1,38 @@
@import "fonts.css";
@import "colors.css";
html {
width: 100%;
height: 100%;
margin: 0;
}
body {
background: radial-gradient(ellipse, var(--color-secondary), var(--color-primary)) fixed !important;
}
#logo {
width: 45%;
max-width: 340px;
}
h1 {
color: white;
}
p {
color: rgba(255, 255, 255, 0.7);
font-size: 1.2em;
line-height: 100%;
}
.btn {
color: white !important;
background-color: rgba(240, 240, 240, 0.25);
font-size: 1.3em;
}
.btn:hover {
color: white !important;
background-color: rgba(240, 240, 240, 0.4);
}

@ -1,216 +1,274 @@
@import url('https://fonts.googleapis.com/css?family=Calistoga|Roboto+Mono|Source+Sans+Pro:400,700&display=swap');
@import "fonts.css";
@import "colors.css";
@import "syntax.css";
body {
font-weight: 400;
font-family: 'Source Sans Pro', sans-serif;
:root {
--color-footer: var(--color-code-background);
--color-table-head: var(--color-code-background);
--color-divider: rgba(230, 230, 230, 0.7);
--header-height: 65px; /* kind of */
--cards-radius: 4px;
}
h1, h2, h3, h4, h5, h6, th {
font-family: 'Calistoga', sans-serif;
html, body {
height: 100%;
}
small {
font-weight: 400;
font-family: 'Source Sans Pro', sans-serif;
}
/* dividers */
pre, code, pre code {
border: none;
border-radius: 0;
background-color: #fafafa;
font-size: 0.8em;
.has-divider {
border-color: var(--color-divider) !important;
}
.highlight {
background-color: #fafafa;
border-radius: 12px;
}
/* header */
pre {
font-size: 1em;
header {
background: radial-gradient(ellipse, var(--color-secondary), var(--color-primary)) fixed;
position: fixed;
top: 0;
width: 100%;
z-index: 10;
}
code {
color: inherit;
font-family: 'Roboto Mono', monospace;
color: #dd2200;
header .left {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
a {
color: #0e95e3;
header .right {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}
#header {
border-bottom: 1px solid #eee;
margin-bottom: 20px;
header a {
color: white !important;
}
#header a:hover {
text-decoration: none;
header a:hover {
color: white !important;
}
#content {
/* bigger font */
font-size: 1.1em;
header .logo {
height: 32px;
width: auto;
}
#content p {
/* spacing for all paragraphs */
margin-top: 16px;
margin-bottom: 16px;
header .version {
font-size: 0.9em;
color: rgba(255, 255, 255, 0.8);
}
#content ul li {
/* spacing for lists */
margin-top: 8px;
margin-bottom: 8px;
body {
/* to offset wrt sticky header */
padding-top: var(--header-height);
}
#content h5 {
font-size: 1.1em;
/* footer */
footer {
background-color: var(--color-footer);
color: var(--color-text-muted);
font-size: 0.9em;
}
#footer {
margin: 20px 0;
font-size: 0.85em;
color: #999;
text-align: center;
/* drawer */
.drawer-toggle:hover {
background-color: rgba(240, 240, 240, 0.25);
border-radius: 50%;
}
#content > .page-header:first-child {
margin-top: 0;
@media (max-width: 768px) {
.drawer {
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 100%;
overflow-x: hidden;
overflow-y: auto;
background-color: var(--color-background);
transition: transform 0.4s cubic-bezier(0.4, 0, 0, 1);
z-index: 5;
padding-top: var(--header-height);
}
#content > .page-header:first-child h2 {
margin-top: 0;
.drawer-closed {
transform: translateX(-100%);
}
}
#content .page-subtitle {
font-size: 0.45em;
@media (max-width: 480px) {
.drawer {
width: 100%;
}
}
#landing {
background: radial-gradient(ellipse, #f7a816, #f76c16) !important;
background-attachment: fixed !important;
.drawer ul {
list-style: none;
margin: 0;
padding: 0;
line-height: 100%;
}
#landing h1 {
font-size: 10vw;
color: white;
margin-top: 16px;
margin-bottom: 0px;
letter-spacing: 0.04em;
font-weight: bold;
.drawer a {
color: inherit;
}
@media (min-width: 576px) {
#landing h1 {
font-size: 4em;
.drawer a:hover {
color: var(--color-primary-hover) !important;
}
.drawer li.active a {
color: var(--color-primary);
position: relative;
}
#landing p {
font-size: 1.2em;
color: rgba(255, 255, 255, 0.7);
margin: 8px;
max-width: 80%;
line-height: 100%;
/* .drawer li.active a:hover {
color: var(--color-primary-active) !important;
text-decoration: none;
} */
.drawer li.active {
position: relative;
}
#landing a {
background-color: rgba(240, 240, 240, 0.3);
color: white;
border-radius: 24px;
padding: 10px 20px 10px 20px;
margin-top: 16px;
.drawer li.active::after {
content: '';
display: inline-block;
font-family: 'Calistoga', sans-serif;
font-size: 1.1em;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
width: 8px;
height: 8px;
background-color: var(--color-primary);
border-radius: 50%;
}
#landing #screenshots img {
max-width: 100%;
padding: 12px;
/* tables */
table {
/* same margins that reboot gives to pre */
margin-top: 0;
margin-bottom: 1rem;
border-collapse: collapse;
/* make it scrollable if needed */
display: block;
overflow-x: auto;
}
#landing #screenshots {
margin-top: 24px;
margin-bottom: 24px;
thead {
background-color: var(--color-table-head);
}
#navigation {
font-size: 1.0em;
th {
padding: 8px;
border: 1px solid var(--color-divider);
font-family: var(--font-display), sans-serif;
font-weight: 700;
}
#navigation li a {
padding-left: 16px;
padding-right: 16px;
border-radius: 32px;
td {
padding: 8px;
border: 1px solid var(--color-divider);
}
#navigation li a:hover {
background: #fafafa;
/* page and content */
.content a, footer a {
color: var(--color-accent);
}
#navigation li.active a {
background: #f76c16;
color: #FFFFFF;
.content a:hover, footer a:hover {
color: var(--color-accent) !important;
}
#navigation .nav-header {
padding-top: 16px;
padding-bottom: 4px;
padding-left: 0;
padding-right: 0;
.content ul {
padding-left: 24px;
}
.nav-header {
font-size: 1.1em;
cursor: default;
/* text-transform: uppercase; */
font-weight: bold;
font-family: 'Calistoga', sans-serif;
.content blockquote {
background-color: var(--color-code-background);
border-radius: var(--cards-radius);
border-left: 4px;
border-left-style: solid;
border-left-color: var(--color-accent);
font-size: 0.9em;
color: var(--color-text-muted);
padding: 0.8rem;
/* text-align: justify;
position: relative;
padding: 0.5rem 32px 0.5rem 0.5rem;
text-justify: inter-word; */
}
body.rtl {
direction: rtl;
/* .content blockquote::after {
content: '!';
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 16px;
font-size: 1rem !important;
font-weight: 700 !important;
color: var(--color-accent);
} */
.content blockquote p, .content blockquote ul {
margin: 0;
}
body.rtl #header .brand {
float: right;
margin-left: 5px;
.content h1, .content h2, .content h3, .content h4, .content h5, .content h6 {
margin-top: 1.4rem;
margin-bottom: 0.8rem;
}
body.rtl .row-fluid [class*="span"] {
float: right !important;
margin-left: 0;
margin-right: 2.564102564102564%;
.page-header span {
font-size: 0.9em;
color: var(--color-text-muted);
}
body.rtl .row-fluid [class*="span"]:first-child {
margin-right: 0;
/* code */
pre {
border-radius: var(--cards-radius);
padding: 0.8rem;
font-size: 0.8rem !important;
line-height: 1.6;
}
body.rtl ul, body.rtl ol {
margin: 0 25px 10px 0;
:not(pre) > code {
border-radius: var(--cards-radius);
padding: 2px;
font-weight: 700 !important;
font-size: 0.8rem !important;
}
table {
margin-top: 25px;
margin-bottom: 25px;
border: 1px solid #e5e5e5;
border-collapse: collapse;
.language-java, .language-xml, .language-groovy {
position: relative;
}
thead {
background-color: #f9f9f9;
.language-java::after, .language-xml::after, .language-groovy::after {
position: absolute;
top: 0;
right: 0;
padding: 6px;
font-size: 0.65rem;
color: var(--color-text-muted);
}
td {
padding: .25rem .5rem;
border: 1px solid #e5e5e5;
.language-java::after {
content: 'java';
}
th {
padding: 8px 12px;
border: 1px solid #e5e5e5;
font-weight: 400;
.language-xml::after {
content: 'xml';
}
.language-groovy::after {
content: 'groovy';
}

@ -1,61 +1,86 @@
/* https://github.com/richleland/pygments-css/ */
@import "colors.css";
:root {
--syntax-muted: #999999;
--syntax-annotations: #a49848;
--syntax-keyword: #007020;
--syntax-operators: #606060;
--syntax-numbers: var(--syntax-keyword);
--syntax-xml-tags: var(--syntax-keyword);
}
.highlight .c { color: var(--syntax-muted); font-style: italic } /* Comment */
.highlight .ch { color: var(--syntax-muted); font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: var(--syntax-muted); font-style: italic } /* Comment.Multiline */
.highlight .cp { color: var(--syntax-muted); } /* Comment.Preproc */
.highlight .cpf { color: var(--syntax-muted); font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: var(--syntax-muted); font-style: italic } /* Comment.Single */
.highlight .cs { color: var(--syntax-muted); background-color: #fff0f0 } /* Comment.Special */
.highlight .nt { color: var(--syntax-xml-tags); font-weight: bold } /* Name.Tag */
.highlight .na { color: inherit; /* var(--color-accent) */ } /* Name.Attribute */
.highlight .nf { color: inherit; /* var(--color-accent) */ } /* Name.Function */
.highlight .mb { color: var(--syntax-numbers) } /* Literal.Number.Bin */
.highlight .mf { color: var(--syntax-numbers) } /* Literal.Number.Float */
.highlight .mh { color: var(--syntax-numbers) } /* Literal.Number.Hex */
.highlight .mi { color: var(--syntax-numbers) } /* Literal.Number.Integer */
.highlight .mo { color: var(--syntax-numbers) } /* Literal.Number.Oct */
.highlight .nd { color: var(--syntax-annotations); } /* Name.Decorator */
.highlight .k { color: var(--syntax-keyword); font-weight: bold } /* Keyword */
.highlight .kd { color: var(--syntax-keyword); font-weight: bold } /* Keyword.Declaration */
.highlight .kt { color: var(--syntax-keyword); font-weight: bold } /* Keyword.Type */
.highlight .kc { color: var(--syntax-keyword); font-weight: bold } /* Keyword.Constant */
.highlight .kn { color: var(--syntax-keyword); font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: var(--syntax-keyword); font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { color: var(--syntax-keyword); font-weight: bold } /* Keyword.Reserved */
.highlight .s { color: var(--color-accent-dark); background-color: var(--color-accent-light); } /* Literal.String */
.highlight .s1 { color: var(--color-accent-dark); background-color: var(--color-accent-light); } /* Literal.String.Single */
.highlight .sa { color: var(--color-accent-dark) } /* Literal.String.Affix */
.highlight .sb { color: var(--color-accent-dark) } /* Literal.String.Backtick */
.highlight .sc { color: var(--color-accent-dark) } /* Literal.String.Char */
.highlight .dl { color: var(--color-accent-dark) } /* Literal.String.Delimiter */
.highlight .sd { color: var(--color-accent-dark); font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: var(--color-accent-dark) } /* Literal.String.Double */
.highlight .se { color: var(--color-accent-dark); font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: var(--color-accent-dark) } /* Literal.String.Heredoc */
.highlight .si { color: var(--color-accent-dark); font-style: italic } /* Literal.String.Interpol */
.highlight .sx { color: var(--color-accent-dark) } /* Literal.String.Other */
.highlight .sr { color: var(--color-accent-dark) } /* Literal.String.Regex */
.highlight .ss { color: var(--color-accent-dark) } /* Literal.String.Symbol */
.highlight .o { color: var(--syntax-operators) } /* Operator */
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; /* background-color: #fff0f0 */ } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .m { color: #40a070 } /* Literal.Number */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.highlight .no { color: #60add5 } /* Name.Constant */
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #007020 } /* Name.Exception */
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nv { color: #bb60d5 } /* Name.Variable */
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06287e } /* Name.Function.Magic */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 512 499.36">
<path
fill="#fff"
fill-rule="evenodd"
fill-opacity="0.8"
d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z"/>
</svg>

After

Width:  |  Height:  |  Size: 993 B

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24">
<path fill="none" d="M0 0h24v24H0V0z"/>
<path fill="#fff" fill-opacity="0.8" d="M4 18h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1s.45 1 1 1zm0-5h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1s.45 1 1 1zM3 7c0 .55.45 1 1 1h16c.55 0 1-.45 1-1s-.45-1-1-1H4c-.55 0-1 .45-1 1z"/>
</svg>

After

Width:  |  Height:  |  Size: 395 B

@ -3,7 +3,5 @@ layout: landing
title: "CameraView"
---
# CameraView
A well documented, high-level library that makes capturing pictures and videos easy,
addressing all of the common issues and needs. Supports real-time filters, gestures, watermarks, frame processing, RAW, outputs of any size and much more.

@ -1,107 +0,0 @@
#!/usr/bin/env ruby
require 'date'
require 'optparse'
options = {
# Expects to be in the bin/ sub-directory by default
:path => File.dirname(File.dirname(__FILE__))
}
parser = OptionParser.new do |opt|
opt.banner = 'usage: jekyll-page TITLE CATEGORY [FILENAME] [OPTIONS]'
opt.separator ''
opt.separator 'Options'
opt.on('-e', '--edit', 'Edit the page') do |edit|
options[:edit] = true
end
opt.on('-l', '--link', 'Relink pages') do |link|
options[:link] = true
end
opt.on('-p PATH', '--path PATH', String, 'Path to project root') do |path|
options[:path] = path
end
opt.separator ''
end
parser.parse!
title = ARGV[0]
category = ARGV[1]
filename = ARGV[2]
# Resolve any relative links
BASE_DIR = File.expand_path(options[:path])
POSTS_DIR = "#{BASE_DIR}/_posts"
PAGES_DIR = "#{BASE_DIR}/_pages"
# Ensure the _posts directory exists (we are in the correct directory)
if not Dir.exists?(POSTS_DIR)
puts "#{POSTS_DIR} directory does not exists"
exit
end
# Create _pages directory if it doesn't exist
if not Dir.exists?(PAGES_DIR)
Dir.mkdir(PAGES_DIR)
end
if options[:link]
Dir.foreach(POSTS_DIR) do |name|
next if name[0] == '.'
nodate = name[/\d{4}-\d{2}-\d{2}-(?<rest>.*)/, 'rest']
if File.symlink?("#{PAGES_DIR}/#{nodate}")
File.delete("#{PAGES_DIR}/#{nodate}")
end
abspath = File.absolute_path("#{POSTS_DIR}/#{name}")
File.symlink(abspath, "#{PAGES_DIR}/#{nodate}")
end
end
if not title or not category
# This flag can be used by itself, exit silently if no arguments
# are defined
if not options[:link]
puts parser
end
exit
end
if not filename
filename = title.downcase.gsub(/[^a-z0-9\s]/, '').gsub(/\s+/, '-')
end
today=Date.today().strftime('%F')
now=DateTime.now().strftime('%F %T')
filepath = "#{POSTS_DIR}/#{today}-#{filename}.md"
symlink = "#{PAGES_DIR}/#{filename}.md"
if File.exists?(filepath)
puts "File #{filepath} already exists"
exit
end
content = <<END
---
layout: page
title: \"#{title}\"
category: #{category}
date: #{now}
---
END
File.open(filepath, 'w') do |file|
file.puts content
end
File.symlink("../_posts/#{today}-#{filename}.md", symlink)
if options[:edit]
if not ENV['EDITOR']
puts 'No $EDITOR variable set'
exit
end
puts ENV['EDITOR']
exec("#{ENV['EDITOR']} #{filename}")
end
Loading…
Cancel
Save