Mercurial > games > semicongine
diff semiconginev2/image.nim @ 1242:e8b3dc80e48e
add: PNG loading and tests for it
author | sam <sam@basx.dev> |
---|---|
date | Mon, 22 Jul 2024 15:53:32 +0700 |
parents | |
children | c15770761865 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semiconginev2/image.nim Mon Jul 22 15:53:32 2024 +0700 @@ -0,0 +1,70 @@ +type + Gray* = TVec1[uint8] + RGBA* = TVec4[uint8] + PixelType* = Gray | RGBA + Image*[T: PixelType] = object + width*: uint32 + height*: uint32 + interpolation*: VkFilter = VK_FILTER_LINEAR + data*: seq[T] + vk*: VkImage + imageview*: VkImageView + sampler*: VkSampler + isRenderTarget*: bool = false + samples*: VkSampleCountFlagBits = VK_SAMPLE_COUNT_1_BIT + +proc LoadImage*[T: PixelType](path: string, package = DEFAULT_PACKAGE): Image[T] = + assert path.splitFile().ext.toLowerAscii == ".png" + when T is Gray: + let pngType = 0.cint + elif T is RGBA: + let pngType = 6.cint + + let indata = loadResource_intern(path, package = package).readAll() + var w, h: cuint + var data: cstring + + if lodepng_decode_memory(out_data = addr(data), w = addr(w), h = addr(h), in_data = cstring(indata), insize = csize_t(indata.len), colorType = pngType, bitdepth = 8) != 0: + raise newException(Exception, "An error occured while loading PNG file") + + let imagesize = w * h * 4 + result = Image[T](width: w, height: h, data: newSeq[T](w * h)) + copyMem(result.data.ToCPointer, data, imagesize) + nativeFree(data) + + when T is RGBA: # converkt to BGRA + for i in 0 ..< result.data.len: + swap(result.data[i][0], result.data[i][2]) + +proc toPNG[T: PixelType](image: Image[T]): seq[uint8] = + when T is Gray: + let pngType = 0 # hardcoded in lodepng.h + else: + let pngType = 6 # hardcoded in lodepng.h + var + pngData: cstring + pngSize: csize_t + for y in 0 ..< image.height: + for x in 0 ..< image.width: + discard + let ret = lodepng_encode_memory( + addr pngData, + addr pngSize, + cast[cstring](image.imagedata.ToCPointer), + cuint(image.width), + cuint(image.height), + cint(pngType), + 8, + ) + assert ret == 0, &"There was an error with generating the PNG data for image {image}, result was: {ret}" + result = newSeq[uint8](pngSize) + for i in 0 ..< pngSize: + result[i] = uint8(pngData[i]) + nativeFree(pngData) + +proc WritePNG*(image: Image, filename: string) = + let f = filename.open(mode = fmWrite) + let data = image.toPNG() + let written = f.writeBytes(data, 0, data.len) + assert written == data.len, &"There was an error while saving '{filename}': only {written} of {data.len} bytes were written" + f.close()