Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Brightness table special effects try #517

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cgeDemo/src/main/java/org/wysaid/cgeDemo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public class MainActivity extends AppCompatActivity {

public static final String EFFECT_CONFIGS[] = {
"",
"@curve RGB(0,255)(255,0) @style cm mapping0.jpg 80 80 8 3", // ASCII art (字符画效果)
"@style hist 0.01 0.01 0.4 0.4 0.0 0.0 0.0 0.9",
"@style waveform 0.01 0.01 0.4 0.4",
"@curve RGB(0,255)(255,0) @style cm mapping0.jpg 80 80 8 3", // ASCII art (字符画效果)
"@beautify face 1 480 640", //Beautify
"@adjust lut edgy_amber.png",
"@adjust lut filmstock.png",
Expand Down
1 change: 1 addition & 0 deletions library/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ LOCAL_SRC_FILES := \
$(CGE_SOURCE)/filters/cgeEmbossFilter.cpp \
\
$(CGE_SOURCE)/filters/cgeWaveformFilter.cpp \
$(CGE_SOURCE)/filters/cgeHistogramFilter.cpp \
\
$(CGE_SOURCE)/filters/cgeCrosshatchFilter.cpp \
$(CGE_SOURCE)/filters/cgeLiquifyFilter.cpp \
Expand Down
75 changes: 73 additions & 2 deletions library/src/main/jni/cge/common/cgeGLFunctions.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
/*
* cgeGLFunctions.cpp
*
* Created on: 2013-12-5
* Author: Wang Yang
*/

#include "cgeGLFunctions.h"

#include <EGL/egl.h>
#include <cmath>

CGE_LOG_CODE(
Expand Down Expand Up @@ -390,4 +390,75 @@ bool FrameBufferWithTexture::checkStatus()
return ret == GL_FRAMEBUFFER_COMPLETE;
}

//////////////

FrameBufferTexture::FrameBufferTexture() : m_fbo(0), m_texture(0), m_width(0), m_height(0)
{
glGenFramebuffers(1, &m_fbo);
assert(m_fbo != 0);
}

FrameBufferTexture::~FrameBufferTexture()
{
glDeleteFramebuffers(1, &m_fbo);
glDeleteTextures(1, &m_texture);
}

GLuint FrameBufferTexture::texture() const
{
return m_texture;
}

GLsizei FrameBufferTexture::width() const
{
return m_width;
}

GLsizei FrameBufferTexture::height() const
{
return m_height;
}

void FrameBufferTexture::bindTexture2D(GLsizei width, GLsizei height)
{
if (m_texture == 0)
{
glGenTextures(1, &m_texture);
assert(m_texture != 0);
}

glBindTexture(GL_TEXTURE_2D, m_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);

m_width = width;
m_height = height;
}

void FrameBufferTexture::bind()
{
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
}

unsigned char* FrameBufferTexture::mapBuffer()
{
glBindTexture(GL_TEXTURE_2D, m_texture);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
const auto bufferSize = m_width * m_height * sizeof(float);
auto buffer = new unsigned char[bufferSize];
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_UNSIGNED_BYTE, buffer);
return buffer;
}

void FrameBufferTexture::unmapBuffer()
{
glBindTexture(GL_TEXTURE_2D, 0);
}

} // namespace CGE
26 changes: 24 additions & 2 deletions library/src/main/jni/cge/common/cgeGLFunctions.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* cgeGLFunctions.h
*
* Created on: 2013-12-5
Expand Down Expand Up @@ -103,13 +103,14 @@ class FrameBuffer
bindTexture2D(texID, attachment);
glViewport(x, y, w, h);
}

inline GLuint fbo() { return m_framebuffer; }


protected:
GLuint m_framebuffer;
};


struct CGESizei
{
CGESizei() :
Expand Down Expand Up @@ -210,6 +211,27 @@ class FrameBufferWithTexture : protected FrameBuffer, public TextureObject
GLuint m_renderBuffer = 0;
};

class FrameBufferTexture
{
public:
FrameBufferTexture();
~FrameBufferTexture();

GLuint texture() const;
GLsizei width() const;
GLsizei height() const;
void bindTexture2D(GLsizei width, GLsizei height);
void bind();
unsigned char* mapBuffer();
void unmapBuffer();

private:
GLuint m_fbo;
GLuint m_texture;
GLsizei m_width;
GLsizei m_height;
};

struct CGELuminance
{
enum
Expand Down
5 changes: 5 additions & 0 deletions library/src/main/jni/cge/filters/cgeAdvancedEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ CGEBeautifyFilter* createBeautifyFilter()
COMMON_FUNC(CGEBeautifyFilter);
}

CGEHistogramFilter* createHistogramFilter()
{
COMMON_FUNC(CGEHistogramFilter);
}

