Skip to content

Commit

Permalink
Impl Image.load & Add example for Backend.setIcons
Browse files Browse the repository at this point in the history
  • Loading branch information
PGZXB committed Aug 7, 2024
1 parent 7162ee0 commit e8aef8c
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 44 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "external/cimgui"]
path = external/cimgui
url = https://github.com/cimgui/cimgui
[submodule "external/stb"]
path = external/stb
url = https://github.com/nothings/stb.git
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ file(GLOB IMGUI_SOURCES
${IMGUI_TABLES_SOURCE}
# cimgui struct accessor wrappers
${CMAKE_CURRENT_SOURCE_DIR}/c_src/cimgui_struct_accessors.c
# image loading
${CMAKE_CURRENT_SOURCE_DIR}/c_src/load_image.c
)

set(IMGUI_STATIC "no" CACHE STRING "Build as a static library")
Expand Down Expand Up @@ -97,6 +99,7 @@ target_include_directories(${IMGUI4CJ_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/c_
target_include_directories(${IMGUI4CJ_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/external/cimgui)
target_include_directories(${IMGUI4CJ_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/external/cimgui/generator/output)
target_include_directories(${IMGUI4CJ_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/external/cimgui/imgui)
target_include_directories(${IMGUI4CJ_LIB} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/external/stb)

if (IMGUI4CJ_GLFW_OPENGL3_BACKEND)
target_compile_definitions(${IMGUI4CJ_LIB} PUBLIC IMGUI4CJ_GLFW_OPENGL3_BACKEND=1)
Expand Down
17 changes: 17 additions & 0 deletions c_src/load_image.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include "imgui4cj.h"

#include <assert.h>

// foreign func imgui4cj_loadImage(result: CPointer<CImage>, filename: CString, pErrMsg: CPointer<CPointer<UInt8>>): Int32
IMGUI4CJ_API int imgui4cj_loadImage(CImage *result, const char *filename, const char ** pErrMsg) {
assert(result && filename && pErrMsg);

int channels;
if ((result->pixels = stbi_load(filename, &result->width, &result->height, &channels, 4)) == NULL) {
*pErrMsg = stbi_failure_reason();
return -1;
}
return 0;
}
Binary file added examples/helloworld/assets/logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion examples/helloworld/src/main.cj
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package helloworld

import std.fs.Path
import imgui4cj.*
import imgui4cj.utils

func getAssetsDirectory() {
return Path("${Path(@sourceFile()).directoryName}/../assets").toCanonical()
}

main(): Int64 {
let clickCount = i64(0)
Expand All @@ -24,7 +30,9 @@ main(): Int64 {
)

let backend = getBackend(GLFWOpenGL3)
backend.createWindow("Hello IMGUI4CJ", 800, 600).setKeyCallback {
backend.createWindow("Hello IMGUI4CJ", 800, 600)
.setIcons([utils.Image.load(getAssetsDirectory().join("logo.jpg"))])
.setKeyCallback {
key: Key, _: Int32, action: KeyAction, _: ModifierKey =>
// Check key `space`
if (key == KEY_SPACE && action == KEY_PRESS) {
Expand Down
1 change: 1 addition & 0 deletions external/stb
Submodule stb added at f75e8d
2 changes: 1 addition & 1 deletion src/backends/glfw_opengl3_backend.cj
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ class GLFWOpenGL3Backend <: Backend {
try (r = LibC.malloc<CImage>(count: icons.size).asResource()) {
let pCImage = r.value
for (icon in icons) {
pCImage.write(icon.toCImage())
pCImage.write(icon.getCImage())
}
imgui4cj_glfwSetWindowIcon(glfwWindowInstance, Int32(icons.size), r.value)
}
Expand Down
67 changes: 25 additions & 42 deletions src/utils/image.cj
Original file line number Diff line number Diff line change
@@ -1,59 +1,42 @@
package imgui4cj.utils

import std.fs.File
import std.io.InputStream
import std.collection.ArrayList
import std.fs.Path

// TODO: Replace Image and related functions with std/3rd library used to process image
foreign func imgui4cj_loadImage(result: CPointer<CImage>, filename: CString, pErrMsg: CPointer<CPointer<UInt8>>): Int32

@C
public struct CImage {
protected struct CImage {
var width: Int32 = 0
var height: Int32 = 0
var pixels: CPointer<Byte> = CPointer<Byte>()

public func release() {
unsafe { LibC.free<Byte>(pixels) }
}
var pixels: CPointer<UInt8> = CPointer<UInt8>()
}

public struct Image {
var width: Int32 = 0
var height: Int32 = 0
var pixels: ArrayList<Byte> = ArrayList<Byte>([])

public func toCImage(): CImage {
var result = CImage()
result.width = width
result.height = height
result.pixels = unsafe { LibC.malloc<Byte>(count: pixels.size) }

unsafe { // Copy from pixels to result.pixels
var p = result.pixels
for (byte in pixels) {
p.write(byte)
p += 1
}
}
public class Image {
private Image(private let cImage: CImage) {
}

return result
~init() {
unsafe { LibC.free<UInt8>(cImage.pixels) }
}
}

public func tryLoadImage(_: InputStream): ?Image {
// TODO: Impt it: read many image formats as pixels
throw UnsupportedException("to be implemented")
}
protected func getCImage(): CImage {
return cImage
}

public func tryLoadImage(filename: String): ?Image {
try (fp = File.openRead(filename)) {
return tryLoadImage(fp)
public static func load(filename: Path): Image {
return load(filename.toString())
}
return None
}

public func loadImage(filename: String): Image {
return tryLoadImage(filename).getOrThrow {
IllegalArgumentException("invalid image file: ${filename}")
public static func load(filename: String): Image {
try (filenameRes = unsafe { LibC.mallocCString(filename) }.asResource()) {
var cImage: CImage = CImage()
var errMsg: CPointer<UInt8> = CPointer<UInt8>()
let err = unsafe { imgui4cj_loadImage(inout cImage, filenameRes.value, inout errMsg) }
if (err != 0) {
throw IllegalArgumentException("Load image ${filename} failed: ${CString(errMsg)}")
}
return Image(cImage)
}
throw IllegalStateException("illegal state")
}
}

0 comments on commit e8aef8c

Please sign in to comment.