{"id":16163753,"url":"https://github.com/sug0/libgoimg","last_synced_at":"2025-06-19T04:04:27.570Z","repository":{"id":98038393,"uuid":"143570407","full_name":"sug0/libgoimg","owner":"sug0","description":"C library that aims to provide the ease of operation Go enables for image processing","archived":false,"fork":false,"pushed_at":"2024-04-28T20:52:19.000Z","size":116,"stargazers_count":6,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-19T04:04:02.552Z","etag":null,"topics":["c","farbfeld","go","golang","image","interface","jpeg","library","png"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sug0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-04T23:44:18.000Z","updated_at":"2024-04-28T20:52:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"ef7d3c8f-4928-4237-9b24-e61c4adf4fcb","html_url":"https://github.com/sug0/libgoimg","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sug0/libgoimg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sug0%2Flibgoimg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sug0%2Flibgoimg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sug0%2Flibgoimg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sug0%2Flibgoimg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sug0","download_url":"https://codeload.github.com/sug0/libgoimg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sug0%2Flibgoimg/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260684101,"owners_count":23046098,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","farbfeld","go","golang","image","interface","jpeg","library","png"],"created_at":"2024-10-10T02:44:20.917Z","updated_at":"2025-06-19T04:04:22.560Z","avatar_url":"https://github.com/sug0.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n   \u003cimg src=\"res/logo.png\" width=350\u003e\n\u003c/p\u003e\n\n# libgoimg\n\nA C library that aims to provide the ease of operation Go enables for image processing.\n\nIt is extremely modular in the sense that you can leave out all formats that ship with\nit by default, implementing your own decoding and encoding routines for your custom format,\nor even your custom image and color routines for custom color spaces.\n\n# Status\n\nThis library is most likely not ready for production, but you can\nsafely use it for your personal projects. Right now you can\nencode and decode the farbfeld, PNG and JPEG formats, with the\nlater two requiring `libpng` and `libjpeg(-turbo)` respectively.\n\n# Building\n\nThis library comes with a simple python build script I wrote. The syntax for the\ncommand line arguments it accepts is:\n\n    $ python build.py [-i:INSTALL_PATH_PREFIX] [FMT_1+FMT_2+...]\n\nTo build with support for all formats do:\n\n    $ python build.py png+jpeg+farbfeld\n\nTo install it after building:\n\n    $ sudo python build.py -i:/usr/local png+jpeg+farbfeld\n\nTo build with none of these formats:\n\n    $ python build.py\n\n# Linking against this library\n\nI chose to only build a static library, because the code base is simple enough,\nand it catered to my use cases. However, hacking the python script to\nbuild a shared library shouldn't be too hard.\n\n# Documentation\n\nYou can find what each function does reading the header files. I tried documenting\nthem as best as I could. To simplify things however, I'll provide a few examples\non the following subsections.\n\n## Converting an image to JPEG\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003cgoimg/goimg.h\u003e\n\nint fpread(void *src, char *buf, int size)\n{\n    return fread(buf, 1, size, (FILE *)src);\n}\n\nint fpwrite(void *dst, char *buf, int size)\n{\n    return fwrite(buf, 1, size, (FILE *)dst);\n}\n\nint main(void)\n{\n    int err = 0;\n    Image_t img = {.img = NULL, .allocator = im_std_allocator};\n\n    im_load_defaults();\n\n    if (!im_decode(\u0026img, fpread, stdin)) {\n        err = 1;\n        goto done;\n    }\n\n    if (im_encode(\u0026img, \"JPEG\", fpwrite, stdout) \u003c 0)\n        err = 1;\n\ndone:\n    im_xfree(im_std_allocator, img.img);\n\n    return err;\n}\n```\n\n## Drawing a circle with a custom allocator\n\n```c\n#include \u003cstdio.h\u003e\n#include \u003cstdlib.h\u003e\n#include \u003cstring.h\u003e\n#include \u003csys/mman.h\u003e\n\n#include \u003cgoimg/goimg.h\u003e\n\n#define DIM  100\n#define M    ((DIM)/2)\n\n#define NO_ADDR  8\n\n#define COLOR_WHITE  255\n#define COLOR_BLACK  0\n\nstruct mem_addr {\n    void *addr;\n    FILE *fp;\n    size_t size;\n};\n\nstruct mem {\n    struct mem_addr addrs[NO_ADDR];\n};\n\nint sq(int x);\nuint8_t get_color(int x, int y);\n\nvoid *mem_alloc(void *data, size_t size);\nvoid *mem_realloc(void *data, void *addr, size_t size);\nvoid mem_free(void *data, void *addr);\n\nint main(void)\n{\n    int x, y, err = 0;\n\n    struct mem mem;\n    Allocator_t allocator = {\n        .alloc = mem_alloc,\n        .realloc = mem_realloc,\n        .free = mem_free,\n        .data = \u0026mem\n    };\n\n    /* load default image formats */\n    im_load_defaults();\n\n    /* zero out allocator memory */\n    memset(\u0026mem, 0, sizeof(struct mem));\n\n    Color_t c = im_newcolor_gray();\n    Image_t img = im_newimg_gray(DIM, DIM, \u0026allocator);\n\n    /* draw pixel data */\n    for (y = 0; y \u003c DIM; y++) {\n        for (x = 0; x \u003c DIM; x++) {\n            *(uint8_t *)c.color = get_color(x, y);\n            img.set(\u0026img, x, y, \u0026c);\n        }\n    }\n\n    /* encode to stdout as PNG */\n    if (im_encode(\u0026img, \"PNG\", fdwrite, GOIO_FD(1)) \u003c 0)\n        err = 1;\n\n    /* free memory using the respective allocators,\n     * for 'img' and 'c' */\n    im_xfree(im_std_allocator, c.color);\n    im_xfree(\u0026allocator, img.img);\n\n    return err;\n}\n\ninline int sq(int x)\n{\n    return x*x;\n}\n\ninline uint8_t get_color(int x, int y)\n{\n    return (sq(x - M) + sq(y - M) \u003c sq(M)) ? COLOR_WHITE : COLOR_BLACK;\n}\n\nvoid *_allocate(struct mem_addr *mem, size_t size)\n{\n    void *addr;\n\n    if (!mem)\n        return NULL;\n\n    if (!mem-\u003efp) {\n        mem-\u003efp = tmpfile();\n\n        if (!mem-\u003efp)\n            return NULL;\n    }\n\n    /* initialize memory area */\n    fseek(mem-\u003efp, size, SEEK_SET);\n    fputc('\\0', mem-\u003efp);\n    fseek(mem-\u003efp, 0, SEEK_SET);\n\n    /* map region */\n    addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(mem-\u003efp), 0);\n\n    if (addr == MAP_FAILED) {\n        fclose(mem-\u003efp);\n        return NULL;\n    }\n\n    /* save the state */\n    mem-\u003eaddr = addr;\n    mem-\u003esize = size;\n\n    return addr;\n}\n\nvoid *mem_alloc(void *data, size_t size)\n{\n    struct mem *mem = (struct mem *)data;\n    int i;\n    \n    /* find free space */\n    for (i = 0; i \u003c NO_ADDR; i++)\n        if (!mem-\u003eaddrs[i].addr)\n            return _allocate(\u0026mem-\u003eaddrs[i], size);\n\n    return NULL;\n}\n\nvoid *mem_realloc(void *data, void *addr, size_t size)\n{\n    struct mem *mem = (struct mem *)data;\n    struct mem_addr *mem_addr = NULL;\n    int i;\n\n    for (i = 0; i \u003c NO_ADDR; i++) {\n        if (!mem_addr \u0026\u0026 !mem-\u003eaddrs[i].addr)\n            mem_addr = \u0026mem-\u003eaddrs[i];\n\n        if (mem-\u003eaddrs[i].addr == addr) {\n            munmap(addr, mem-\u003eaddrs[i].size);\n            return _allocate(\u0026mem-\u003eaddrs[i], size);\n        }\n    }\n\n    return _allocate(mem_addr, size);\n}\n\nvoid mem_free(void *data, void *addr)\n{\n    struct mem *mem = (struct mem *)data;\n    int i;\n\n    for (i = 0; i \u003c NO_ADDR; i++) {\n        if (mem-\u003eaddrs[i].addr == addr) {\n            munmap(addr, mem-\u003eaddrs[i].size);\n            fclose(mem-\u003eaddrs[i].fp);\n            memset(\u0026mem-\u003eaddrs[i], 0, sizeof(struct mem_addr));\n            return;\n        }\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsug0%2Flibgoimg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsug0%2Flibgoimg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsug0%2Flibgoimg/lists"}