Mercurial > games > semicongine
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 1241:a0ed1a918fda | 1242:e8b3dc80e48e |
|---|---|
| 1 type | |
| 2 Gray* = TVec1[uint8] | |
| 3 RGBA* = TVec4[uint8] | |
| 4 PixelType* = Gray | RGBA | |
| 5 Image*[T: PixelType] = object | |
| 6 width*: uint32 | |
| 7 height*: uint32 | |
| 8 interpolation*: VkFilter = VK_FILTER_LINEAR | |
| 9 data*: seq[T] | |
| 10 vk*: VkImage | |
| 11 imageview*: VkImageView | |
| 12 sampler*: VkSampler | |
| 13 isRenderTarget*: bool = false | |
| 14 samples*: VkSampleCountFlagBits = VK_SAMPLE_COUNT_1_BIT | |
| 15 | |
| 16 proc LoadImage*[T: PixelType](path: string, package = DEFAULT_PACKAGE): Image[T] = | |
| 17 assert path.splitFile().ext.toLowerAscii == ".png" | |
| 18 when T is Gray: | |
| 19 let pngType = 0.cint | |
| 20 elif T is RGBA: | |
| 21 let pngType = 6.cint | |
| 22 | |
| 23 let indata = loadResource_intern(path, package = package).readAll() | |
| 24 var w, h: cuint | |
| 25 var data: cstring | |
| 26 | |
| 27 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: | |
| 28 raise newException(Exception, "An error occured while loading PNG file") | |
| 29 | |
| 30 let imagesize = w * h * 4 | |
| 31 result = Image[T](width: w, height: h, data: newSeq[T](w * h)) | |
| 32 copyMem(result.data.ToCPointer, data, imagesize) | |
| 33 nativeFree(data) | |
| 34 | |
| 35 when T is RGBA: # converkt to BGRA | |
| 36 for i in 0 ..< result.data.len: | |
| 37 swap(result.data[i][0], result.data[i][2]) | |
| 38 | |
| 39 proc toPNG[T: PixelType](image: Image[T]): seq[uint8] = | |
| 40 when T is Gray: | |
| 41 let pngType = 0 # hardcoded in lodepng.h | |
| 42 else: | |
| 43 let pngType = 6 # hardcoded in lodepng.h | |
| 44 var | |
| 45 pngData: cstring | |
| 46 pngSize: csize_t | |
| 47 for y in 0 ..< image.height: | |
| 48 for x in 0 ..< image.width: | |
| 49 discard | |
| 50 let ret = lodepng_encode_memory( | |
| 51 addr pngData, | |
| 52 addr pngSize, | |
| 53 cast[cstring](image.imagedata.ToCPointer), | |
| 54 cuint(image.width), | |
| 55 cuint(image.height), | |
| 56 cint(pngType), | |
| 57 8, | |
| 58 ) | |
| 59 assert ret == 0, &"There was an error with generating the PNG data for image {image}, result was: {ret}" | |
| 60 result = newSeq[uint8](pngSize) | |
| 61 for i in 0 ..< pngSize: | |
| 62 result[i] = uint8(pngData[i]) | |
| 63 nativeFree(pngData) | |
| 64 | |
| 65 proc WritePNG*(image: Image, filename: string) = | |
| 66 let f = filename.open(mode = fmWrite) | |
| 67 let data = image.toPNG() | |
| 68 let written = f.writeBytes(data, 0, data.len) | |
| 69 assert written == data.len, &"There was an error while saving '{filename}': only {written} of {data.len} bytes were written" | |
| 70 f.close() |