CGEWaveformFilter* createWaveformFilter()
{
COMMON_FUNC(CGEWaveformFilter);
Expand Down
2 changes: 2 additions & 0 deletions library/src/main/jni/cge/filters/cgeAdvancedEffects.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "cgeRandomBlurFilter.h"
#include "cgeSketchFilter.h"
#include "cgeWaveformFilter.h"
#include "cgeHistogramFilter.h"

namespace CGE
{
Expand Down Expand Up @@ -51,6 +52,7 @@ CGESketchFilter* createSketchFilter();
CGEBeautifyFilter* createBeautifyFilter();

CGEWaveformFilter* createWaveformFilter();
CGEHistogramFilter* createHistogramFilter();
} // namespace CGE

#endif
17 changes: 17 additions & 0 deletions library/src/main/jni/cge/filters/cgeDataParsingEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,23 @@ CGEImageFilterInterface* CGEDataParsingEngine::advancedStyleParser(const char* p
{
ADJUSTHELP_COMMON_FUNC2(pstr, CGECrosshatchFilter, setCrosshatchSpacing, setLineWidth);
}
else if (strcmp(buffer, "hist") == 0)
{
float x, y, width, height;
if (sscanf(pstr, "%f%*c%f%*c%f%*c%f", &x, &y, &width, &height) < 4)
{
LOG_ERROR_PARAM(pstr);
return nullptr;
}

CGEHistogramFilter* filter = createHistogramFilter();
if (filter != nullptr)
{
proc = filter;
filter->setFormPosition(x, y);
filter->setFormSize(width, height);
}
}
else if (strcmp(buffer, "waveform") == 0)
{
float x, y, width, height;
Expand Down
126 changes: 126 additions & 0 deletions library/src/main/jni/cge/filters/cgeHistogramFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@

#include "cgeHistogramFilter.h"

#include <EGL/egl.h>
#include <array>

static CGEConstString s_vshHistogram = "#version 320 es\n" CGE_SHADER_STRING_PRECISION_H(
layout(location = 0) in vec2 position;
layout(location = 0) out vec2 textureCoordinate;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
textureCoordinate = (position.xy + 1.0) / 2.0;
});

static CGEConstString s_fshHistogram = "#version 320 es\n" CGE_SHADER_STRING(
precision highp float;
precision highp int;
layout(location = 0) in vec2 textureCoordinate;
layout(rgba8ui, binding = 0) uniform readonly highp uimage2D inputImageTexture;
layout(rgba8ui, binding = 1) uniform writeonly highp uimage2D outputImage;
layout(location = 0) out vec4 fragColor;

void main() {
fragColor = vec4(1.0);

vec4 color = texture(inputImageTexture, textureCoordinate);
float lum = dot(color.rgb, vec3(0.299, 0.587, 0.114));
int newLoc = int(lum * 255.0);
if (newLoc >= 0 && newLoc < 256) {
//vec2 location = vec2(newLoc, 0.0);
ivec2 location = ivec2(newLoc, 0);
atomicAdd(imageAtomic(outputImage, location), 1);
//imageAtomic(outputImage, ivec2(location.x, location.y), uvec4(1, 0, 0, 0));
}
});

namespace CGE {

CGEHistogramFilter::~CGEHistogramFilter() {}

bool CGEHistogramFilter::init() {
if (initShadersFromString(s_vshHistogram, s_fshHistogram)) {
m_program.bind();
setFormPosition(0.1f, 0.1f);
setFormSize(0.3f, 0.3f);
m_drawer.reset(TextureDrawer::create());
m_drawer->setFlipScale(1.0f, -1.0f);
m_renderTarget = std::make_unique<FrameBufferTexture>();
return true;
}

return false;
}

void CGEHistogramFilter::render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) {
auto&& sz = handler->getOutputFBOSize();
if (sz.width != m_renderTarget->width() || m_renderTarget->texture() == 0) {
m_renderTarget->bindTexture2D(sz.width, sz.height);
}
m_renderTarget->bind();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);

glFinish();

m_program.bind();
glColorMask(false, false, false, false);

glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, srcTexture);

glUniform1i(m_program.uniformLocation("inputImageTexture"), 0);

// 获取纹理尺寸,用于计算像素位置
const auto texSize = handler->getOutputFBOSize();
// 清空直方图数组
std::array<float, 256> histogram{};
// 遍历纹理像素,计算亮度直方图
std::vector<unsigned char> pixels(texSize.width * texSize.height * 4);
glReadPixels(0, 0, texSize.width, texSize.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
// glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
for (int i = 0; i < pixels.size(); i += 4) {
const auto r = pixels[i];
const auto g = pixels[i + 1];
const auto b = pixels[i + 2];
const auto lum = 0.299f * r + 0.587f * g + 0.114f * b;
histogram[static_cast<int>(lum * 255)]++;
}

// 将直方图数据传入图像数据,写入 GLSL Image 中
auto data = m_renderTarget->mapBuffer();
for (int i = 0; i < histogram.size(); i++) {
const auto height = static_cast<int>(histogram[i] * 256);
for (int j = 0; j < height; j++) {
const auto pixel = reinterpret_cast<unsigned char*>(data) + j * m_renderTarget->width() * 4 + i * 4;
pixel[0] = 255;
pixel[1] = 255;
pixel[2] = 255;
pixel[3] = 255;
}
}
m_renderTarget->unmapBuffer();

glViewport(m_position[0] * sz.width, m_position[1] * sz.height, m_size[0] * sz.width, m_size[1] * sz.height);
// 绘制直方图
m_drawer->drawTexture(m_renderTarget->texture());

glColorMask(true, true, true, true);

glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void CGEHistogramFilter::setFormPosition(float left, float top)
{
m_position = {left, top};
}

void CGEHistogramFilter::setFormSize(float width, float height)
{
m_size = {width, height};
}
}
29 changes: 29 additions & 0 deletions library/src/main/jni/cge/filters/cgeHistogramFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef _HISTOGRAMFILTER_H_
#define _HISTOGRAMFILTER_H_

#include "cgeImageFilter.h"
#include "cgeTextureUtils.h"
#include "cgeVec.h"

namespace CGE{
class CGEHistogramFilter : public CGEImageFilterInterface
{
public:
~CGEHistogramFilter() override;

void setFormPosition(float left, float top);

void setFormSize(float width, float height);

bool init() override;

void render2Texture(CGEImageHandlerInterface* handler, GLuint srcTexture, GLuint vertexBufferID) override;

protected:
std::unique_ptr<TextureDrawer> m_drawer;
std::unique_ptr<FrameBufferTexture> m_renderTarget;
Vec2f m_position;
Vec2f m_size;
};
}
#endif