Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
imjiangjun
pbrt-v4
提交
cacd50aa
P
pbrt-v4
项目概览
imjiangjun
/
pbrt-v4
11 个月 前同步成功
通知
7
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
pbrt-v4
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
cacd50aa
编写于
4月 18, 2022
作者:
M
Matt Pharr
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for qoi format images
https://qoiformat.org
上级
60e95c27
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
166 addition
and
0 deletion
+166
-0
.gitmodules
.gitmodules
+3
-0
CMakeLists.txt
CMakeLists.txt
+2
-0
src/ext/CMakeLists.txt
src/ext/CMakeLists.txt
+6
-0
src/ext/qoi
src/ext/qoi
+1
-0
src/pbrt/util/image.cpp
src/pbrt/util/image.cpp
+89
-0
src/pbrt/util/image.h
src/pbrt/util/image.h
+1
-0
src/pbrt/util/image_test.cpp
src/pbrt/util/image_test.cpp
+64
-0
未找到文件。
.gitmodules
浏览文件 @
cacd50aa
...
...
@@ -30,3 +30,6 @@
[submodule "src/ext/utf8proc"]
path = src/ext/utf8proc
url = https://github.com/JuliaStrings/utf8proc.git
[submodule "src/ext/qoi"]
path = src/ext/qoi
url = https://github.com/phoboslab/qoi.git
CMakeLists.txt
浏览文件 @
cacd50aa
...
...
@@ -64,6 +64,7 @@ check_ext ("double-conversion" "double-conversion/cmake" cc1f75a114aca8d2af69f73
check_ext
(
"filesystem"
"filesystem/filesystem"
c5f9de30142453eb3c6fe991e82dfc2583373116
)
check_ext
(
"libdeflate"
"libdeflate/common"
1fd0bea6ca2073c68493632dafc4b1ddda1bcbc3
)
check_ext
(
"lodepng"
"lodepng/examples"
8c6a9e30576f07bf470ad6f09458a2dcd7a6a84a
)
check_ext
(
"qoi"
"qoi"
028c75fd26e5e0758c7c711216c00404994c1ad3
)
check_ext
(
"stb"
"stb/tools"
af1a5bc352164740c1cc1354942b1c6b72eacb8a
)
check_ext
(
"utf8proc"
"utf8proc/bench"
2484e2ed5e1d9c19edcccf392a7d9920ad90dfaf
)
check_ext
(
"zlib"
"zlib/doc"
54d591eabf9fe0e84c725638f8d5d8d202a093fa
)
...
...
@@ -829,6 +830,7 @@ target_include_directories (pbrt_lib PUBLIC
src
src/ext
${
STB_INCLUDE
}
${
QOI_INCLUDE
}
${
OPENEXR_INCLUDE
}
${
ZLIB_INCLUDE_DIRS
}
${
LIBDEFLATE_INCLUDE_DIRS
}
...
...
src/ext/CMakeLists.txt
浏览文件 @
cacd50aa
...
...
@@ -146,3 +146,9 @@ set_property (TARGET flip_lib PROPERTY FOLDER "ext")
set
(
UTF8PROC_INCLUDE
${
CMAKE_CURRENT_SOURCE_DIR
}
/utf8proc PARENT_SCOPE
)
add_subdirectory
(
utf8proc
)
###########################################################################
# qoi
set
(
QOI_INCLUDE
${
CMAKE_CURRENT_SOURCE_DIR
}
/qoi PARENT_SCOPE
)
qoi
@
028c75fd
Subproject commit 028c75fd26e5e0758c7c711216c00404994c1ad3
src/pbrt/util/image.cpp
浏览文件 @
cacd50aa
...
...
@@ -46,6 +46,10 @@
#define STBI_WINDOWS_UTF8
#include <stb/stb_image.h>
#define QOI_NO_STDIO
#define QOI_IMPLEMENTATION
#include <qoi/qoi.h>
namespace
pbrt
{
std
::
string
ToString
(
PixelFormat
format
)
{
...
...
@@ -867,6 +871,7 @@ static ImageAndMetadata ReadPNG(const std::string &name, Allocator alloc,
ColorEncoding
encoding
);
static
ImageAndMetadata
ReadPFM
(
const
std
::
string
&
filename
,
Allocator
alloc
);
static
ImageAndMetadata
ReadHDR
(
const
std
::
string
&
filename
,
Allocator
alloc
);
static
ImageAndMetadata
ReadQOI
(
const
std
::
string
&
filename
,
Allocator
alloc
);
// ImageIO Function Definitions
ImageAndMetadata
Image
::
Read
(
std
::
string
name
,
Allocator
alloc
,
ColorEncoding
encoding
)
{
...
...
@@ -878,6 +883,8 @@ ImageAndMetadata Image::Read(std::string name, Allocator alloc, ColorEncoding en
return
ReadPFM
(
name
,
alloc
);
else
if
(
HasExtension
(
name
,
"hdr"
))
return
ReadHDR
(
name
,
alloc
);
else
if
(
HasExtension
(
name
,
"qoi"
))
return
ReadQOI
(
name
,
alloc
);
else
{
int
x
,
y
,
n
;
unsigned
char
*
data
=
stbi_load
(
name
.
c_str
(),
&
x
,
&
y
,
&
n
,
0
);
...
...
@@ -1001,6 +1008,8 @@ bool Image::Write(std::string name, const ImageMetadata &metadata) const {
return
outImage
.
WritePFM
(
name
,
outMetadata
);
else
if
(
HasExtension
(
name
,
"png"
))
return
outImage
.
WritePNG
(
name
,
outMetadata
);
else
if
(
HasExtension
(
name
,
"qoi"
))
return
outImage
.
WriteQOI
(
name
,
outMetadata
);
else
{
Error
(
"%s: no support for writing images with this extension"
,
name
);
return
false
;
...
...
@@ -1483,6 +1492,58 @@ bool Image::WritePNG(const std::string &filename, const ImageMetadata &metadata)
return
true
;
}
bool
Image
::
WriteQOI
(
const
std
::
string
&
filename
,
const
ImageMetadata
&
metadata
)
const
{
Image
image
=
*
this
;
void
*
qoiPixels
=
nullptr
;
int
qoiSize
=
0
;
qoi_desc
desc
;
desc
.
width
=
resolution
.
x
;
desc
.
height
=
resolution
.
y
;
desc
.
channels
=
NChannels
();
if
(
Encoding
()
&&
!
Encoding
().
Is
<
LinearColorEncoding
>
()
&&
!
Encoding
().
Is
<
sRGBColorEncoding
>
())
{
Error
(
"%s: only linear and sRGB encodings are supported by QOI."
,
Encoding
().
ToString
());
//filename);
return
false
;
}
desc
.
colorspace
=
Encoding
().
Is
<
LinearColorEncoding
>
()
?
QOI_LINEAR
:
QOI_SRGB
;
if
(
NChannels
()
==
4
)
{
// Try to order it as QOI expects. Though continue on if we don't
// find these particular channel names.a
ImageChannelDesc
desc
=
GetChannelDesc
({
"R"
,
"G"
,
"B"
,
"A"
});
if
(
desc
)
image
=
SelectChannels
(
desc
);
}
else
if
(
NChannels
()
==
3
)
{
// Similarly try to get the channels in order..
ImageChannelDesc
desc
=
GetChannelDesc
({
"R"
,
"G"
,
"B"
});
if
(
desc
)
image
=
SelectChannels
(
desc
);
}
else
{
Error
(
"%s: only 3 and 4 channel images are supported for QOI"
,
filename
);
return
false
;
}
if
(
format
==
PixelFormat
::
U256
)
qoiPixels
=
qoi_encode
(
image
.
RawPointer
({
0
,
0
}),
&
desc
,
&
qoiSize
);
else
{
int
nOutOfGamut
=
0
;
std
::
unique_ptr
<
uint8_t
[]
>
rgba8
=
QuantizePixelsToU256
(
&
nOutOfGamut
);
if
(
nOutOfGamut
>
0
)
Warning
(
"%s: %d out of gamut pixel channels clamped to [0,1]."
,
filename
,
nOutOfGamut
);
qoiPixels
=
qoi_encode
(
rgba8
.
get
(),
&
desc
,
&
qoiSize
);
}
bool
success
=
WriteFileContents
(
filename
,
std
::
string
((
const
char
*
)
qoiPixels
,
qoiSize
));
if
(
!
success
)
Error
(
"%s: error writing QOI file."
,
filename
);
free
(
qoiPixels
);
return
success
;
}
///////////////////////////////////////////////////////////////////////////
// PFM Function Definitions
...
...
@@ -1660,6 +1721,34 @@ static ImageAndMetadata ReadHDR(const std::string &filename, Allocator alloc) {
}
}
static
ImageAndMetadata
ReadQOI
(
const
std
::
string
&
filename
,
Allocator
alloc
)
{
std
::
string
contents
=
ReadFileContents
(
filename
);
qoi_desc
desc
;
void
*
pixels
=
qoi_decode
(
contents
.
data
(),
contents
.
size
(),
&
desc
,
0
/* channels */
);
CHECK
(
pixels
!=
nullptr
);
// qoi failure
ImageMetadata
metadata
;
metadata
.
colorSpace
=
RGBColorSpace
::
sRGB
;
std
::
vector
<
std
::
string
>
channelNames
{
"R"
,
"G"
,
"B"
};
if
(
desc
.
channels
==
4
)
channelNames
.
push_back
(
"A"
);
else
CHECK_EQ
(
3
,
desc
.
channels
);
CHECK
(
desc
.
colorspace
==
QOI_SRGB
||
desc
.
colorspace
==
QOI_LINEAR
);
ColorEncoding
encoding
=
(
desc
.
colorspace
==
QOI_SRGB
)
?
ColorEncoding
::
sRGB
:
ColorEncoding
::
Linear
;
Image
image
(
PixelFormat
::
U256
,
Point2i
(
desc
.
width
,
desc
.
height
),
channelNames
,
encoding
,
alloc
);
std
::
memcpy
(
image
.
RawPointer
({
0
,
0
}),
pixels
,
desc
.
width
*
desc
.
height
*
desc
.
channels
);
free
(
pixels
);
return
ImageAndMetadata
{
image
,
metadata
};
}
bool
Image
::
WritePFM
(
const
std
::
string
&
filename
,
const
ImageMetadata
&
metadata
)
const
{
FILE
*
fp
=
FOpenWrite
(
filename
);
if
(
!
fp
)
{
...
...
src/pbrt/util/image.h
浏览文件 @
cacd50aa
...
...
@@ -407,6 +407,7 @@ class Image {
bool
WriteEXR
(
const
std
::
string
&
name
,
const
ImageMetadata
&
metadata
)
const
;
bool
WritePFM
(
const
std
::
string
&
name
,
const
ImageMetadata
&
metadata
)
const
;
bool
WritePNG
(
const
std
::
string
&
name
,
const
ImageMetadata
&
metadata
)
const
;
bool
WriteQOI
(
const
std
::
string
&
name
,
const
ImageMetadata
&
metadata
)
const
;
std
::
unique_ptr
<
uint8_t
[]
>
QuantizePixelsToU256
(
int
*
nOutOfGamut
)
const
;
...
...
src/pbrt/util/image_test.cpp
浏览文件 @
cacd50aa
...
...
@@ -546,6 +546,66 @@ TEST(Image, PngEmojiIO) {
EXPECT_TRUE
(
RemoveFile
(
filename
.
c_str
()));
}
TEST
(
Image
,
QoiRgbIO
)
{
Point2i
res
(
11
,
50
);
pstd
::
vector
<
uint8_t
>
rgbPixels
=
GetU8Pixels
(
res
,
3
);
Image
image
(
rgbPixels
,
res
,
{
"R"
,
"G"
,
"B"
},
ColorEncoding
::
sRGB
);
EXPECT_TRUE
(
image
.
Write
(
"test.qoi"
));
ImageAndMetadata
read
=
Image
::
Read
(
"test.qoi"
);
EXPECT_EQ
(
image
.
Resolution
(),
read
.
image
.
Resolution
());
EXPECT_EQ
(
read
.
image
.
Format
(),
PixelFormat
::
U256
);
ASSERT_TRUE
(
read
.
image
.
Encoding
()
!=
nullptr
);
// EXPECT_EQ(*read.image.Encoding(), *ColorEncoding::sRGB);
ASSERT_TRUE
((
bool
)
read
.
metadata
.
colorSpace
);
ASSERT_TRUE
(
*
read
.
metadata
.
colorSpace
!=
nullptr
);
EXPECT_EQ
(
*
RGBColorSpace
::
sRGB
,
*
read
.
metadata
.
GetColorSpace
());
for
(
int
y
=
0
;
y
<
res
[
1
];
++
y
)
for
(
int
x
=
0
;
x
<
res
[
0
];
++
x
)
for
(
int
c
=
0
;
c
<
3
;
++
c
)
{
EXPECT_EQ
(
SRGB8ToLinear
(
rgbPixels
[
c
+
3
*
(
y
*
res
[
0
]
+
x
)]),
image
.
GetChannel
({
x
,
y
},
c
))
<<
" x "
<<
x
<<
", y "
<<
y
<<
", c "
<<
c
<<
", orig "
<<
rgbPixels
[
3
*
y
*
res
[
0
]
+
3
*
x
+
c
];
}
EXPECT_TRUE
(
RemoveFile
(
"test.qoi"
));
}
TEST
(
Image
,
QoiRgbaIO
)
{
Point2i
res
(
11
,
50
);
pstd
::
vector
<
uint8_t
>
rgbPixels
=
GetU8Pixels
(
res
,
4
);
// Intentionally out of normal order...
Image
image
(
rgbPixels
,
res
,
{
"A"
,
"R"
,
"G"
,
"B"
},
ColorEncoding
::
sRGB
);
EXPECT_TRUE
(
image
.
Write
(
"test-rgba.qoi"
));
ImageAndMetadata
read
=
Image
::
Read
(
"test-rgba.qoi"
);
EXPECT_EQ
(
image
.
Resolution
(),
read
.
image
.
Resolution
());
EXPECT_EQ
(
read
.
image
.
Format
(),
PixelFormat
::
U256
);
ASSERT_TRUE
(
read
.
image
.
Encoding
()
!=
nullptr
);
// EXPECT_EQ(*read.image.Encoding(), *ColorEncoding::sRGB);
ASSERT_TRUE
((
bool
)
read
.
metadata
.
colorSpace
);
ASSERT_TRUE
(
*
read
.
metadata
.
colorSpace
!=
nullptr
);
EXPECT_EQ
(
*
RGBColorSpace
::
sRGB
,
*
read
.
metadata
.
GetColorSpace
());
ImageChannelDesc
desc
=
image
.
GetChannelDesc
({
"A"
,
"R"
,
"G"
,
"B"
});
ASSERT_TRUE
((
bool
)
desc
);
for
(
int
y
=
0
;
y
<
res
[
1
];
++
y
)
for
(
int
x
=
0
;
x
<
res
[
0
];
++
x
)
{
ImageChannelValues
v
=
image
.
GetChannels
({
x
,
y
},
desc
);
for
(
int
c
=
0
;
c
<
4
;
++
c
)
EXPECT_EQ
(
SRGB8ToLinear
(
rgbPixels
[
c
+
4
*
(
y
*
res
[
0
]
+
x
)]),
v
[
c
])
<<
" x "
<<
x
<<
", y "
<<
y
<<
", c "
<<
c
<<
", orig "
<<
rgbPixels
[
c
+
4
*
(
y
*
res
[
0
]
+
x
)];
}
EXPECT_TRUE
(
RemoveFile
(
"test-rgba.qoi"
));
}
TEST
(
Image
,
SampleSimple
)
{
pstd
::
vector
<
float
>
texels
=
{
Float
(
0
),
Float
(
1
),
Float
(
0
),
Float
(
0
)};
Image
zeroOne
(
texels
,
{
2
,
2
},
{
"Y"
});
...
...
@@ -751,3 +811,7 @@ TEST(ImageIO, RoundTripPFM) {
TEST
(
ImageIO
,
RoundTripPNG
)
{
TestRoundTrip
(
"out.png"
);
}
TEST
(
ImageIO
,
RoundTripQOI
)
{
TestRoundTrip
(
"out.qoi"
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录