Skip to content

Commit 897120c

Browse files
committed
captured image to save as 48bit PNG
1 parent 3ee67c4 commit 897120c

File tree

6 files changed

+196
-22
lines changed

6 files changed

+196
-22
lines changed

HDR10Capture2019/HDR10Capture.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<ClInclude Include="imstb_rectpack.h" />
3333
<ClInclude Include="imstb_textedit.h" />
3434
<ClInclude Include="imstb_truetype.h" />
35+
<ClInclude Include="MLPngWriter.h" />
3536
<ClInclude Include="MLSaveSettings.h" />
3637
<ClInclude Include="Contrib\include\OpenEXR\half.h" />
3738
<ClInclude Include="Contrib\include\OpenEXR\OpenEXRConfig.h" />
@@ -57,6 +58,7 @@
5758
<ClCompile Include="Main.cpp" />
5859
<ClCompile Include="MLDX12Common.cpp" />
5960
<ClCompile Include="MLImage.cpp" />
61+
<ClCompile Include="MLPngWriter.cpp" />
6062
<ClCompile Include="MLSaveSettings.cpp" />
6163
<ClCompile Include="MLPngReader.cpp" />
6264
<ClCompile Include="MLVideoCapUser.cpp" />

HDR10Capture2019/HDR10Capture.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@
6161
<ClCompile Include="MLConverter.cpp">
6262
<Filter>Sources</Filter>
6363
</ClCompile>
64+
<ClCompile Include="MLPngWriter.cpp">
65+
<Filter>Sources</Filter>
66+
</ClCompile>
6467
</ItemGroup>
6568
<ItemGroup>
6669
<ClInclude Include="d3dx12.h">
@@ -147,6 +150,9 @@
147150
<ClInclude Include="MLConverter.h">
148151
<Filter>Headers</Filter>
149152
</ClInclude>
153+
<ClInclude Include="MLPngWriter.h">
154+
<Filter>Headers</Filter>
155+
</ClInclude>
150156
</ItemGroup>
151157
<ItemGroup>
152158
<CustomBuild Include="shaderColorConvPS.hlsl">

HDR10Capture2019/MLDX12App.cpp

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "half.h"
1010
#include "MLImage.h"
1111
#include "MLPngReader.h"
12+
#include "MLPngWriter.h"
1213
#include "MLBmpReader.h"
1314
#include "MLVideoCaptureEnumToStr.h"
1415

@@ -1212,10 +1213,11 @@ MLDX12App::ShowSettingsWindow(void) {
12121213
}
12131214

