mirror of
https://github.com/celisej567/cool-source-archive.git
synced 2025-12-31 17:48:37 +03:00
console command feature restored
used in dev i guess, restored sending command ability, no screenshot tho
This commit is contained in:
122
engine/ccs.cpp
122
engine/ccs.cpp
@@ -8,19 +8,19 @@
|
||||
|
||||
#include "host_state.h"
|
||||
|
||||
//#define CON_COMMAND_SERVER_SUPPORT
|
||||
#define CON_COMMAND_SERVER_SUPPORT
|
||||
|
||||
#include "tier2/tier2.h"
|
||||
#include "materialsystem/imaterialsystemhardwareconfig.h"
|
||||
|
||||
#ifdef CON_COMMAND_SERVER_SUPPORT
|
||||
#include <algorithm>
|
||||
#include "socketlib/socketlib.h"
|
||||
#include "../public/socketlib/socketlib.h"
|
||||
#define MINIZ_NO_ARCHIVE_APIS
|
||||
#include "../../thirdparty/miniz/miniz.c"
|
||||
#include "../../thirdparty/miniz/simple_bitmap.h"
|
||||
#include <WinUser.h>
|
||||
#define STBI_NO_STDIO
|
||||
#include "../../thirdparty/stb_image/stb_image.c"
|
||||
//#include "../../thirdparty/stb_image/ml_stb_image.c"
|
||||
#include "ivideomode.h"
|
||||
#endif
|
||||
|
||||
@@ -101,9 +101,9 @@ public:
|
||||
|
||||
void close(void);
|
||||
|
||||
const simple_bgr_bitmap& frameBuffer(void) const { return m_frame_buffer; }
|
||||
const int& frameBuffer(void) const { return m_frame_buffer; }
|
||||
|
||||
simple_bgr_bitmap& frameBuffer(void) { return m_frame_buffer; }
|
||||
int& frameBuffer(void) { return m_frame_buffer; }
|
||||
|
||||
private:
|
||||
int m_width, m_height;
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
char m_bitmap_info[16 + sizeof(BITMAPINFO)];
|
||||
BITMAPINFO* m_pBitmap_hdr;
|
||||
HDC m_windowHDC;
|
||||
simple_bgr_bitmap m_frame_buffer;
|
||||
int m_frame_buffer;
|
||||
static frame_buf_window* m_pCur_app;
|
||||
|
||||
user_window_proc_ptr_t m_pWindow_proc;
|
||||
@@ -179,7 +179,7 @@ void frame_buf_window::update(void)
|
||||
|
||||
void frame_buf_window::close(void)
|
||||
{
|
||||
m_frame_buffer.clear();
|
||||
//m_frame_buffer.clear();
|
||||
|
||||
if (m_window)
|
||||
{
|
||||
@@ -192,41 +192,7 @@ void frame_buf_window::close(void)
|
||||
|
||||
void frame_buf_window::create_window(const char* pTitle)
|
||||
{
|
||||
memset( &m_window_class, 0, sizeof( m_window_class ) );
|
||||
m_window_class.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
|
||||
m_window_class.lpfnWndProc = static_window_proc;
|
||||
m_window_class.cbWndExtra = sizeof(DWORD);
|
||||
m_window_class.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
m_window_class.lpszClassName = pTitle;
|
||||
m_window_class.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); //GetStockObject(NULL_BRUSH);
|
||||
RegisterClass(&m_window_class);
|
||||
|
||||
RECT rect;
|
||||
rect.left = rect.top = 0;
|
||||
rect.right = m_width * m_scale_x;
|
||||
rect.bottom = m_height * m_scale_y;
|
||||
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, 0);
|
||||
rect.right -= rect.left;
|
||||
rect.bottom -= rect.top;
|
||||
|
||||
m_orig_x = (GetSystemMetrics(SM_CXSCREEN) - rect.right) / 2;
|
||||
m_orig_y = (GetSystemMetrics(SM_CYSCREEN) - rect.bottom) / 2;
|
||||
|
||||
m_orig_width = rect.right;
|
||||
m_orig_height = rect.bottom;
|
||||
|
||||
m_pCur_app = this;
|
||||
|
||||
m_window = CreateWindowEx(
|
||||
0, pTitle, pTitle,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
m_orig_x, m_orig_y, rect.right, rect.bottom, 0, 0, 0, 0);
|
||||
|
||||
SetWindowLong(m_window, 0, reinterpret_cast<LONG>(this));
|
||||
|
||||
m_pCur_app = NULL;
|
||||
|
||||
ShowWindow(m_window, SW_NORMAL);
|
||||
|
||||
}
|
||||
|
||||
void frame_buf_window::create_bitmap(void)
|
||||
@@ -247,8 +213,8 @@ void frame_buf_window::create_bitmap(void)
|
||||
|
||||
m_windowHDC = GetDC(m_window);
|
||||
|
||||
m_frame_buffer.init( m_width, m_height );
|
||||
m_frame_buffer.cls( 30, 30, 30 );
|
||||
// m_frame_buffer.init( m_width, m_height );
|
||||
//m_frame_buffer.cls( 30, 30, 30 );
|
||||
//m_frame_buffer.draw_text( 50, 200, 2, 255, 127, 128, "This is a test!" );
|
||||
}
|
||||
|
||||
@@ -266,19 +232,6 @@ LRESULT frame_buf_window::window_proc(HWND hWnd, UINT message, WPARAM wParam, LP
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
if (m_frame_buffer.is_valid())
|
||||
{
|
||||
RECT window_size;
|
||||
GetClientRect(hWnd, &window_size);
|
||||
|
||||
StretchDIBits(m_windowHDC,
|
||||
0, 0, window_size.right, window_size.bottom,
|
||||
0, 0, m_width, m_height,
|
||||
m_frame_buffer.get_ptr(), m_pBitmap_hdr,
|
||||
DIB_RGB_COLORS, SRCCOPY);
|
||||
|
||||
ValidateRect(hWnd, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
@@ -522,7 +475,7 @@ public:
|
||||
|
||||
m_bHasNewScreenshot = false;
|
||||
m_nScreenshotID = 0;
|
||||
m_screenshot.clear();
|
||||
//m_screenshot.clear();
|
||||
|
||||
m_bReceivedNewCameraPos = false;
|
||||
memset( &m_NewCameraPos, 0, sizeof( m_NewCameraPos ) );
|
||||
@@ -623,7 +576,7 @@ public:
|
||||
bool HasNewScreenshotFlag() const { return m_bHasNewScreenshot; }
|
||||
void ClearNewScreenshotFlag() { m_bHasNewScreenshot = false; }
|
||||
uint GetScreenshotID() const { return m_nScreenshotID; }
|
||||
simple_bitmap &GetScreenshot() { return m_screenshot; }
|
||||
int &GetScreenshot() { return m_screenshot; }
|
||||
|
||||
bool HasNewConVarDumpFlag() const { return m_bHasNewConVarDump; }
|
||||
void ClearHasNewConVarDumpFlag() { m_bHasNewConVarDump = false; }
|
||||
@@ -644,7 +597,7 @@ private:
|
||||
bool m_bReceivedNewCameraPos;
|
||||
SetCameraPosPacket_t m_NewCameraPos;
|
||||
|
||||
simple_bitmap m_screenshot;
|
||||
int m_screenshot;
|
||||
bool m_bHasNewScreenshot;
|
||||
uint m_nScreenshotID;
|
||||
|
||||
@@ -716,7 +669,7 @@ private:
|
||||
videomode->ReadScreenPixels( 0, 0, nWidth, nHeight, s_pBuf, IMAGE_FORMAT_RGB888 );
|
||||
|
||||
size_t nPNGSize = 0;
|
||||
void *pPNGData = tdefl_write_image_to_png_file_in_memory( s_pBuf, nWidth, nHeight, 3, &nPNGSize, true );
|
||||
void *pPNGData = tdefl_write_image_to_png_file_in_memory( s_pBuf, nWidth, nHeight, 3, &nPNGSize );
|
||||
|
||||
if ( pPNGData )
|
||||
{
|
||||
@@ -771,9 +724,9 @@ private:
|
||||
else
|
||||
{
|
||||
int nWidth = 0, nHeight = 0, nComp = 3;
|
||||
unsigned char *pImageData = stbi_load_from_memory( reinterpret_cast< stbi_uc const * >( pPNGData ), nPNGDataSize, &nWidth, &nHeight, &nComp, 3);
|
||||
//unsigned char *pImageData = stbi_load_from_memory( reinterpret_cast< stbi_uc const * >( pPNGData ), nPNGDataSize, &nWidth, &nHeight, &nComp, 3);
|
||||
|
||||
if ( !pImageData )
|
||||
//if ( !pImageData )
|
||||
{
|
||||
Warning( "CONCMDSRV: Failed unpacking PNG screenshot!\n" );
|
||||
return false;
|
||||
@@ -782,14 +735,14 @@ private:
|
||||
m_bHasNewScreenshot = true;
|
||||
m_nScreenshotID = replyPacket.m_nScreenshotID;
|
||||
|
||||
if ( ( (int)m_screenshot.width() != nWidth ) || ( (int)m_screenshot.height() != nHeight ) )
|
||||
{
|
||||
m_screenshot.init( nWidth, nHeight );
|
||||
}
|
||||
//if ( ( (int)m_screenshot.width() != nWidth ) || ( (int)m_screenshot.height() != nHeight ) )
|
||||
//{
|
||||
// m_screenshot.init( nWidth, nHeight );
|
||||
//}
|
||||
|
||||
memcpy( m_screenshot.get_ptr(), pImageData, nWidth * nHeight * 3 );
|
||||
//memcpy( m_screenshot.get_ptr(), pImageData, nWidth * nHeight * 3 );
|
||||
|
||||
stbi_image_free( pImageData );
|
||||
//stbi_image_free( pImageData );
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1073,7 +1026,7 @@ public:
|
||||
|
||||
bool bHasUpdatedScreenshot = false;
|
||||
|
||||
simple_bgr_bitmap &frameBuf = m_pFrameBufWindow->frameBuffer();
|
||||
//simple_bgr_bitmap &frameBuf = m_pFrameBufWindow->frameBuffer();
|
||||
|
||||
for ( int i = 0; i < cMaxClients; i++ )
|
||||
{
|
||||
@@ -1096,7 +1049,7 @@ public:
|
||||
{
|
||||
client.ClearNewScreenshotFlag();
|
||||
|
||||
simple_bitmap &clientScreenshot = client.GetScreenshot();
|
||||
//simple_bitmap &clientScreenshot = client.GetScreenshot();
|
||||
|
||||
if ( ccs_remote_screenshots_delta.GetBool() )
|
||||
{
|
||||
@@ -1107,20 +1060,21 @@ public:
|
||||
uint nScreenWidth = videomode->GetModeWidth();
|
||||
uint nScreenHeight = videomode->GetModeHeight();
|
||||
|
||||
if ( ( m_screenshot.width() != nScreenWidth ) || ( m_screenshot.height() != nScreenHeight ) )
|
||||
{
|
||||
m_screenshot.init( nScreenWidth, nScreenHeight );
|
||||
}
|
||||
//if ( ( m_screenshot.width() != nScreenWidth ) || ( m_screenshot.height() != nScreenHeight ) )
|
||||
//{
|
||||
// m_screenshot.init( nScreenWidth, nScreenHeight );
|
||||
//}
|
||||
|
||||
videomode->ReadScreenPixels( 0, 0, nScreenWidth, nScreenHeight, m_screenshot.get_ptr(), IMAGE_FORMAT_RGB888 );
|
||||
//videomode->ReadScreenPixels( 0, 0, nScreenWidth, nScreenHeight, m_screenshot.get_ptr(), IMAGE_FORMAT_RGB888 );
|
||||
}
|
||||
|
||||
uint mx = MIN( clientScreenshot.width(), m_screenshot.width() );
|
||||
mx = MIN( mx, frameBuf.width() );
|
||||
//uint mx = MIN( clientScreenshot.width(), m_screenshot.width() );
|
||||
//mx = MIN( mx, frameBuf.width() );
|
||||
|
||||
uint my = MIN( clientScreenshot.height(), m_screenshot.height() );
|
||||
my = MIN( my, frameBuf.height() );
|
||||
//uint my = MIN( clientScreenshot.height(), m_screenshot.height() );
|
||||
//my = MIN( my, frameBuf.height() );
|
||||
|
||||
/*
|
||||
for ( uint y = 0; y < my; ++y )
|
||||
{
|
||||
const uint8 *pSrc1 = clientScreenshot.get_scanline( y );
|
||||
@@ -1149,11 +1103,11 @@ public:
|
||||
pDst += 3;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
frameBuf.blit( 0, 0, (simple_bgr_bitmap &)clientScreenshot, true );
|
||||
//frameBuf.blit( 0, 0, (simple_bgr_bitmap &)clientScreenshot, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1259,7 +1213,7 @@ private:
|
||||
CConCommandConnection m_Clients[cMaxClients];
|
||||
frame_buf_window *m_pFrameBufWindow;
|
||||
|
||||
simple_bitmap m_screenshot;
|
||||
int m_screenshot;
|
||||
int m_nViewEndpointIndex;
|
||||
|
||||
void AcceptNewConnections()
|
||||
|
||||
4916
thirdparty/miniz/miniz.c
vendored
Normal file
4916
thirdparty/miniz/miniz.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1350
thirdparty/miniz/miniz.h
vendored
Normal file
1350
thirdparty/miniz/miniz.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
thirdparty/stb_image/.gitignore
vendored
Normal file
9
thirdparty/stb_image/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*.annot
|
||||
*.cmo
|
||||
*.cma
|
||||
*.cmi
|
||||
*.a
|
||||
*.o
|
||||
*.cmx
|
||||
*.cmxs
|
||||
*.cmxa
|
||||
1
thirdparty/stb_image/.merlin
vendored
Normal file
1
thirdparty/stb_image/.merlin
vendored
Normal file
@@ -0,0 +1 @@
|
||||
PKG result
|
||||
117
thirdparty/stb_image/LICENSE
vendored
Normal file
117
thirdparty/stb_image/LICENSE
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
6
thirdparty/stb_image/META
vendored
Normal file
6
thirdparty/stb_image/META
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
name="stb_image"
|
||||
version="0.5"
|
||||
description="OCaml bindings to stb_image, a public domain image loader"
|
||||
requires="result"
|
||||
archive(byte)="stb_image.cma"
|
||||
archive(native)="stb_image.cmxa"
|
||||
62
thirdparty/stb_image/Makefile
vendored
Normal file
62
thirdparty/stb_image/Makefile
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
OCAMLC=ocamlfind c
|
||||
OCAMLOPT=ocamlfind opt
|
||||
OCAMLMKLIB=ocamlfind mklib
|
||||
|
||||
EXT_DLL=$(shell $(OCAMLC) -config | grep ext_dll | cut -f 2 -d ' ')
|
||||
EXT_LIB=$(shell $(OCAMLC) -config | grep ext_lib | cut -f 2 -d ' ')
|
||||
EXT_OBJ=$(shell $(OCAMLC) -config | grep ext_obj | cut -f 2 -d ' ')
|
||||
|
||||
CFLAGS=-O3 -std=gnu99 -ffast-math
|
||||
|
||||
all: stb_image.cma stb_image.cmxa
|
||||
|
||||
ml_stb_image$(EXT_OBJ): ml_stb_image.c
|
||||
$(OCAMLC) -c -ccopt "$(CFLAGS)" $<
|
||||
|
||||
dll_stb_image_stubs$(EXT_DLL) lib_stb_image_stubs$(EXT_LIB): ml_stb_image$(EXT_OBJ)
|
||||
$(OCAMLMKLIB) -o _stb_image_stubs $<
|
||||
|
||||
stb_image.cmi: stb_image.mli
|
||||
$(OCAMLC) -package result -c $<
|
||||
|
||||
stb_image.cmo: stb_image.ml stb_image.cmi
|
||||
$(OCAMLC) -package result -c $<
|
||||
|
||||
stb_image.cma: stb_image.cmo dll_stb_image_stubs$(EXT_DLL)
|
||||
$(OCAMLC) -package result -a -custom -o $@ $< \
|
||||
-dllib dll_stb_image_stubs$(EXT_DLL) \
|
||||
-cclib -l_stb_image_stubs
|
||||
|
||||
stb_image.cmx: stb_image.ml stb_image.cmi
|
||||
$(OCAMLOPT) -package result -c $<
|
||||
|
||||
stb_image.cmxa stb_image$(EXT_LIB): stb_image.cmx dll_stb_image_stubs$(EXT_DLL)
|
||||
$(OCAMLOPT) -package result -a -o $@ $< \
|
||||
-cclib -l_stb_image_stubs
|
||||
|
||||
.PHONY: clean install uninstall reinstall
|
||||
|
||||
clean:
|
||||
rm -f *$(EXT_LIB) *$(EXT_OBJ) *$(EXT_DLL) *.cm[ixoa] *.cmxa
|
||||
|
||||
DIST_FILES= \
|
||||
stb_image$(EXT_LIB) \
|
||||
stb_image.cmi \
|
||||
stb_image.cmo \
|
||||
stb_image.cma \
|
||||
stb_image.cmx \
|
||||
stb_image.cmxa \
|
||||
stb_image.ml \
|
||||
stb_image.mli \
|
||||
lib_stb_image_stubs$(EXT_LIB) \
|
||||
dll_stb_image_stubs$(EXT_DLL)
|
||||
|
||||
install: $(DIST_FILES) META
|
||||
ocamlfind install stb_image $^
|
||||
|
||||
uninstall:
|
||||
ocamlfind remove stb_image
|
||||
|
||||
reinstall:
|
||||
-$(MAKE) uninstall
|
||||
$(MAKE) install
|
||||
29
thirdparty/stb_image/README.md
vendored
Normal file
29
thirdparty/stb_image/README.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
Stb\_image is an OCaml binding to stb\_image from Sean Barrett, [Nothings](http://nothings.org/):
|
||||
|
||||
stb\_image.h: public domain C image loading library
|
||||
|
||||
The OCaml binding is released under CC-0 license. It has no dependency beside
|
||||
working OCaml and C compilers (stb\_image is self-contained).
|
||||
|
||||
```shell
|
||||
$ make
|
||||
$ make install
|
||||
```
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
Version 0.5, Fri Jun 28 19:45:20 CEST 2019
|
||||
Bug fix in C-bindings, fixed by @LaurentMazare
|
||||
|
||||
Version 0.4, Wed Jan 17 20:52:19 JST 2018
|
||||
Image specification can now contain offset and stride (BREAKING CHANGE).
|
||||
Add filtering primitives (blur and mipmap)
|
||||
|
||||
Version 0.3, Thu Nov 3 18:26:45 CET 2016
|
||||
Update to stb\_image.h v2.12
|
||||
|
||||
Version 0.2, Sun Dec 13 15:18:39 CET 2015
|
||||
Make use of result package
|
||||
|
||||
Version 0.1, Fri Sep 18 20:53:03 CET 2015
|
||||
Initial release
|
||||
475
thirdparty/stb_image/ml_stb_image.c
vendored
Normal file
475
thirdparty/stb_image/ml_stb_image.c
vendored
Normal file
@@ -0,0 +1,475 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <caml/mlvalues.h>
|
||||
#include <caml/memory.h>
|
||||
#include <caml/alloc.h>
|
||||
#include <caml/bigarray.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
static int Channels_val(value channel)
|
||||
{
|
||||
CAMLparam1(channel);
|
||||
int ret = 0;
|
||||
if (channel != Val_unit)
|
||||
ret = Long_val(Field(channel, 0));
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
static value return_image(void *data, int ty, int x, int y, int n)
|
||||
{
|
||||
CAMLparam0();
|
||||
CAMLlocal3(ret, tup, ba);
|
||||
|
||||
ba = caml_ba_alloc_dims(ty | CAML_BA_C_LAYOUT, 1, data, x * y * n);
|
||||
|
||||
tup = caml_alloc(6, 0);
|
||||
Store_field(tup, 0, Val_long(x));
|
||||
Store_field(tup, 1, Val_long(y));
|
||||
Store_field(tup, 2, Val_long(n));
|
||||
Store_field(tup, 3, Val_long(0));
|
||||
Store_field(tup, 4, Val_long(x * n));
|
||||
Store_field(tup, 5, ba);
|
||||
|
||||
/* Result.Ok tup */
|
||||
ret = caml_alloc(1, 0);
|
||||
Store_field(ret, 0, tup);
|
||||
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
static value return_failure(void)
|
||||
{
|
||||
CAMLparam0();
|
||||
CAMLlocal3(ret, str, err);
|
||||
|
||||
str = caml_copy_string(stbi_failure_reason());
|
||||
|
||||
/* `Msg "str" */
|
||||
err = caml_alloc(2, 0);
|
||||
Store_field(err, 0, Val_long(3854881));
|
||||
Store_field(err, 1, str);
|
||||
|
||||
/* Result.Error (`Msg "str") */
|
||||
ret = caml_alloc(1, 1);
|
||||
Store_field(ret, 0, err);
|
||||
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_load(value channels, value filename)
|
||||
{
|
||||
CAMLparam2(channels, filename);
|
||||
CAMLlocal1(ret);
|
||||
|
||||
int x, y, n, n0;
|
||||
n0 = Channels_val(channels);
|
||||
unsigned char* image_data = stbi_load(String_val(filename), &x, &y, &n, n0);
|
||||
if (n0 != 0) n = n0;
|
||||
|
||||
if (image_data)
|
||||
ret = return_image(image_data, CAML_BA_UINT8, x, y, n);
|
||||
else
|
||||
ret = return_failure();
|
||||
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_loadf(value channels, value filename)
|
||||
{
|
||||
CAMLparam2(channels, filename);
|
||||
CAMLlocal1(ret);
|
||||
|
||||
int x, y, n, n0;
|
||||
n0 = Channels_val(channels);
|
||||
float* image_data =
|
||||
stbi_loadf(String_val(filename), &x, &y, &n, n0);
|
||||
if (n0 != 0) n = n0;
|
||||
|
||||
if (image_data)
|
||||
ret = return_image(image_data, CAML_BA_FLOAT32, x, y, n);
|
||||
else
|
||||
ret = return_failure();
|
||||
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_load_mem(value channels, value mem)
|
||||
{
|
||||
CAMLparam2(channels, mem);
|
||||
CAMLlocal1(ret);
|
||||
|
||||
int x, y, n, n0;
|
||||
n0 = Channels_val(channels);
|
||||
unsigned char* image_data =
|
||||
stbi_load_from_memory(Caml_ba_data_val(mem),
|
||||
caml_ba_byte_size(Caml_ba_array_val(mem)),
|
||||
&x, &y, &n, n0);
|
||||
if (n0 != 0) n = n0;
|
||||
|
||||
if (image_data)
|
||||
ret = return_image(image_data, CAML_BA_UINT8, x, y, n);
|
||||
else
|
||||
ret = return_failure();
|
||||
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_loadf_mem(value channels, value mem)
|
||||
{
|
||||
CAMLparam2(channels, mem);
|
||||
CAMLlocal1(ret);
|
||||
|
||||
int x, y, n, n0;
|
||||
n0 = Channels_val(channels);
|
||||
float* image_data =
|
||||
stbi_loadf_from_memory(Caml_ba_data_val(mem),
|
||||
caml_ba_byte_size(Caml_ba_array_val(mem)),
|
||||
&x, &y, &n, n0);
|
||||
if (n0 != 0) n = n0;
|
||||
|
||||
if (image_data)
|
||||
ret = return_image(image_data, CAML_BA_FLOAT32, x, y, n);
|
||||
else
|
||||
ret = return_failure();
|
||||
|
||||
CAMLreturn(ret);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_image_free(value ba)
|
||||
{
|
||||
CAMLparam1(ba);
|
||||
void *data = Caml_ba_data_val(ba);
|
||||
|
||||
assert (data);
|
||||
stbi_image_free(data);
|
||||
Caml_ba_data_val(ba) = NULL;
|
||||
|
||||
CAMLreturn(Val_unit);
|
||||
}
|
||||
|
||||
#define POUT(x,n) pout[x] = (pin[x] + pin[n + x] + pin[w * n + n] + pin[w * n + x]) / 4
|
||||
#define POUTf(x,n) pout[x] = (pin[x] + pin[n + x] + pin[w * n + n] + pin[w * n + x]) / 4.0f
|
||||
|
||||
#define LOOP(w,h,n) \
|
||||
for (unsigned int y = 0, w2 = (w) / 2, h2 = (h) / 2; \
|
||||
y < h2; ++y, pin0 += sin, pin = pin0, pout0 += sout, pout = pout0) \
|
||||
for (unsigned int x = 0; x < w2; ++x, pin += 2 * n, pout += n)
|
||||
|
||||
CAMLprim value ml_stbi_mipmap(value img_in, value img_out)
|
||||
{
|
||||
CAMLparam2(img_in, img_out);
|
||||
unsigned char *pin, *pout,
|
||||
*pin0 = Caml_ba_data_val(Field(img_in, 5)),
|
||||
*pout0 = Caml_ba_data_val(Field(img_out, 5));
|
||||
assert (pin0 && pout0);
|
||||
|
||||
pin0 += Long_val(Field(img_in, 3));
|
||||
pout0 += Long_val(Field(img_out, 3));
|
||||
|
||||
unsigned int
|
||||
sin = Long_val(Field(img_in, 4)),
|
||||
sout = Long_val(Field(img_out, 4)),
|
||||
w = Long_val(Field(img_in, 0)),
|
||||
h = Long_val(Field(img_in, 1));
|
||||
|
||||
switch (Long_val(Field(img_in, 2))) {
|
||||
case 1:
|
||||
LOOP(w, h, 1) { POUT(0, 1); }
|
||||
break;
|
||||
case 2:
|
||||
LOOP(w, h, 2) { POUT(0, 2); POUT(1, 2); }
|
||||
break;
|
||||
case 3:
|
||||
LOOP(w, h, 3) { POUT(0, 3); POUT(1, 3); POUT(2, 3); }
|
||||
break;
|
||||
case 4:
|
||||
LOOP(w, h, 4) { POUT(0, 4); POUT(1, 4); POUT(2, 4); POUT(3, 4); }
|
||||
break;
|
||||
}
|
||||
|
||||
CAMLreturn(Val_unit);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_mipmapf(value img_in, value img_out)
|
||||
{
|
||||
CAMLparam2(img_in, img_out);
|
||||
float *pin, *pout,
|
||||
*pin0 = Caml_ba_data_val(Field(img_in, 5)),
|
||||
*pout0 = Caml_ba_data_val(Field(img_out, 5));
|
||||
assert (pin0 && pout0);
|
||||
|
||||
pin0 += Long_val(Field(img_in, 3));
|
||||
pout0 += Long_val(Field(img_out, 3));
|
||||
|
||||
unsigned int
|
||||
sin = Long_val(Field(img_in, 4)),
|
||||
sout = Long_val(Field(img_out, 4)),
|
||||
w = Long_val(Field(img_in, 0)),
|
||||
h = Long_val(Field(img_in, 1));
|
||||
|
||||
switch (Long_val(Field(img_in, 2))) {
|
||||
case 1:
|
||||
LOOP(w, h, 1) { POUTf(0, 1); }
|
||||
break;
|
||||
case 2:
|
||||
LOOP(w, h, 2) { POUTf(0, 2); POUTf(1, 2); }
|
||||
break;
|
||||
case 3:
|
||||
LOOP(w, h, 3) { POUTf(0, 3); POUTf(1, 3); POUTf(2, 3); }
|
||||
break;
|
||||
case 4:
|
||||
LOOP(w, h, 4) { POUTf(0, 4); POUTf(1, 4); POUTf(2, 4); POUTf(3, 4); }
|
||||
break;
|
||||
}
|
||||
|
||||
CAMLreturn(Val_unit);
|
||||
}
|
||||
|
||||
static void memswap(void *i0, void *i1, size_t count)
|
||||
{
|
||||
unsigned char *p0 = i0, *p1 = i1;
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned char tmp = p0[i];
|
||||
p0[i] = p1[i];
|
||||
p1[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_vflip(value img)
|
||||
{
|
||||
CAMLparam1(img);
|
||||
unsigned char *ptop = Caml_ba_data_val(Field(img, 5));
|
||||
assert (ptop);
|
||||
ptop += Long_val(Field(img, 3));
|
||||
|
||||
unsigned int
|
||||
w = Long_val(Field(img, 0)),
|
||||
h = Long_val(Field(img, 1)),
|
||||
n = Long_val(Field(img, 2)),
|
||||
stride = Long_val(Field(img, 4)),
|
||||
row = w * n;
|
||||
|
||||
unsigned char *pbot = ptop + (stride * h - stride);
|
||||
w = w * n;
|
||||
|
||||
for (unsigned int y = 0; y < h; y++)
|
||||
{
|
||||
memswap(ptop, pbot, row);
|
||||
ptop += stride;
|
||||
pbot -= stride;
|
||||
}
|
||||
|
||||
CAMLreturn(Val_unit);
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_vflipf(value img)
|
||||
{
|
||||
CAMLparam1(img);
|
||||
float *ptop = Caml_ba_data_val(Field(img, 5));
|
||||
assert (ptop);
|
||||
ptop += Long_val(Field(img, 3));
|
||||
|
||||
unsigned int
|
||||
w = Long_val(Field(img, 0)),
|
||||
h = Long_val(Field(img, 1)),
|
||||
n = Long_val(Field(img, 2)),
|
||||
stride = Long_val(Field(img, 4)),
|
||||
row = w * n * sizeof(float);
|
||||
|
||||
float *pbot = ptop + (stride * h - stride);
|
||||
w = w * n;
|
||||
|
||||
for (unsigned int y = 0; y < h; y++)
|
||||
{
|
||||
memswap(ptop, pbot, row);
|
||||
ptop += stride;
|
||||
pbot -= stride;
|
||||
}
|
||||
|
||||
CAMLreturn(Val_unit);
|
||||
}
|
||||
|
||||
// Based on Exponential blur, Jani Huhtanen, 2006
|
||||
// and [https://github.com/memononen/fontstash](fontstash), Mikko Mononen, 2014
|
||||
|
||||
#define APREC 16
|
||||
#define ZPREC 7
|
||||
|
||||
#define APPROX(alpha, reg, acc) \
|
||||
((alpha * (((int)(reg) << ZPREC) - acc)) >> APREC)
|
||||
|
||||
#define BLUR0(reg, acc) int acc = (int)(reg) << ZPREC
|
||||
|
||||
#define BLUR(reg, acc) \
|
||||
do { \
|
||||
acc += APPROX(alpha, reg, acc); \
|
||||
reg = (unsigned char)(acc >> ZPREC); \
|
||||
} while (0)
|
||||
|
||||
#define OUTERLOOP(var, ptr, bound, stride) \
|
||||
for (unsigned char *_limit = ptr + bound * stride, *var = ptr; var < _limit; var += stride)
|
||||
|
||||
#define INNERLOOP(var, bound, stride, BODY) \
|
||||
do { \
|
||||
int var; \
|
||||
for (var = stride; var < bound * stride; var += stride) BODY; \
|
||||
for (var = (bound - 2) * stride; var >= 0; var -= stride) BODY; \
|
||||
for (var = stride; var < bound * stride; var += stride) BODY; \
|
||||
for (var = (bound - 2) * stride; var >= 0; var -= stride) BODY; \
|
||||
} while (0)
|
||||
|
||||
static void expblur4(unsigned char* ptr, int w, int h, int stride, int alpha)
|
||||
{
|
||||
OUTERLOOP(dst, ptr, h, stride)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
BLUR0(dst[1], acc1);
|
||||
BLUR0(dst[2], acc2);
|
||||
BLUR0(dst[3], acc3);
|
||||
INNERLOOP(x, w, 4,
|
||||
{
|
||||
BLUR(dst[x+0], acc0);
|
||||
BLUR(dst[x+1], acc1);
|
||||
BLUR(dst[x+2], acc2);
|
||||
BLUR(dst[x+3], acc3);
|
||||
});
|
||||
}
|
||||
|
||||
OUTERLOOP(dst, ptr, w, 4)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
BLUR0(dst[1], acc1);
|
||||
BLUR0(dst[2], acc2);
|
||||
BLUR0(dst[3], acc3);
|
||||
INNERLOOP(y, h, stride,
|
||||
{
|
||||
BLUR(dst[y+0], acc0);
|
||||
BLUR(dst[y+1], acc1);
|
||||
BLUR(dst[y+2], acc2);
|
||||
BLUR(dst[y+3], acc3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void expblur3(unsigned char* ptr, int w, int h, int stride, int alpha)
|
||||
{
|
||||
OUTERLOOP(dst, ptr, h, stride)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
BLUR0(dst[1], acc1);
|
||||
BLUR0(dst[2], acc2);
|
||||
INNERLOOP(x, w, 3,
|
||||
{
|
||||
BLUR(dst[x+0], acc0);
|
||||
BLUR(dst[x+1], acc1);
|
||||
BLUR(dst[x+2], acc2);
|
||||
});
|
||||
}
|
||||
|
||||
OUTERLOOP(dst, ptr, w, 3)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
BLUR0(dst[1], acc1);
|
||||
BLUR0(dst[2], acc2);
|
||||
INNERLOOP(y, h, stride,
|
||||
{
|
||||
BLUR(dst[y+0], acc0);
|
||||
BLUR(dst[y+1], acc1);
|
||||
BLUR(dst[y+2], acc2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void expblur2(unsigned char* ptr, int w, int h, int stride, int alpha)
|
||||
{
|
||||
OUTERLOOP(dst, ptr, h, stride)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
BLUR0(dst[1], acc1);
|
||||
INNERLOOP(x, w, 2,
|
||||
{
|
||||
BLUR(dst[x+0], acc0);
|
||||
BLUR(dst[x+1], acc1);
|
||||
});
|
||||
}
|
||||
|
||||
OUTERLOOP(dst, ptr, w, 2)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
BLUR0(dst[1], acc1);
|
||||
INNERLOOP(y, h, stride,
|
||||
{
|
||||
BLUR(dst[y+0], acc0);
|
||||
BLUR(dst[y+1], acc1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void expblur1(unsigned char* ptr, int w, int h, int stride, int alpha)
|
||||
{
|
||||
OUTERLOOP(dst, ptr, h, stride)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
INNERLOOP(x, w, 1,
|
||||
{
|
||||
BLUR(dst[x+0], acc0);
|
||||
});
|
||||
}
|
||||
|
||||
OUTERLOOP(dst, ptr, w, 1)
|
||||
{
|
||||
BLUR0(dst[0], acc0);
|
||||
INNERLOOP(y, h, stride,
|
||||
{
|
||||
BLUR(dst[y+0], acc0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void expblur(unsigned char* ptr, int w, int h, int channels, int stride, float radius)
|
||||
{
|
||||
int i, alpha;
|
||||
float sigma;
|
||||
|
||||
if (radius < 0.01) return;
|
||||
|
||||
// Calculate the alpha such that 90% of the kernel is within the radius.
|
||||
// (Kernel extends to infinity)
|
||||
sigma = radius * 0.57735f; // 1 / sqrt(3)
|
||||
|
||||
// Improve blur quality by doing two pass
|
||||
// blur(sigma1) o blur(sigma2) = blur(sqrt(sqr(sigma1)*sqr(sigma2)))
|
||||
sigma = sigma * 0.707106f; // 1 / sqrt(2)
|
||||
|
||||
alpha = (int)((1<<APREC) * (1.0f - expf(-2.3f / (sigma + 1.0f))));
|
||||
|
||||
switch (channels)
|
||||
{
|
||||
case 1: expblur1(ptr, w, h, stride, alpha); break;
|
||||
case 2: expblur2(ptr, w, h, stride, alpha); break;
|
||||
case 3: expblur3(ptr, w, h, stride, alpha); break;
|
||||
case 4: expblur4(ptr, w, h, stride, alpha); break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
|
||||
CAMLprim value ml_stbi_expblur(value img, value radius)
|
||||
{
|
||||
CAMLparam2(img, radius);
|
||||
|
||||
unsigned char *ptr = Caml_ba_data_val(Field(img, 5));
|
||||
assert (ptr);
|
||||
ptr += Long_val(Field(img, 3));
|
||||
|
||||
unsigned int
|
||||
w = Long_val(Field(img, 0)),
|
||||
h = Long_val(Field(img, 1)),
|
||||
n = Long_val(Field(img, 2)),
|
||||
stride = Long_val(Field(img, 4));
|
||||
|
||||
expblur(ptr, w, h, n, stride, Double_val(radius));
|
||||
CAMLreturn(Val_unit);
|
||||
}
|
||||
27
thirdparty/stb_image/opam
vendored
Normal file
27
thirdparty/stb_image/opam
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
opam-version: "2.0"
|
||||
name: "stb_image"
|
||||
version: "0.5"
|
||||
maintainer: "Frederic Bour <frederic.bour@lakaban.net>"
|
||||
authors: "Frederic Bour <frederic.bour@lakaban.net>"
|
||||
homepage: "https://github.com/let-def/stb_image"
|
||||
bug-reports: "https://github.com/let-def/stb_image"
|
||||
license: "CC0"
|
||||
dev-repo: "git+https://github.com/let-def/stb_image.git"
|
||||
build: [
|
||||
[make]
|
||||
]
|
||||
install: [make "install"]
|
||||
remove: ["ocamlfind" "remove" "stb_image"]
|
||||
depends: [
|
||||
"ocaml" {!= "4.01.0"}
|
||||
"ocamlfind" {build}
|
||||
"result"
|
||||
]
|
||||
flags: light-uninstall
|
||||
synopsis: "OCaml bindings to stb_image, a public domain image loader"
|
||||
description: """
|
||||
Stb_image is an OCaml binding to stb_image from Sean Barrett, [Nothings](http://nothings.org/):
|
||||
|
||||
stb_image.h: public domain C image loading library
|
||||
|
||||
The OCaml binding is released under CC-0 license. It has no dependency beside working OCaml and C compilers (stb_image is self-contained)."""
|
||||
6755
thirdparty/stb_image/stb_image.h
vendored
Normal file
6755
thirdparty/stb_image/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
84
thirdparty/stb_image/stb_image.ml
vendored
Normal file
84
thirdparty/stb_image/stb_image.ml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
open Bigarray
|
||||
|
||||
type 'a result = ('a, [`Msg of string]) Result.result
|
||||
|
||||
type 'kind buffer = ('a, 'b, c_layout) Array1.t
|
||||
constraint 'kind = ('a, 'b) kind
|
||||
|
||||
type 'kind t = {
|
||||
width: int;
|
||||
height: int;
|
||||
channels: int;
|
||||
offset: int;
|
||||
stride: int;
|
||||
data: 'kind buffer;
|
||||
}
|
||||
|
||||
type float32 = (float, float32_elt) kind
|
||||
type int8 = (int, int8_unsigned_elt) kind
|
||||
|
||||
external load_unmanaged : ?channels:int -> string -> int8 t result = "ml_stbi_load"
|
||||
external loadf_unmanaged : ?channels:int -> string -> float32 t result = "ml_stbi_loadf"
|
||||
external decode_unmanaged : ?channels:int -> _ buffer -> int8 t result = "ml_stbi_load_mem"
|
||||
external decodef_unmanaged : ?channels:int -> _ buffer -> float32 t result = "ml_stbi_loadf_mem"
|
||||
|
||||
external ml_stbi_image_free : _ buffer -> unit = "ml_stbi_image_free"
|
||||
let free_unmanaged image =
|
||||
ml_stbi_image_free image.data
|
||||
|
||||
let clone buf =
|
||||
let buf' = Array1.create (Array1.kind buf) c_layout (Array1.dim buf) in
|
||||
Array1.blit buf buf';
|
||||
buf'
|
||||
|
||||
let manage f ?channels filename =
|
||||
match f ?channels filename with
|
||||
| Result.Error _ as err -> err
|
||||
| Result.Ok image ->
|
||||
let managed = {image with data = clone image.data} in
|
||||
free_unmanaged image;
|
||||
Result.Ok managed
|
||||
|
||||
let load ?channels filename = manage load_unmanaged ?channels filename
|
||||
let loadf ?channels filename = manage loadf_unmanaged ?channels filename
|
||||
let decode ?channels filename = manage decode_unmanaged ?channels filename
|
||||
let decodef ?channels filename = manage decodef_unmanaged ?channels filename
|
||||
|
||||
let image ~width ~height ~channels ?(offset=0) ?(stride=width*channels) data =
|
||||
let size = Array1.dim data in
|
||||
if width < 0 then
|
||||
Result.Error (`Msg "width should be positive")
|
||||
else if height < 0 then
|
||||
Result.Error (`Msg "height should be positive")
|
||||
else if channels < 0 || channels > 4 then
|
||||
Result.Error (`Msg "channels should be between 1 and 4")
|
||||
else if offset < 0 then
|
||||
Result.Error (`Msg "offset should be positive")
|
||||
else if offset + stride * height > size then
|
||||
Result.Error (`Msg "image does not fit in buffer")
|
||||
else
|
||||
Result.Ok { width; height; channels; offset; stride; data }
|
||||
|
||||
|
||||
let width t = t.width
|
||||
let height t = t.height
|
||||
let channels t = t.channels
|
||||
let data t = t.data
|
||||
|
||||
let validate_mipmap t1 t2 =
|
||||
if t1.channels <> t2.channels then
|
||||
invalid_arg "mipmap: images have different number of channels";
|
||||
if t1.width / 2 <> t2.width || t1.height / 2 <> t2.height then
|
||||
invalid_arg "mipmap: second image size should exactly be half of first image"
|
||||
|
||||
external mipmap : int8 t -> int8 t -> unit = "ml_stbi_mipmap"
|
||||
external mipmapf : float32 t -> float32 t -> unit = "ml_stbi_mipmapf"
|
||||
|
||||
let mipmap t1 t2 = validate_mipmap t1 t2; mipmap t1 t2
|
||||
let mipmapf t1 t2 = validate_mipmap t1 t2; mipmapf t1 t2
|
||||
|
||||
external vflip : int8 t -> unit = "ml_stbi_vflip"
|
||||
external vflipf : float32 t -> unit = "ml_stbi_vflipf"
|
||||
|
||||
(** Blur the image *)
|
||||
external expblur : int8 t -> radius:float -> unit = "ml_stbi_expblur"
|
||||
120
thirdparty/stb_image/stb_image.mli
vendored
Normal file
120
thirdparty/stb_image/stb_image.mli
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
(*
|
||||
Stb_image for OCaml by Frédéric Bour <frederic.bour(_)lakaban.net>
|
||||
To the extent possible under law, the person who associated CC0 with
|
||||
Stb_image for OCaml has waived all copyright and related or neighboring
|
||||
rights to Stb_image for OCaml.
|
||||
|
||||
You should have received a copy of the CC0 legalcode along with this
|
||||
work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
|
||||
Website: https://github.com/let-def/stb_image
|
||||
stb_image is a public domain library by Sean Barrett,
|
||||
http://nothings.org/
|
||||
Version 0.1, September 2015
|
||||
*)
|
||||
open Bigarray
|
||||
|
||||
type 'a result = ('a, [`Msg of string]) Result.result
|
||||
|
||||
|
||||
(*##############################*)
|
||||
(** {1 Image representation} *)
|
||||
|
||||
(** [buffer] simply is an alias to a bigarray with c_layout.
|
||||
The [buffer] type serves two purposes:
|
||||
- representing input files,
|
||||
- representing the raw pixels of an image.
|
||||
|
||||
Two kind of pixel buffers are manipulated:
|
||||
- int8 for images with 8-bit channels
|
||||
- float32 for images with floating point channels *)
|
||||
type 'kind buffer = ('a, 'b, c_layout) Array1.t
|
||||
constraint 'kind = ('a, 'b) kind
|
||||
|
||||
type float32 = (float, float32_elt) kind
|
||||
type int8 = (int, int8_unsigned_elt) kind
|
||||
|
||||
(** A record describing an image.
|
||||
The buffer contains [channels * width * height] items, in this order:
|
||||
- channels are interleaved
|
||||
- each pixel is made of [channels] items
|
||||
- each line is made of [width] pixels
|
||||
- image is made of [height] lines *)
|
||||
type 'kind t = private {
|
||||
width: int;
|
||||
height: int;
|
||||
channels: int;
|
||||
offset: int;
|
||||
stride: int;
|
||||
data: 'kind buffer;
|
||||
}
|
||||
|
||||
(** {2 Creating image} *)
|
||||
|
||||
val image : width:int -> height:int -> channels:int ->
|
||||
?offset:int -> ?stride:int ->
|
||||
'kind buffer -> 'kind t result
|
||||
|
||||
(** {2 Image accessors} *)
|
||||
|
||||
val width : _ t -> int
|
||||
val height : _ t -> int
|
||||
val channels : _ t -> int
|
||||
val data : 'kind t -> 'kind buffer
|
||||
|
||||
(** {1 Image decoding} *)
|
||||
|
||||
(** Load an 8-bit per channel image from a filename.
|
||||
If [channels] is specified, it has to be between 1 and 4 and the decoded image
|
||||
will be processed to have the requested number of channels. *)
|
||||
val load : ?channels:int -> string -> int8 t result
|
||||
|
||||
(** Load a floating point channel image from a filename.
|
||||
See [load] for [channels] parameter. *)
|
||||
val loadf : ?channels:int -> string -> float32 t result
|
||||
|
||||
(** Decode an 8-bit per channel image from a buffer.
|
||||
See [load] for [channels] parameter. *)
|
||||
val decode : ?channels:int -> _ buffer -> int8 t result
|
||||
|
||||
(** Decode a floating point channel image from a buffer.
|
||||
See [load] for [channels] parameter. *)
|
||||
val decodef : ?channels:int -> _ buffer -> float32 t result
|
||||
|
||||
(** {2 Low-level interface}
|
||||
|
||||
Functions are similar to the above one, except memory is not managed by OCaml GC.
|
||||
It has to be released explicitly with [free_unmanaged] function.
|
||||
|
||||
You get slightly faster load times, more deterministic memory use and more
|
||||
responsibility.
|
||||
Use at your own risk! *)
|
||||
|
||||
val load_unmanaged : ?channels:int -> string -> int8 t result
|
||||
val loadf_unmanaged : ?channels:int -> string -> float32 t result
|
||||
val decode_unmanaged : ?channels:int -> _ buffer -> int8 t result
|
||||
val decodef_unmanaged : ?channels:int -> _ buffer -> float32 t result
|
||||
val free_unmanaged: _ t -> unit
|
||||
|
||||
(** {2 Image filtering} *)
|
||||
|
||||
(** Generate one level of mipmap: downsample image half in each dimension.
|
||||
In [mipmap imgin imgout]:
|
||||
- imgout.channels must be imgin.channels
|
||||
- imgout.width must be imgin.width / 2
|
||||
- imgout.height must be imgin.height / 2
|
||||
- imgout.data will be filled with downsampled imgin.data
|
||||
*)
|
||||
val mipmap : int8 t -> int8 t -> unit
|
||||
|
||||
(** Downsample floating point images. See [mipmap]. *)
|
||||
val mipmapf : float32 t -> float32 t -> unit
|
||||
|
||||
(** Flip the image vertically *)
|
||||
val vflip : int8 t -> unit
|
||||
|
||||
(** Flip the image vertically *)
|
||||
val vflipf : float32 t -> unit
|
||||
|
||||
(** Blur the image *)
|
||||
val expblur : int8 t -> radius:float -> unit
|
||||
Reference in New Issue
Block a user