Skip to content

Commit

Permalink
Merge pull request #1337 from zenustech/png-16
Browse files Browse the repository at this point in the history
Read Png 16
  • Loading branch information
legobadman authored Aug 9, 2023
2 parents e2fda3d + baf1eea commit a24ccd8
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 12 deletions.
3 changes: 3 additions & 0 deletions projects/Alembic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ else()
target_include_directories(zeno PRIVATE Alembic/openexr/Imath/src/Imath)
target_include_directories(zeno PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/Alembic/openexr/Imath/config)
endif()

find_package(PNG REQUIRED)
target_link_libraries(zeno PRIVATE PNG::PNG)
130 changes: 130 additions & 0 deletions projects/Alembic/png16.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//
// Created by zh on 2023/7/31.
//
#include <zeno/zeno.h>
#include <zeno/types/PrimitiveObject.h>
#include <zeno/types/NumericObject.h>
#include <zeno/types/UserData.h>
#include <stdexcept>
#include <filesystem>
#include <zeno/utils/log.h>
#include <zeno/utils/image_proc.h>

#include <png.h>
#include <cstdio>
#include <vector>

static std::shared_ptr<zeno::PrimitiveObject> read_png(const char* file_path) {
auto img = std::make_shared<zeno::PrimitiveObject>();
FILE* file = fopen(file_path, "rb");
if (!file) {
zeno::log_error("Error: File not found: {}", file_path);
return img;
}

png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr) {
fclose(file);
zeno::log_error("Error: png_create_read_struct failed.");
return img;
}

png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
fclose(file);
zeno::log_error("Error: png_create_info_struct failed.");
return img;
}

if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
fclose(file);
zeno::log_error("Error: Error during png_read_png.");
return img;
}

png_init_io(png_ptr, file);
png_set_sig_bytes(png_ptr, 0);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);

int width = png_get_image_width(png_ptr, info_ptr);
int height = png_get_image_height(png_ptr, info_ptr);

int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
int channels = png_get_channels(png_ptr, info_ptr);

png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);
std::vector<zeno::vec3f> image_data;
image_data.reserve(width * height);

for (int y = 0; y < height; y++) {
png_bytep row = row_pointers[y];
for (int x = 0; x < width; x++) {
zeno::vec3f color;
if (bit_depth == 16) {
if (channels == 1) {
uint16_t value = (row[x * 2] << 8) | row[x * 2 + 1];
float normalized_value = float(value) / 65535.0f;
color = zeno::vec3f(normalized_value);
} else if (channels == 3) {
uint16_t r = (row[x * 6] << 8) | row[x * 6 + 1];
uint16_t g = (row[x * 6 + 2] << 8) | row[x * 6 + 3];
uint16_t b = (row[x * 6 + 4] << 8) | row[x * 6 + 5];

color[0] = float(r) / 65535.0f;
color[1] = float(g) / 65535.0f;
color[2] = float(b) / 65535.0f;
}
} else if (bit_depth == 8) {
if (channels == 1) {
uint8_t value = row[x];
float normalized_value = float(value) / 255.0f;
color = zeno::vec3f(normalized_value);
} else if (channels == 3) {
uint8_t r = row[x * 3];
uint8_t g = row[x * 3 + 1];
uint8_t b = row[x * 3 + 2];

color[0] = float(r) / 255.0f;
color[1] = float(g) / 255.0f;
color[2] = float(b) / 255.0f;
}
}

image_data.push_back(color);
}
}

png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
fclose(file);
zeno::image_flip_vertical(image_data.data(), width, height);
img->verts.values = image_data;
img->userData().set2("isImage", 1);
img->userData().set2("w", width);
img->userData().set2("h", height);
img->userData().set2("bit_depth", bit_depth);
img->userData().set2("channels", channels);
return img;
}

namespace zeno {
struct ReadPNG16 : INode {//todo: select custom color space
virtual void apply() override {
auto path = get_input2<std::string>("path");
path = std::filesystem::u8path(path).string();
auto img = read_png(path.c_str());
set_output("image", img);
}
};
ZENDEFNODE(ReadPNG16, {
{
{"readpath", "path"},
},
{
{"PrimitiveObject", "image"},
},
{},
{"comp"},
});
}
10 changes: 10 additions & 0 deletions zeno/include/zeno/utils/image_proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
#include <zeno/utils/vec.h>

namespace zeno {
template<typename T>
void image_flip_vertical(T *v, int w, int h) {
for (auto j = 0; j < h / 2; j++) {
for (auto i = 0; i < w; i++) {
auto index1 = i + j * w;
auto index2 = i + (h - j - 1) * w;
std::swap(v[index1], v[index2]);
}
}
}
ZENO_API std::vector<vec3f> float_gaussian_blur(const vec3f *data, int w, int h);
}

Expand Down
12 changes: 0 additions & 12 deletions zeno/src/nodes/prim/UVProjectFromPlane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#define STB_IMAGE_WRITE_STATIC
#include <tinygltf/stb_image_write.h>
#include <vector>
#include <zeno/types/HeatmapObject.h>

static const float eps = 0.0001f;

Expand Down Expand Up @@ -408,17 +407,6 @@ ZENDEFNODE(ReadImageFile, {
{"comp"},
});

template<typename T>
void image_flip_vertical(T *v, int w, int h) {
for (auto j = 0; j < h / 2; j++) {
for (auto i = 0; i < w; i++) {
auto index1 = i + j * w;
auto index2 = i + (h - j - 1) * w;
std::swap(v[index1], v[index2]);
}
}
}

struct ImageFlipVertical : INode {
virtual void apply() override {
auto image = get_input<PrimitiveObject>("image");
Expand Down
22 changes: 22 additions & 0 deletions zenovis/xinxinoptix/OptiXStuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include <filesystem>
#include "ies/ies_loader.h"
#include "zeno/utils/fileio.h"
#include "zeno/extra/TempNode.h"
#include "zeno/types/PrimitiveObject.h"
#include <cudaMemMarco.hpp>

static void context_log_cb( unsigned int level, const char* tag, const char* message, void* /*cbdata */ )
Expand Down Expand Up @@ -691,6 +693,26 @@ inline void addTexture(std::string path)
auto img = IES2HDR(path);
g_tex[path] = makeCudaTexture(img.data(), 256, 1, 3);
}
else if (zeno::getSession().nodeClasses.count("ReadPNG16") > 0 && zeno::ends_with(path, ".png", false)) {
auto outs = zeno::TempNodeSimpleCaller("ReadPNG16")
.set2("path", path)
.call();

// Create nodes
auto img = outs.get<zeno::PrimitiveObject>("image");
if (img->verts.size() == 0) {
g_tex[path] = std::make_shared<cuTexture>();
return;
}
int nx = std::max(img->userData().get2<int>("w"), 1);
int ny = std::max(img->userData().get2<int>("h"), 1);
if(sky_tex.value() == path)//if this is a loading of a sky texture
{
calc_sky_cdf_map(nx, ny, 3, (float *)img->verts.data());
}

g_tex[path] = makeCudaTexture((float *)img->verts.data(), nx, ny, 3);
}
else if (stbi_is_hdr(native_path.c_str())) {
float *img = stbi_loadf(native_path.c_str(), &nx, &ny, &nc, 0);
if(!img){
Expand Down

0 comments on commit a24ccd8

Please sign in to comment.