12141215
void
1215-
MLDX12App::ShowFileReadWindow(void) {
1216-
ImGui::Begin("File Read");
1216+
MLDX12App::ShowImageFileRWWindow(void) {
1217+
int hr = S_OK;
1218+
ImGui::Begin("File Read / Write");
12171219

1218-
if (ImGui::BeginPopupModal("ErrorFileReadPopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
1220+
if (ImGui::BeginPopupModal("ErrorImageFileRWPopup", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
12191221
ImGui::Text(mErrorFileReadMsg);
12201222
if (ImGui::Button("OK ## EFM", ImVec2(120, 0))) {
12211223
ImGui::CloseCurrentPopup();
@@ -1224,24 +1226,39 @@ MLDX12App::ShowFileReadWindow(void) {
12241226
ImGui::EndPopup();
12251227
}
12261228

1227-
ImGui::InputText("Image Filename to Read", mImgFilePath, sizeof mImgFilePath - 1);
1228-
if (ImGui::Button("Open ##RF0")) {
1229-
mMutex.lock();
1230-
int rv = MLBmpRead(mImgFilePath, mShowImg);
1231-
if (rv == 1) {
1232-
// ファイルは存在するがBMPではなかった場合。
1233-
rv = MLPngRead(mImgFilePath, mShowImg);
1234-
if (rv == 1) {
1235-
// ファイルは存在するがPNGではなかった場合。
1236-
rv = MLExrRead(mImgFilePath, mShowImg);
1229+
if (mState == S_Capturing) {
1230+
// キャプチャー中。
1231+
ImGui::InputText("PNG Image Filename to Write", mImgFilePath, sizeof mImgFilePath - 1);
1232+
if (ImGui::Button("Write PNG ##RF0")) {
1233+
mMutex.lock();
1234+
hr = MLPngWrite(mImgFilePath, mShowImg);
1235+
mMutex.unlock();
1236+
1237+
if (FAILED(hr)) {
1238+
sprintf_s(mErrorFileReadMsg, "Write PNG Image Failed.\nFile Write error : %s", mImgFilePath);
1239+
ImGui::OpenPopup("ErrorImageFileRWPopup");
12371240
}
12381241
}
1239-
mMutex.unlock();
1240-
if (rv < 0) {
1241-
sprintf_s(mErrorFileReadMsg, "Read Image Failed.\nFile open error : %s", mImgFilePath);
1242-
ImGui::OpenPopup("ErrorFileReadPopup");
1243-
} else {
1244-
mState = S_ImageViewing;
1242+
} else {
1243+
ImGui::InputText("Image Filename to Read", mImgFilePath, sizeof mImgFilePath - 1);
1244+
if (ImGui::Button("Read ##RF0")) {
1245+
mMutex.lock();
1246+
hr = MLBmpRead(mImgFilePath, mShowImg);
1247+
if (hr == 1) {
1248+
// ファイルは存在するがBMPではなかった場合。
1249+
hr = MLPngRead(mImgFilePath, mShowImg);
1250+
if (hr == 1) {
1251+
// ファイルは存在するがPNGではなかった場合。
1252+
hr = MLExrRead(mImgFilePath, mShowImg);
1253+
}
1254+
}
1255+
mMutex.unlock();
1256+
if (hr < 0) {
1257+
sprintf_s(mErrorFileReadMsg, "Read Image Failed.\nFile open error : %s", mImgFilePath);
1258+
ImGui::OpenPopup("ErrorImageFileRWPopup");
1259+
} else {
1260+
mState = S_ImageViewing;
1261+
}
12451262
}
12461263
}
12471264

@@ -1252,9 +1269,10 @@ void
12521269
MLDX12App::ImGuiCommands(void) {
12531270
if (mShowImGui) {
12541271
//ImGui::ShowDemoWindow();
1255-
ShowSettingsWindow();
1256-
ShowFileReadWindow();
1272+
// 順番が重要。キャプチャー画像を保存するため。
12571273
ShowVideoCaptureWindow();
1274+
ShowImageFileRWWindow();
1275+
ShowSettingsWindow();
12581276
}
12591277

12601278
ImGui::Render();

HDR10Capture2019/MLDX12App.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class MLDX12App : public MLDX12 {
163163
void DrawFullscreenTexture(TextureEnum texId, MLImage & drawMode);
164164

165165
void ShowSettingsWindow(void);
166-
void ShowFileReadWindow(void);
166+
void ShowImageFileRWWindow(void);
167167

168168
void UploadImgToGpu(MLImage &ci, ComPtr<ID3D12Resource> &tex, int texIdx);
169169
void AdjustFullScreenQuadAspectRatio(int w, int h);

HDR10Capture2019/MLPngWriter.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include "MLPngWriter.h"
2+
#include <png.h>
3+
#include <stdio.h>
4+
#include <Windows.h>
5+
#include <half.h>
6+
#include <assert.h>
7+
#include <stdint.h>
8+
9+
static uint16_t
10+
HtoNS(uint16_t v)
11+
{
12+
return ((v & 0xff) << 8)
13+
| ((v >> 8) & 0xff);
14+
}
15+
16+
/// <summary>
17+
/// PNGファイルを書き込む。
18+
/// </summary>
19+
/// <returns>0:成功。負の数:失敗。</returns>
20+
int MLPngWrite(const char* pngFilePath, const MLImage& img)
21+
{
22+
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
23+
if (!png) {
24+
printf("Error: png_create_write_struct failed.\n");
25+
return E_FAIL;
26+
}
27+
png_infop info = png_create_info_struct(png);
28+
if (!info) {
29+
png_destroy_write_struct(&png, &info);
30+
printf("Error: png_create_info_struct failed.\n");
31+
return E_FAIL;
32+
}
33+
34+
// 書き込む画像データを準備します。
35+
uint8_t* data = nullptr;
36+
png_bytepp rows = nullptr;
37+
38+
int bitDepth = 8;
39+
if (8 == img.originalBitDepth) {
40+
// R8G8B8A8
41+
bitDepth = 8;
42+
switch (img.bitFormat) {
43+
case MLImage::BFT_UIntR8G8B8A8:
44+
break;
45+
default:
46+
// 作ってない。
47+
return E_NOTIMPL;
48+
}
49+
50+
rows = (png_bytepp)png_malloc(png, img.height * sizeof(png_bytep));
51+
data = new uint8_t[(int64_t)img.width * img.height * 3 * bitDepth / 8];
52+
for (int y = 0; y < img.height; ++y) {
53+
rows[y] = (png_bytep)(data + (0 + y * img.width) * 3);
54+
for (int x = 0; x < img.width; ++x) {
55+
const int readPos = (x + y * img.width) * 4;
56+
57+
const uint8_t r = img.data[readPos + 0];
58+
const uint8_t g = img.data[readPos + 1];
59+
const uint8_t b = img.data[readPos + 2];
60+
61+
const int writePos = (x + y * img.width) * 3;
62+
data[writePos + 0] = r;
63+
data[writePos + 1] = g;
64+
data[writePos + 2] = b;
65+
}
66+
}
67+
} else {
68+
// R10G10B10A2
69+
bitDepth = 16;
70+
switch (img.bitFormat) {
71+
case MLImage::BFT_UIntR10G10B10A2:
72+
break;
73+
default:
74+
// 作ってない。
75+
return E_NOTIMPL;
76+
}
77+
78+
uint32_t* from32 = (uint32_t*)img.data;
79+
rows = (png_bytepp)png_malloc(png, img.height * sizeof(png_bytep));
80+
data = new uint8_t[(int64_t)img.width * img.height * 3 * bitDepth / 8];
81+
uint16_t* data16 = (uint16_t*)data;
82+
for (int y = 0; y < img.height; ++y) {
83+
rows[y] = (uint8_t*)&data16[(0 + y * img.width) * 3];
84+
for (int x = 0; x < img.width; ++x) {
85+
const int readPos = (x + y * img.width);
86+
const uint32_t v = from32[readPos];
87+
// v: AABBBBBB BBBBGGGG GGGGGGRR RRRRRRRR
88+
89+
uint16_t r = (v << 6) & 0xffc0;
90+
uint16_t g = (v >> 4) & 0xffc0;
91+
uint16_t b = (v >> 14) & 0xffc0;
92+
93+
const int writePos = (x + y * img.width) * 3;
94+
data16[writePos + 0] = HtoNS(r);
95+
data16[writePos + 1] = HtoNS(g);
96+
data16[writePos + 2] = HtoNS(b);
97+
}
98+
}
99+
}
100+
101+
// ここでファイルを書き込みオープン。
102+
FILE* fp = nullptr;
103+
int ercd = fopen_s(&fp, pngFilePath, "wb");
104+
if (0 != ercd || !fp) {
105+
printf("Error: PngWrite failed. %s\n", pngFilePath);
106+
107+
png_free(png, rows);
108+
rows = nullptr;
109+
110+
png_destroy_write_struct(&png, &info);
111+
112+
delete[] data;
113+
return E_FAIL;
114+
}
115+
116+
png_init_io(png, fp);
117+
118+
png_set_IHDR(png, info, img.width, img.height, bitDepth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
119+
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
120+
png_write_info(png, info);
121+
png_set_packing(png);
122+
123+
png_write_image(png, rows);
124+
png_write_end(png, info);
125+
126+
png_free(png, rows);
127+
rows = nullptr;
128+
129+
png_destroy_write_struct(&png, &info);
130+
131+
fclose(fp);
132+
133+
return S_OK;
134+
}
135+
136+
137+
138+

HDR10Capture2019/MLPngWriter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#include "MLImage.h"
4+
5+
/// <summary>
6+
/// PNGファイルを書き込む。
7+
/// </summary>
8+
/// <returns>0:成功。負の数:失敗。</returns>
9+
int MLPngWrite(const char* pngFilePath, const MLImage& img);
10+

0 commit comments

Comments
 (0)