Skip to content

Commit 772fb4b

Browse files
author
Kevin Welton
committed
Add IBuffer sample
1 parent f3d207e commit 772fb4b

File tree

12 files changed

+576
-0
lines changed

12 files changed

+576
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#include "pch.h"
2+
3+
namespace com = ::Windows::Storage::Streams;
4+
5+
using namespace winrt;
6+
using namespace winrt::Windows::ApplicationModel::Activation;
7+
using namespace winrt::Windows::Foundation;
8+
using namespace winrt::Windows::Graphics::Imaging;
9+
using namespace winrt::Windows::Storage;
10+
using namespace winrt::Windows::Storage::Pickers;
11+
using namespace winrt::Windows::Storage::Streams;
12+
using namespace winrt::Windows::UI;
13+
using namespace winrt::Windows::UI::Core;
14+
using namespace winrt::Windows::UI::Xaml;
15+
using namespace winrt::Windows::UI::Xaml::Controls;
16+
using namespace winrt::Windows::UI::Xaml::Media;
17+
using namespace winrt::Windows::UI::Xaml::Media::Imaging;
18+
19+
struct App : ApplicationT<App>
20+
{
21+
public:
22+
23+
// The Click and Rendering methods be default use IInspectable from winrt::ABI. They should use the version from winrt::Windows.
24+
void RenderingHandler(const IInspectable&, const IInspectable& args)
25+
{
26+
// Once the image is loaded successfully, then we can dynamically update the WritableBitmap.
27+
if (m_imageLoaded)
28+
{
29+
auto renderingArgs = args.as<IRenderingEventArgs>();
30+
31+
// Get elapsed time
32+
TimeSpan timeSpan = renderingArgs.RenderingTime();
33+
34+
// Calculate twistAngle from -180 to 180 degrees
35+
double t = (timeSpan.count() % m_cycleDuration) / (double)m_cycleDuration;
36+
double tprime = 2 * (t < 0.5 ? t : 1 - t);
37+
double twistAngle = 2 * (tprime - 0.5) * 3.14159;
38+
39+
for (int yDst = 0; yDst < m_height; yDst++)
40+
{
41+
for (int xDst = 0; xDst < m_width; xDst++)
42+
{
43+
// Calculate length of point to center and angle
44+
int xDelta = xDst - m_xCenter;
45+
int yDelta = yDst - m_yCenter;
46+
double distanceToCenter = sqrt(xDelta * xDelta +
47+
yDelta * yDelta);
48+
double angleClockwise = atan2(yDelta, xDelta);
49+
50+
// Calculation angle of rotation for twisting effect
51+
double xEllipse = m_xCenter * cos(angleClockwise);
52+
double yEllipse = m_yCenter * sin(angleClockwise);
53+
double radius = sqrt(xEllipse * xEllipse +
54+
yEllipse * yEllipse);
55+
double fraction = max(0.0, 1 - distanceToCenter / radius);
56+
double twist = fraction * twistAngle;
57+
58+
// Calculate the source pixel for each destination pixel
59+
int xSrc = (int)(m_xCenter + (xDst - m_xCenter) * cos(twist)
60+
- (yDst - m_yCenter) * sin(twist));
61+
int ySrc = (int)(m_yCenter + (xDst - m_xCenter) * sin(twist)
62+
+ (yDst - m_yCenter) * cos(twist));
63+
xSrc = max(0, min(m_width - 1, xSrc));
64+
ySrc = max(0, min(m_height - 1, ySrc));
65+
66+
// Calculate the indices
67+
int iDst = 4 * (yDst * m_width + xDst);
68+
int iSrc = 4 * (ySrc * m_width + xSrc);
69+
70+
// Transfer the pixel bytes
71+
m_destPixels[iDst++] = m_srcPixels[iSrc++];
72+
m_destPixels[iDst++] = m_srcPixels[iSrc++];
73+
m_destPixels[iDst++] = m_srcPixels[iSrc++];
74+
m_destPixels[iDst] = m_srcPixels[iSrc];
75+
}
76+
}
77+
78+
// Invalidate the bitmap
79+
m_writeableBitmap.Invalidate();
80+
}
81+
}
82+
83+
std::future<void> ClickHandler(const IInspectable&, const IInspectable&)
84+
{
85+
FileOpenPicker picker;
86+
picker.ViewMode(PickerViewMode::Thumbnail);
87+
picker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
88+
89+
auto fileTypeFilters = picker.FileTypeFilter();
90+
fileTypeFilters.Append(L".jpg");
91+
fileTypeFilters.Append(L".jpeg");
92+
fileTypeFilters.Append(L".png");
93+
94+
StorageFile selectedFile = await picker.PickSingleFileAsync();
95+
if (!selectedFile)
96+
{
97+
return;
98+
}
99+
100+
IRandomAccessStream imageStream = await selectedFile.OpenAsync(FileAccessMode::Read);
101+
BitmapDecoder decoder = await BitmapDecoder::CreateAsync(imageStream);
102+
BitmapFrame frame = await decoder.GetFrameAsync(0);
103+
104+
m_width = frame.PixelWidth();
105+
m_height = frame.PixelHeight();
106+
m_xCenter = m_width / 2;
107+
m_yCenter = m_height / 2;
108+
109+
PixelDataProvider provider = await frame.GetPixelDataAsync();
110+
m_srcPixels = provider.DetachPixelData();
111+
112+
// Manipulation of the bitmap objects must be done on the UI thread
113+
m_uiDispatcher.RunAsync(CoreDispatcherPriority::Normal, [this]() {
114+
115+
m_writeableBitmap = WriteableBitmap(m_width, m_height);
116+
m_image.Source(m_writeableBitmap);
117+
118+
IBuffer buffer = m_writeableBitmap.PixelBuffer();
119+
com_ptr<com::IBufferByteAccess> byteAccess = buffer.as<com::IBufferByteAccess>();
120+
byteAccess->Buffer(&m_destPixels);
121+
122+
m_imageLoaded = true;
123+
});
124+
}
125+
126+
void OnLaunched(LaunchActivatedEventArgs const &)
127+
{
128+
CompositionTarget::Rendering({ this, &App::RenderingHandler });
129+
130+
m_uiDispatcher = CoreWindow::GetForCurrentThread().Dispatcher();
131+
132+
StackPanel panel;
133+
panel.Orientation(Orientation::Vertical);
134+
135+
Button pickerButton;
136+
TextBlock pickerButtonText;
137+
pickerButtonText.Text(L"Choose image...");
138+
pickerButton.Content(pickerButtonText);
139+
pickerButton.Click({ this, &App::ClickHandler });
140+
141+
m_image.Height(200.0);
142+
m_image.Width(200.0);
143+
144+
auto panelContent = panel.Children();
145+
panelContent.Append(pickerButton);
146+
panelContent.Append(m_image);
147+
148+
Window window = Window::Current();
149+
window.Content(panel);
150+
window.Activate();
151+
}
152+
153+
private:
154+
CoreDispatcher m_uiDispatcher{ nullptr };
155+
Image m_image;
156+
157+
int m_width{ 0 };
158+
int m_height{ 0 };
159+
int m_xCenter{ 0 };
160+
int m_yCenter{ 0 };
161+
162+
byte* m_destPixels{ nullptr };
163+
com_array<uint8_t> m_srcPixels;
164+
WriteableBitmap m_writeableBitmap{ nullptr };
165+
166+
bool m_imageLoaded{ false };
167+
168+
static const int64_t m_cycleDuration{ 30000000 };
169+
};
170+
171+
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
172+
{
173+
Application::Start([](auto &&)
174+
{
175+
make<App>();
176+
});
177+
}
1 KB
Binary file not shown.
801 Bytes
Loading
526 Bytes
Loading
2.1 KB
Loading
429 Bytes
Loading
2.1 KB
Loading
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 14
4+
VisualStudioVersion = 14.0.25420.1
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IBuffer", "IBuffer.vcxproj", "{1F93D330-56FC-4497-BBDE-1807301B5C79}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|ARM = Debug|ARM
11+
Debug|x64 = Debug|x64
12+
Debug|x86 = Debug|x86
13+
Release|ARM = Release|ARM
14+
Release|x64 = Release|x64
15+
Release|x86 = Release|x86
16+
EndGlobalSection
17+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
18+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|ARM.ActiveCfg = Debug|ARM
19+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|ARM.Build.0 = Debug|ARM
20+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|ARM.Deploy.0 = Debug|ARM
21+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|x64.ActiveCfg = Debug|x64
22+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|x64.Build.0 = Debug|x64
23+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|x64.Deploy.0 = Debug|x64
24+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|x86.ActiveCfg = Debug|Win32
25+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|x86.Build.0 = Debug|Win32
26+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Debug|x86.Deploy.0 = Debug|Win32
27+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|ARM.ActiveCfg = Release|ARM
28+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|ARM.Build.0 = Release|ARM
29+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|ARM.Deploy.0 = Release|ARM
30+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|x64.ActiveCfg = Release|x64
31+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|x64.Build.0 = Release|x64
32+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|x64.Deploy.0 = Release|x64
33+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|x86.ActiveCfg = Release|Win32
34+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|x86.Build.0 = Release|Win32
35+
{1F93D330-56FC-4497-BBDE-1807301B5C79}.Release|x86.Deploy.0 = Release|Win32
36+
EndGlobalSection
37+
GlobalSection(SolutionProperties) = preSolution
38+
HideSolutionNode = FALSE
39+
EndGlobalSection
40+
EndGlobal

0 commit comments

Comments
 (0)