├── README.md ├── better-c.md ├── color.md ├── decision-process.md ├── draw_command_buffering_api.md ├── errors.md ├── image-loading.md ├── image-resizing.md ├── image.md ├── pixel-format-summary.md ├── png-read-write.md ├── research.md └── rgb-format.md /README.md: -------------------------------------------------------------------------------- 1 | # Dlang Graphics Workgroup 2 | 3 | 4 | The output of the Dlang Graphics Workgroup: a technical recommendation for an Image abstraction library, suitable to implement further graphics works. 5 | 6 | 7 | **Step 1: requirements gathering.** 8 | 9 | Please vote on proposals here: https://github.com/DlangGraphicsWG/documents/pulls 10 | 11 | - Color: [color.md](color.md) 12 | - Image: [requirements.md](image.md) 13 | - Image Loading: [image-loading.md](image-loading.md) 14 | - Image Resizing: [image-resizing.md](image-resizing.md) 15 | - Decision process: [decision-process.md](decision-process.md) 16 | 17 | 18 | # Goals 19 | 20 | 21 | The Dlang Graphics Workgroup is a collective of D library writers who want to 22 | make libraries together with a collegial design. 23 | 24 | 25 | We feel that Phobos leads the path towards building reusable, expressive abstractions; 26 | and that there is no reason a GUI Toolkit can't be unopinionated to the same degree std.range or std.allocator is. 27 | 28 | We acknowledge that working on our own graphics libraries (like we currently do), may not yield 29 | the best possible result for everyone; and that discussion and arguing are called 30 | for if we are to keep the D community engaged. 31 | 32 | Because this task is essentially about defining graphical interfaces, and those interfaces exchanges "images", 33 | **our first line of work is the design of an Image library**. 34 | 35 | Because this task is essentially about (dis)agreement, we **talk about pain points** (pros/cons) 36 | and give them existence. 37 | 38 | 39 | ## Step 1: 40 | 41 | Find out what we actually need in an Image library. 42 | 43 | ## Step 2: 44 | 45 | Figure out what we already got that matches it. 46 | 47 | ## Step 3: 48 | 49 | Figure out what do we need to do to make it fully match our needs. 50 | 51 | -------------------------------------------------------------------------------- /better-c.md: -------------------------------------------------------------------------------- 1 | # Do we `-better-c` or not? 2 | 3 | Pros: 4 | - More inclusive to more users 5 | - Accessible by foreign languages 6 | - Available to resource limited systems 7 | - Increase opportunity to become a de-facto standard image representation library 8 | - There's something to be said for compile times 9 | 10 | Cons: 11 | - Potentially affects API design in a way that frustrates usability 12 | - Some phobos functionality may need to be mirrored locally 13 | 14 | Considerations: 15 | - Our suite not need be a monolith; low-level inter-op packages may be `better-c` while higher level functions take full advantage of the std library 16 | - Where tension exists, we may choose to present modern-d and better-c overload apis 17 | - Tasteful and careful design may be possible to allow for the best of both worlds 18 | 19 | Discussions points: 20 | - p0nce: personally I still don't think we should avoid phobos or the runtime. Illusion of consensus right here! 21 | - NX133t: if for some reason we were to decide gui to be betterC I would just run away 22 | - Manu: I would like to justify large dependencies with substance before they're drawn in 23 | - Manu: Packages that define API layers may specify different dependency sets 24 | 25 | 26 | I think it's possible to have our cake and eat it too with careful design. 27 | Everyone should be vigilent, and make sure each new API doesn't violate their design sensibilities, and we can iterate to make sure designs feel great from all perspectives. 28 | -------------------------------------------------------------------------------- /color.md: -------------------------------------------------------------------------------- 1 | # What is a Color? 2 | 3 | 4 | 5 | 6 | # Open questions (no vote occured yet) 7 | 8 | - What is a Color, the "pixel" type of an Image? 9 | 10 | - Is it a compile-time or runtime thing? 11 | 12 | - Should there be several different Color format and type? 13 | -------------------------------------------------------------------------------- /decision-process.md: -------------------------------------------------------------------------------- 1 | # Decision Process 2 | 3 | GUI libraries are notoriously complex to design and are prone to easy disapproval. 4 | 5 | The DlangGraphicsWG initiative comes from a shared understanding disagreement must be 6 | reified and talked upon, rather than hidden behind individual initiatives. 7 | 8 | 9 | 1. The Output of this Work Group is every Markdown .md files in the Organization's repositories. 10 | The wiki is only informal. 11 | 12 | 2. Members of the Github organization DlangGraphicsWG have no special rights, 13 | apart from being able to merge/reject Pull Requests according to this document. 14 | 15 | 3. Modifications proposals to the Output (.md files) are brought in through Pull Requests. 16 | 17 | 4. Each open Pull Request is a vote to be held. 18 | 19 | Voting is open to anyone, as long as the PR is currently open, for a period of at least 24h. 20 | After this time, a member of the Github Organization is allowed to merge or reject the Pull Request. 21 | 22 | For being merged, a proposal: 23 | * must have a strict majority of votes "yes" 24 | * AND must have gathered at least three vote "yes" 25 | * must still be open by its author 26 | 27 | For being rejected, a proposal: 28 | * must have a strict majority of votes "no" 29 | * AND must have gathered at least three vote "no" 30 | 31 | If there are insufficient votes, or if no one wants to merge/reject yet, the period 32 | of voting is extended for 24h, with a maximum of one month. 33 | After that duration, it is rejected due to lack of interest. 34 | 35 | 5. One can vote "yes-if(X)" or "no-if(X)" to a proposal which mean the vote counts as a "yes" 36 | if the Proposal's submitter answers the concern of the voter, and a "no" instead. 37 | This is meant for clarification. Reviewers are trusted to compute X in an impartial way. 38 | The yes-if and no-if variants of votes have to be managed through Github reviews. 39 | In the case of a single voter having several Github reviews, whose result is conflicting, 40 | the "no" wins. 41 | 42 | 6. A proposal cannot be merged or rejected by the same person making the proposal. 43 | 44 | 7. A proposal being merged or rejected doesn't mean the debate is closed. 45 | 46 | 8. This document is self-referential. Process modifications themselves must follow this document. 47 | -------------------------------------------------------------------------------- /draw_command_buffering_api.md: -------------------------------------------------------------------------------- 1 | ## Disclaimer 2 | 3 | First of all this is an attempt to gather information about state of Renderer in dlang 4 | 5 | # What is a Draw Command Buffering API? 6 | 7 | This API provides functionality to draw primitives issuing draw commands that will be performed some time later using the backend API. In fact it is a layer between generic part of renderer independent on hardware and hardware specific part of renderer. The draw command buffer API lets draw the following primitives: 8 | - point 9 | - line 10 | - polyline 11 | - polygone (convex only) 12 | - rectangle 13 | - ellipse 14 | - text 15 | - image 16 | 17 | Lines can be stroked, 2D figures can be stroked and filled. Rectange can have rounded corners. 18 | 19 | API is 2D only. 20 | API is vector one. 21 | Example of draw command buffer API: 22 | - [dearimgu](https://github.com/ocornut/imgui/blob/2889a14f86823c4b39b6e4d070fef19064167ab2/imgui.h#L1817) 23 | - [nuklear](https://github.com/vurtun/nuklear/blob/181cfd86c47ae83eceabaf4e640587b844e613b6/nuklear.h#L4701). 24 | 25 | # Sample API 26 | 27 | There are many ways to implement draw command buffer that do same things in different and non-interchangeble ways. For example `dearimgui` and `nuklear` implements draw command buffer in very similar but non API compatible ways. This document try to define one of possible variants based on `dearimgui` and `nuklear` APIs 28 | 29 | ```D 30 | enum Stroke { open = false, closed = true } 31 | enum AntiAliasing { off, on } 32 | 33 | // Path API 34 | pathClear(Ctx); 35 | pathLineTo(Ctx, Vec2 pos); 36 | pathArcTo(Ctx, Vec2 center, float radius, float a_min, float a_max, uint segments); 37 | pathRectTo(Ctx, Vec2 a, Vec2 b, float rounding); 38 | pathCurveTo(Ctx, Vec2 p2, Vec2 p3, Vec2 p4, uint num_segments); 39 | pathFill(Ctx, Color); 40 | pathStroke(Ctx, Color, Stroke closed, float thickness); 41 | 42 | // stroke 43 | strokeLine(Ctx, Vec2 a, Vec2 b, Color, float thickness); 44 | strokeRect(Ctx, rect, Color, float rounding, float thickness); 45 | strokeTriangle(Ctx, Vec2 a, Vec2 b, Vec2 c, Color, float thickness); 46 | strokeCircle(Ctx, Vec2 center, float radius, Color, uint segs, float thickness); 47 | strokeCurve(Ctx, Vec2 p0, Vec2 cp0, Vec2 cp1, Vec2 p1, Color, uint segments, float thickness); 48 | strokePolyLine(Ctx, ref const(Vec2) pnts, uint cnt, Color, Stroke, float thickness, AntiAliasing aa); 49 | 50 | // fill 51 | fillRect(Ctx, rect, Color, float rounding); 52 | fillTriangle(Ctx, Vec2 a, Vec2 b, Vec2 c, Color); 53 | fillCircle(Ctx, Vec2 center, float radius, Color col, uint segs); 54 | fillPolyConvex(Ctx, ref const(Vec2) pnts, uint count, Color, AntiAliasing aa); 55 | 56 | // image 57 | addImage(Ctx, Image texture, rect, Color); 58 | 59 | // text 60 | addText(Ctx, ref Font, Rect, string text, float font_height, Color); 61 | 62 | // scissor 63 | scissor(Ctx, Rect); 64 | ``` 65 | 66 | Notes: 67 | - `Dearimgui` has ability to cancel previous scissor but it is just sugar 68 | - `Dearimgui` provides additional functionality - channels. 69 | - `Nuklear` and `dearimgui` have close implemention. Path stroking lowered to polyline drawing with or without antialiasing with very similar implementation details. For example `nanovega` has very different implementation details but probably it is because tightly coupling with opengl backend. `dearimgui` and `nuklear` are much more backend agnostic. 70 | 71 | ## Open questions: 72 | 1. context+standalone functions (`nuklear`, plain c) vs aggregate with methods (`dearimgui`, C++)? there is no big difference I guess but nevertheless 73 | 2. class vs struct? reference type vs value type 74 | 3. to use const qualifier or not to use? 75 | 4. polygons are convex only (at least now) - both `dearimgui` and `nuklear` use only convex ones 76 | 5. coordinates are fractional. In `dearimgui` pixels have fractional coordinates but width and height for example are integer values. `Nuklear` has float coordinates and also width and height. 77 | 6. how to set Image where the backend render to? both `dearimgui` and `nuklear` have no this functionality, they render to default buffer(?). Probably it could be implemented using: 78 | ``` 79 | ctx.beginFrame(Image image); 80 | ... 81 | ctx.endFrame; 82 | ``` 83 | 7. Vec2, Rect, Color - is it hardcoded types or templated API possible? `nuklear` let you define your own pixel/vertex format, so it is claimed by users. 84 | 85 | # Fonts and text drawing 86 | 87 | Planned to some next PR. 88 | -------------------------------------------------------------------------------- /errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | The policy for the DlangGraphicsWG about errors is the following: 4 | 5 | 1. Internal functions may use any mechanism, left at the discretion of the implementer 6 | 7 | 2. In the public parts of the library that have to follow `-betterC` (TBD): 8 | 9 | - If the function is publicly exported by a module **and has to report an error message**, 10 | use `Result!T` a combination of a `T` an a message `string`. 11 | If the message `string` is null then the `T` is valid. 12 | 13 | - Else if the function doesn't have to report an error message, use error codes (`bool` return and `out` params). 14 | 15 | 16 | 3. In the parts of the library that don't have to follow `-betterC` (TBD) 17 | 18 | Use normal D exceptions. 19 | -------------------------------------------------------------------------------- /image-loading.md: -------------------------------------------------------------------------------- 1 | # What should be in image loading? 2 | 3 | 4 | - The Image Loading solution should support turning what is loaded to raw `ubyte[]` data 5 | 6 | 7 | 8 | # Open questions (no vote occured yet) 9 | 10 | - A 2-layer architecture for image loading (format decoders + generic interface) 11 | 12 | - Error codes or exceptions? 13 | 14 | - stance on `-betterC`? 15 | 16 | - whether there can be an additional IAllocator in Image loaders for temporary buffers, used for decoding 17 | 18 | - Which formats should be supported for loading? 19 | 20 | - Which formats should be supported for encoding? 21 | 22 | - how much Image loader are supposed to convert from one Color format to another 23 | Pros: 24 | - Less allocations 25 | Cons: 26 | - Extra conversions making things less clean 27 | 28 | - Is video to be supported? 29 | 30 | - Should animated format such as GIF be supported? 31 | 32 | - Should progressive images such as GIF be supported? 33 | 34 | - Progressive images (such as progressive JPEG) should be supported with an incomplete input? 35 | 36 | - What happens when loading something with another colorspace as sRGB? should it auto-convert? 37 | 38 | - Whether Image loaders should have short-paths for getting image meta-data such as dimensions 39 | 40 | - What meta-data is accessible to the visible API? 41 | -------------------------------------------------------------------------------- /image-resizing.md: -------------------------------------------------------------------------------- 1 | # What should be in image resizing? 2 | 3 | 4 | 5 | # Open questions (no vote occured yet) 6 | 7 | - What particular filter should be used? for upsizing and downsizing? -------------------------------------------------------------------------------- /image.md: -------------------------------------------------------------------------------- 1 | # What is an Image? 2 | 3 | - View!Color (and operations on these) are range-like objects that can be composed like in `ae.utils.graphics` 4 | 5 | * Pros: 6 | - Friendly and efficient UFCS chains of operations (need good names). 7 | - The Pros of Input ranges, but for images. 8 | 9 | * Cons: 10 | - UFCS chains may leave no room to pass a complex context. 11 | - Most of algorithms end up being written for contiguous in-memory images anyway. 12 | - Like `std.range`, functions are all defined externally hence not quite easy to discover. 13 | 14 | - Images types should have a runtime interface. This interface is a POD `struct` 15 | that looks like: 16 | ```d 17 | struct RuntimeImage 18 | { 19 | int width, height; 20 | size_t pitchbetweenRows; 21 | void* data; 22 | PixelFormat whateverIsNeeded; 23 | } 24 | ``` 25 | 26 | RuntimeImage will get the easiest name, not View!T. 27 | 28 | * Pros: 29 | - Allows crossing binary interfaces, like shared libraries and C ABI. 30 | - Simplest thing that works. 31 | - You can avoid to template something by the Color type. This "type-punning" reduce template bloat and compile times. 32 | - Format conversion may need this internally. 33 | - Instruction-cache friendly. 34 | - Not an `interface` so avoid classes and associated woes. 35 | 36 | * Cons: 37 | - Operating on a `RuntimeImage` may require switches and exhaustive work. 38 | - Not an `interface` so inheritance is limited 39 | - templates were inherently "open-method" at compile-time 40 | 41 | - a buffer to render widgets to, is an Image 42 | 43 | - Images should support fast subsets (like slicing an array) 44 | 45 | - an Image should have named color channels for easy indexing 46 | 47 | - Image data should be held by an `IAllocator` 48 | 49 | - Images abstractions are 2D, not 3D, not N-dimensional. 50 | * Pros: 51 | - simple 52 | 53 | * Cons: 54 | - some niche domains need higher dimensional images. 55 | 56 | ## Aspect ratio discussion 57 | 58 | There are multiple aspect ratios: 59 | - Source aspect ratio - shape of the image buffer: `width / height` 60 | - Pixel aspect ratio - aspect ratio of image pixels as presented on the display 61 | - Display aspect ratio - shape picture should appear on screen: `sourceAspectRatio * pixel_aspect_ratio` 62 | 63 | - Various ways to express aspect ratio 64 | 1. Just store `displayAspectRatio` 65 | 2. DPIx:DPIx - `pixelAspectRatio = DPIx / DPIx` 66 | 3. Store `pixelAspectRatio` + `DPIx` 67 | 68 | After discussion, we decided to go with #3, because: 69 | 1. Just storing `displayAspectRatio` omits DPI information, which can be interesting for certain applications 70 | 2. Calculating `pixelAspectRatio` from `DPIx / DPIy` is unreliable, because not all images have DPI information available 71 | - No reasonable defaults for DPI values, they are just arbitrary 72 | - If DPI is zero, then `DPIx / DPIy` is division by zero! 73 | 3. Storing a `pixelAspectRatio` is convenient, and a reasonable default exists (`1.0`) in lieu 74 | - It is valid for either pixel aspect, or DPI, or both, or neither may be present 75 | - Storing a single DPI value is convenient, because most images have matching H/V DPI 76 | - Lossless transformation between representations is convenient 77 | 78 | # Open questions (no vote occured yet) 79 | 80 | - Who owns `RuntimeImage` data? 81 | 82 | - what exactly owns IAllocator? 83 | 84 | - who owns the Image abstraction itself (GC, RC, scoped ownership)? 85 | 86 | - how animated Image would be represented? 87 | -------------------------------------------------------------------------------- /pixel-format-summary.md: -------------------------------------------------------------------------------- 1 | Sumary of Cairo, PIXMAN, Skia, OpenGL, pixel formats + some random thoughts. 2 | 3 | 4 | cairo formats 5 | ============= 6 | 7 | CAIRO_FORMAT_INVALID --- no such format exists or is supported. 8 | 9 | CAIRO_FORMAT_ARGB32 --- each pixel is a 32-bit quantity, with alpha in the upper 8 bits, then red, then green, then blue. The 32-bit quantities are stored native-endian. Pre-multiplied alpha is used. (That is, 50% transparent red is 0x80800000, not 0x80ff0000.) (Since 1.0) 10 | 11 | CAIRO_FORMAT_RGB24 --- each pixel is a 32-bit quantity, with the upper 8 bits unused. Red, Green, and Blue are stored in the remaining 24 bits in that order. (Since 1.0) 12 | 13 | CAIRO_FORMAT_A8 --- each pixel is a 8-bit quantity holding an alpha value. (Since 1.0) 14 | 15 | CAIRO_FORMAT_A1 --- each pixel is a 1-bit quantity holding an alpha value. Pixels are packed together into 32-bit quantities. The ordering of the bits matches the endianness of the platform. On a big-endian machine, the first pixel is in the uppermost bit, on a little-endian machine the first pixel is in the least-significant bit. (Since 1.0) 16 | 17 | CAIRO_FORMAT_RGB16_565 --- each pixel is a 16-bit quantity with red in the upper 5 bits, then green in the middle 6 bits, and blue in the lower 5 bits. (Since 1.2) 18 | 19 | CAIRO_FORMAT_RGB30 --- like RGB24 but with 10bpc. (Since 1.12) 20 | 21 | notes: 22 | 23 | channel and pixel order is dependent on machine endianness. 24 | the RGB24 is actually 32 bits per pixel, 25 | 26 | https://cairographics.org/manual/cairo-Image-Surfaces.html 27 | 28 | 29 | OpenGL 30 | ====== 31 | 32 | Splits format into component list and data type 33 | 34 | data types 35 | 36 | normalized integers, signed and unsigned 37 | floating point 38 | integer, signed and unsinged 39 | 40 | bit depths supported for each type... 41 | 42 | unsigned normalized (no suffix) 21, 42, 53, 8, 103, 122, 16 43 | signed normalized 8, 16 44 | unsigned integral 8, 16, 32 45 | signed integral 8, 16, 32 46 | floating point 16, 32 47 | 48 | components format is limited to 49 | 50 | "R", "RG", "RGB", or "RGBA"; 51 | 52 | some specialised formats that dont fit the above syntax... 53 | 54 | GL_R3_G3_B2: Normalized integer, with 3 bits for R and G, but only 2 for B. 55 | GL_RGB5_A1: 5 bits each for RGB, 1 for Alpha 56 | GL_RGB10_A2: 10 bits each for RGB, 2 for Alpha 57 | GL_R11F_G11F_B10F: This uses special 11 and 10-bit floating-point values. 58 | GL_RGB9_E5: This one is complicated. It is an RGB format of type floating-point. 59 | GL_RGB565: 5 bits each for RB, 6 for G. 60 | 61 | wikipedia page doesnt say anything about byte order / endianness 62 | 63 | notes: 64 | 65 | There's more than what i've listed tbh, depth formats, and other stuff. 66 | 67 | https://www.khronos.org/opengl/wiki/Image_Format 68 | 69 | 70 | PIXMAN 71 | ====== 72 | 73 | has the following pixel types... 74 | 75 | #define PIXMAN_TYPE_OTHER 0 76 | #define PIXMAN_TYPE_A 1 77 | #define PIXMAN_TYPE_ARGB 2 78 | #define PIXMAN_TYPE_ABGR 3 79 | #define PIXMAN_TYPE_COLOR 4 80 | #define PIXMAN_TYPE_GRAY 5 81 | #define PIXMAN_TYPE_YUY2 6 82 | #define PIXMAN_TYPE_YV12 7 83 | #define PIXMAN_TYPE_BGRA 8 84 | #define PIXMAN_TYPE_RGBA 9 85 | #define PIXMAN_TYPE_ARGB_SRGB 10 86 | #define PIXMAN_TYPE_RGBA_FLOAT 11 87 | 88 | then you can define bits per pixel and bits per component, it has a macro that defines the actual enum value so these properties are encoded in the enum... 89 | 90 | 24..31 = bits per pixel 91 | 16..23 = pixel type 92 | 0..3,4..7,8..11,12..15 = bits used for each component 93 | 94 | then actual format enums are encoded thus... 95 | 96 | PIXMAN_a8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,8,8,8,8), 97 | 98 | there's a seperate macro that handles float format since it the main one can only go up to 16 bits per component. 99 | 100 | cant find any info regarding endianness of format 101 | 102 | https://github.com/servo/pixman/blob/master/pixman/pixman.h 103 | 104 | 105 | Skia 106 | ==== 107 | 108 | skia defines alpha type... 109 | 110 | kUnknown_SkAlphaType, 111 | kOpaque_SkAlphaType, 112 | kPremul_SkAlphaType, 113 | kUnpremul_SkAlphaType, 114 | 115 | and components type 116 | 117 | kUnknown_SkColorType, 118 | kAlpha_8_SkColorType, 119 | kRGB_565_SkColorType, 120 | kARGB_4444_SkColorType, 121 | kRGBA_8888_SkColorType, 122 | kRGB_888x_SkColorType, 123 | kBGRA_8888_SkColorType, 124 | kRGBA_1010102_SkColorType, 125 | kRGB_101010x_SkColorType, 126 | kGray_8_SkColorType, 127 | kRGBA_F16_SkColorType, 128 | kRGBA_F32_SkColorType, 129 | kLastEnum_SkColorType = kRGBA_F32_SkColorType, 130 | kN32_SkColorType = kBGRA_8888_SkColorType, 131 | kN32_SkColorType = kRGBA_8888_SkColorType, 132 | 133 | from what I can understand pixels are considered as machine words, ie 16 bits per pixel is considered as a uint16, 64 bits per pixel is a uint64, and the channels are parsed like hex literal, first channel is most significant bits, IE... 134 | 135 | ARGB32, is like 0xAARRGGBB, 136 | 137 | So i guess byte order depends on endieness of the platform, but its not very clear. 138 | notes.. 139 | 140 | First library to mention premultiplied alpha i think 141 | 142 | Doesnt mention and formats that are less that 8 bits per pixel so doesnt have anything to say about ordering for when multiple pixels are encoded into a byte. 143 | 144 | https://skia.org/user/api/SkImageInfo_Reference#SkImageInfo 145 | 146 | 147 | ============================================================= 148 | 149 | thoughts.... 150 | 151 | Useful to have an 'X' component for unused bits, EG.. 152 | XRGB32, top 8 bits are unused. 153 | 154 | component encodings... 155 | unsigned & signed int, various widths 156 | normalized, signed and unsigned int, various widths 157 | float formats, various widths. 158 | OpenGL has some weird formats, 9,11 bit floats. 159 | 160 | Desirable to be able to define both plain alpha and premultiplied alpha. 161 | 162 | Will have to define A,X,R,G,B, something for Gray? What is "YUY2" in pixman list? 163 | 164 | 'P' for premultiplied alpha? 165 | 166 | so PRGB vs ARGB? 167 | 168 | What about indexed formats? EG somthing like.. "I8" = indexed 8 bits per pixel?? 169 | 170 | Need to define how how format strings relates to bit/byte ordering. 171 | The common way to relate component string to ordering is to think of it as hex literal ordering IE... 172 | 173 | ARGB32 ==> 0xAARRGGBB, 174 | so on little endian Alpha is high bits of 32 bit word 175 | so on big endian Alpha is low bits of 32 bit word 176 | 177 | But better to not depend on endieness of system imo. 178 | 179 | also need to consider that where more than one pixel is encoded into a byte the ordering may be different, see CAIRO_FORMAT_A1 180 | 181 | Could have a shorthand format for when bits per component is equal... 182 | 183 | ARGB32, 8 bits each component 184 | RGB24, 8 bits each 185 | XRGB16, 4 bits each, top 4 bits unused 186 | RGB48f, 16 bit float for each 187 | 188 | then long form for where that wont work 189 | 190 | ARGB_2_10_10_10, 2 alpha, 10 each of the rest 191 | RGB_5_6_5, 5 red, 6 green, 5 blue 192 | 193 | long form if you need the weird OpenGL stuff.. 194 | 195 | RGB_10un_12un_10un, 10 bits usigned normalized.. etc... 196 | -------------------------------------------------------------------------------- /png-read-write.md: -------------------------------------------------------------------------------- 1 | # PNG Read/Write 2 | 3 | I only implemented parts of the reader for now so some things from bellow will definitely change a bit in order to support the writer as well. 4 | 5 | ## Structure 6 | 7 | 8 | - wg/format/png 9 | - common.d 10 | - reader.d 11 | - writer.d 12 | 13 | ##### Common.d 14 | 15 | It contains code common for reader and writer: structs that mirror the file records or are part of both APIs, definitions of chunk types and similar. The main API data structure is this: 16 | 17 | ```d 18 | struct Result(T) { 19 | string errorMessage; 20 | T data; 21 | } 22 | 23 | Result!PngHeaderData loadPngHeader(const ubyte[] data); 24 | Result!ImageBuffer loadPng(const ubyte[] data, Allocator* allocator) 25 | Result!ImageBuffer loadPng(const ubyte[] data, Allocator* allocator, Allocator* chunkAllocator, out PngChunks* chunks) 26 | 27 | 28 | // This structure mirrors the file record 29 | align(1) 30 | struct PngHeaderData 31 | { 32 | uint width; 33 | uint height; 34 | PngBitDepth bitDepth; 35 | PngColorType colorType; 36 | PngCompressionMethod compressionMethod; 37 | PngFilterMethod filterMethod; 38 | PngInterlaceMethod interlaceMethod; 39 | } 40 | ``` 41 | 42 | ##### Reader.d 43 | 44 | With the above API you can read just the headers or the whole image. The ImageBuffer would contain raw pixel data from the file and all chunks including the IHDR would be included in metadata. In case raw pixel data is in color type 3 (palette indices), it would actually be depalettized into RGB or RGBA if transparency chunk is also present but those two chunks would still be present in the metadata. The ImageBuffer format could thus end up being: 45 | 46 | - l, l_1, l_2, l_4, l_16 for grayscale images without alpha and without transparency 47 | - la, la_1_1, la_2_2, la_4_4, la_16_16 for grayscale images with alpha or with transparency 48 | - rgb, rgb_16 for palette images without transparency and rgb images 49 | - rgba, rgba_16 for palette images with transparency and rgba images 50 | 51 | Any of these might get "^" where is non standard gamma read from the gamma chunk and "R{x,y}G{x,y}B{x,y}" and "@{x,y}" if there is a cHRM chunk. In case the numbers descibe some standard color space they will be replaced with its name. If there is sRGB chunk, sRGB colorspace is assumed and gAMA and cHRM chunks are ignored. if iCCP chunk is present it is ignored and just stored in a list of chunks. 52 | 53 | The reader should support interlaced images but should not be complicated with a streaming API (where png file is received in parts and read in multiple passes). It also should not be complicated with File API, but assume the png file can always be completely loaded in memory before parsing. 54 | 55 | If user wants to get ImageBuffer in certain format he will have to load one ImageBuffer and then through conversion functions get another ImageBuffer. This will require additional allocation but it makes the reader code and API much simpler. 56 | 57 | We are ok with PngChunks being implemented however for the first version and we can separately discuss later how to improve them, since that goes under "solving the memory ownership and auto allocation and deallocation" part which we need to solve for everything anyway. 58 | 59 | Because of different use and needs additional allocator is given for chunks. All temporary memory buffers should come from stack if possible and from main allocator otherwise. 60 | 61 | ## Open Questions 62 | 63 | 1. Should the API allow loading only some chunks and not just all or nothing? 64 | -------------------------------------------------------------------------------- /research.md: -------------------------------------------------------------------------------- 1 | DLang Graphics Research 2 | ======================= 3 | This is an incomplete list of notable libraries related to graphics & ux. 4 | The list contains libraries useful for both creating graphical applications and designing your own graphics framework. 5 | 6 | 7 | ## Building Blocks 8 | 9 | ### Color 10 | - **std.experimental.color** https://github.com/TurkeyMan/color 11 | 12 | - **arsd/color** https://github.com/adamdruppe/arsd/blob/master/color.d 13 | 14 | - **dlib/image/color** https://github.com/gecko0307/dlib/blob/master/dlib/image/color.d 15 | 16 | 17 | ### Linear Algebra 18 | - **gfm/math** https://github.com/d-gamedev-team/gfm/tree/master/math/gfm/math 19 | 20 | - **gl3n** https://github.com/Dav1dde/gl3n 21 | 22 | - **dlib/math** https://github.com/gecko0307/dlib/tree/master/dlib/math 23 | 24 | 25 | ### Numeric 26 | - **sargon/halfloat** https://github.com/DigitalMars/sargon/blob/master/src/sargon/halffloat.d 27 | Docs: https://digitalmars.com/sargon/halffloat.html 28 | 29 | - **decimal** https://github.com/rumbu13/decimal 30 | 31 | 32 | ### CPU Intrinsics 33 | - **std.simd** https://github.com/TurkeyMan/simd 34 | 35 | - **intel-intrinsics** https://github.com/AuburnSounds/intel-intrinsics 36 | 37 | - **mir-cpuid** https://github.com/libmir/mir-cpuid 38 | 39 | 40 | ### Constraint Solving & Layout 41 | - **Cassowary** https://overconstrained.io 42 | D implementation: https://github.com/yglukhov/cassowary.d 43 | 44 | 45 | 46 | ## GUI 47 | - **Qt** https://www.qt.io 48 | https://github.com/w0rp/dqt 49 | https://github.com/filcuc/dqml 50 | https://github.com/MGWL/QtE5 51 | 52 | - **wxWidgets** https://www.wxwidgets.org 53 | D binding: http://wxd.sourceforge.net 54 | 55 | - **GTK** https://www.gtk.org 56 | D binding: https://gtkd.org 57 | 58 | - **Nanogui** https://github.com/wjakob/nanogui 59 | D port: https://github.com/drug007/nanogui 60 | 61 | - **Nuklear** https://github.com/vurtun/nuklear 62 | D binding: https://github.com/mogud/nukleard 63 | D binding: https://github.com/Timu5/bindbc-nuklear 64 | 65 | - **Dear ImGui** https://github.com/ocornut/imgui 66 | D binding: https://github.com/Extrawurst/DerelictImgui 67 | D binding: https://github.com/0dyl/d-cimgui 68 | D port: https://github.com/d-gamedev-team/dimgui 69 | 70 | - **libui** https://github.com/andlabs/libui 71 | D binding: https://github.com/Extrawurst/DerelictLibui 72 | D wrapper: https://github.com/mogud/libuid 73 | 74 | - **Tcl/Tk** https://www.tcl.tk 75 | D binding: https://github.com/nomad-software/tcltk 76 | D port: https://github.com/nomad-software/tkd 77 | 78 | - **FLTK** https://www.fltk.org 79 | 80 | - **Clutter** https://wiki.gnome.org/Projects/Clutter 81 | 82 | - **IUP** http://iup.sourceforge.net 83 | D binding: https://github.com/carblue/iup 84 | D binding: https://bitbucket.org/alphaglosined/libglosined/src/85ab6b2135879848e7efd5f1dfa732f2cfb753f8/iup 85 | 86 | - **LittlevGL** https://littlevgl.com 87 | 88 | - **Dlang UI** https://github.com/buggins/dlangui 89 | 90 | - **DWT** https://github.com/d-widget-toolkit/dwt 91 | 92 | - **DQuick** https://github.com/D-Quick/DQuick 93 | 94 | - **arsd/minigui** https://github.com/adamdruppe/arsd/blob/master/minigui.d 95 | 96 | - **Poison** https://github.com/PoisonEngine/poison-ui 97 | 98 | - **ae/ui** https://github.com/CyberShadow/ae/tree/master/ui 99 | 100 | 101 | 102 | ## Dialogs 103 | - **Native File Dialog** https://github.com/mlabbe/nativefiledialog 104 | 105 | - **tinyfiledialogs** https://github.com/native-toolkit/tinyfiledialogs 106 | D port: https://github.com/dayllenger/tinyfiledialogs-d 107 | 108 | - **Boxer** https://github.com/aaronmjacobs/Boxer 109 | 110 | 111 | 112 | ## Window & Input & Event 113 | - **SDL** https://www.libsdl.org 114 | D binding: https://github.com/BindBC/bindbc-sdl 115 | 116 | - **GLFW** https://www.glfw.org 117 | D binding: https://github.com/BindBC/bindbc-glfw 118 | 119 | - **libX11** https://www.x.org 120 | D binding: https://github.com/D-Programming-Deimos/libX11 121 | 122 | - **wayland-d** https://github.com/rtbo/wayland-d 123 | 124 | - **SPEW** https://github.com/Devisualization/spew 125 | 126 | - **dplug/window** https://github.com/AuburnSounds/Dplug/tree/master/window/dplug/window 127 | 128 | - **arsd/simpledisplay** https://github.com/adamdruppe/arsd/blob/master/simpledisplay.d 129 | 130 | 131 | 132 | ## Event-Loop 133 | - **libev** http://software.schmorp.de/pkg/libev.html 134 | D binding: https://github.com/D-Programming-Deimos/libev 135 | 136 | - **libuv** https://github.com/libuv/libuv 137 | D binding: https://github.com/raefaldhia/libuv 138 | D binding: https://github.com/tamediadigital/libuv 139 | D binding: https://github.com/changloong/libuv 140 | 141 | - **libevent** https://libevent.org 142 | D binding: https://github.com/D-Programming-Deimos/libevent 143 | 144 | - **eventcore** https://github.com/vibe-d/eventcore 145 | 146 | - **liuev** https://github.com/troglobit/libuev 147 | 148 | - **libasync** https://github.com/etcimon/libasync 149 | 150 | - **arsd/eventloop** https://github.com/adamdruppe/arsd/blob/master/eventloop.d 151 | 152 | - **SPEW** https://github.com/Devisualization/spew 153 | 154 | - **subscribed** https://github.com/v--/subscribed 155 | 156 | 157 | 158 | ## Renderer 159 | 160 | ### High-Level 161 | - **NanoVG** https://github.com/memononen/NanoVG 162 | - D port: https://github.com/adamdruppe/arsd/blob/master/nanovega.d 163 | - Docs: http://dpldocs.info/experimental-docs/arsd.nanovega.html 164 | - Forum: https://forum.dlang.org/thread/yykncywfhvfarrszpqed@forum.dlang.org 165 | - D binding & wrapper: https://github.com/Pctg-x8/nanovg-d 166 | 167 | - **Cairo** https://www.cairographics.org 168 | D binding: https://gtkd.org 169 | D wrapper: https://github.com/cairoD/cairoD 170 | D binding: https://github.com/D-Programming-Deimos/cairo 171 | 172 | - **Skia** https://github.com/google/skia 173 | 174 | 175 | ### Lower-Level 176 | - **OpenGL** https://www.opengl.org 177 | D binding: https://github.com/BindBC/bindbc-opengl 178 | 179 | - **Vulkan** https://www.khronos.org/vulkan 180 | D binding: https://github.com/ParticlePeter/ErupteD 181 | 182 | - **DirectX** https://en.wikipedia.org/wiki/DirectX 183 | D binding: https://github.com/auroragraphics/directx 184 | D binding: https://github.com/evilrat666/directx-d 185 | 186 | - **bgfx** https://github.com/bkaradzic/bgfx 187 | D binding: https://github.com/GoaLitiuM/bindbc-bgfx 188 | 189 | 190 | 191 | ## Image 192 | 193 | ### Image Loading & Saving 194 | - **FreeImage** http://freeimage.sourceforge.net 195 | D binding: https://github.com/BindBC/bindbc-freeimage 196 | 197 | - **stb_image** https://github.com/nothings/stb/blob/master/stb_image.h 198 | 199 | - **SDL_image** https://www.libsdl.org/projects/SDL_image 200 | D binding: https://github.com/BindBC/bindbc-sdl 201 | 202 | - **DevIL** https://github.com/DentonW/DevIL 203 | D binding: https://github.com/DerelictOrg/DerelictIL 204 | 205 | - **libpng** http://www.libpng.org/pub/png/libpng.html 206 | D binding: https://github.com/D-Programming-Deimos/libpng 207 | 208 | - **ImageMagick** https://imagemagick.org 209 | D binding: https://github.com/MikeWey/DMagick 210 | 211 | - **arsd/image** https://github.com/adamdruppe/arsd/blob/master/image.d 212 | 213 | - **dlib/image** https://github.com/gecko0307/dlib/tree/master/dlib/image 214 | 215 | 216 | ### Image Metadata 217 | - **libexif** https://github.com/libexif/libexif 218 | D binding: https://github.com/D-Programming-Deimos/libexif 219 | 220 | 221 | 222 | ## Text 223 | 224 | ### Font Loading & Rasterization 225 | - **FreeType** https://www.freetype.org 226 | D binding: https://github.com/BindBC/bindbc-freetype 227 | 228 | - **stb_truetype** https://github.com/nothings/stb/blob/master/stb_truetype.h 229 | D port: https://github.com/adamdruppe/arsd/blob/master/stb_truetype.d 230 | 231 | - **SDL_ttf** https://www.libsdl.org/projects/SDL_ttf 232 | D binding: https://github.com/BindBC/bindbc-sdl 233 | 234 | - **Glyphy** https://github.com/behdad/glyphy 235 | 236 | - **fontconfig** https://www.freedesktop.org/wiki/Software/fontconfig 237 | 238 | 239 | ### Text Shaping & Layout 240 | - **HarfBuzz** https://www.freedesktop.org/wiki/Software/HarfBuzz 241 | D binding: https://github.com/DlangGraphicsWG/bindbc-harfbuzz 242 | 243 | - **Pango** https://gitlab.gnome.org/GNOME/pango 244 | D binding: https://gtkd.org 245 | 246 | - **FriBidi** https://github.com/fribidi/fribidi 247 | 248 | - **linebreak** https://github.com/s-ludwig/linebreak 249 | 250 | 251 | 252 | ## Integration 253 | - **D-Bus** https://www.freedesktop.org/wiki/Software/dbus 254 | D wrapper: https://github.com/trishume/ddbus 255 | 256 | - **libnotify** https://gitlab.gnome.org/GNOME/libnotify 257 | D binding: https://github.com/D-Programming-Deimos/libnotify 258 | 259 | 260 | 261 | ## Internationalization (i18n) & Localization (l10n) 262 | - **gettext** https://www.gnu.org/software/gettext 263 | 264 | - **djtext** https://github.com/o3o/djtext 265 | 266 | - **i18n-d** https://github.com/JakobOvrum/i18n-d 267 | 268 | - **mofile** https://github.com/FreeSlave/mofile 269 | 270 | 271 | 272 | ## Accesibility 273 | - **ATK** https://gitlab.gnome.org/GNOME/atk 274 | D binding: https://gtkd.org 275 | 276 | 277 | 278 | ## Uncategorized 279 | - **Allegro5** https://github.com/liballeg/allegro5 280 | D binding: https://github.com/DerelictOrg/DerelictAllegro5 281 | D binding: https://github.com/SiegeLord/DAllegro5 282 | 283 | - **SFML** https://www.sfml-dev.org 284 | D binding: https://github.com/DerelictOrg/DerelictSFML2 285 | D binding: https://github.com/Jebbs/DSFML 286 | 287 | - **ae/utils/graphics** https://github.com/CyberShadow/ae/tree/master/utils/graphics 288 | -------------------------------------------------------------------------------- /rgb-format.md: -------------------------------------------------------------------------------- 1 | # RGB format description 2 | 3 | This document describes a format string spec to comprehensively and compactly describe RGB colour spaces. 4 | Complete description data should be encoded in a human-readable/writable string, which may drive the correct rendering of RGB images. 5 | 6 | ## RGB colour properties 7 | 8 | Complete set of properties relating to an RGB colour: 9 | - Components 10 | - Encoding 11 | - Block compression/chroma subsampling strategy 12 | - Gamma compression strategy 13 | - Colour space 14 | - Dynamic range 15 | - Other encoding options 16 | - Swizzling, Endian, user data, etc 17 | 18 | ## RGB format string encoding: 19 | 20 | `"components_[format]_[colourspace]_["BE" big-endian]_[swizzle parameters]_[userdata]"` 21 | 22 | ### `components`: 23 | A set of single character component names: 24 | - `r` `g` `b` - red, green, blue 25 | - `l` - luma/luminance (`r = g = b`) 26 | - `a` - alpha (exempt from colourspace) 27 | - `e` - shared exponent 28 | - `x` - unused bits (may appear multiple times) 29 | 30 | Component names are lower-case. (or should they be upper case? they could be case-insensitive, but then we halve the namespace for future expansion) 31 | 32 | ### `format` [optional]: 33 | Description of the format for each channel, underscore separated for each component 34 | Eg: `rgb_8_8_8`, `bgra_10_10_10_2`, `rgbe_9_9_9_5`, `rgba_s6_f11_4.8_u3` 35 | Encoding options: 36 | - Omitted: 8 bit normalised integer for each component 37 | - Unsigned normalised integer: `8`, `10` 38 | - Signed normalised integer: `s8` 39 | - Floating point: `f32`, `f11` 40 | - Unsigned fixed point: `1.7`, `8.8` 41 | - Signed fixed point: `s2.6`, `s4.4` 42 | - Unsigned integer: `u16` 43 | - Signed integer: `i16` 44 | - Block compression format: `DXT5`, `ETC1`, `ASTC6x6` 45 | - TODO: chroma subsampling strategy... 46 | 47 | Open question: Is a more compact grammar possible? Without separating underscores? 48 | 49 | ### `colourspace` [optional]: 50 | Colour space name or description. 51 | - Omitted: Assume sRGB 52 | - Typical names: `sRGB`, `DCI-P3`, `BT.709`, (documented set) 53 | - Adapted whitepoint using `'@'`: `sRGB@D50` 54 | - Custom gamma using `'^'`: 55 | - gamma 2.2: `[colourspace]^2.2` 56 | - Linear: `[colourspace]^1` 57 | - Use sRGB hybrid gamma ramp: `[colourspace]^sRGB` 58 | - Use xyY vectors: `{0.312,0.329[,1.0]}` 59 | - Custom whitepoint: `sRGB@{0.312,0.329}` 60 | - Custom primaries: `R{0.64,0.33}G{0.3,0.6}B{0.15,0.06}` 61 | - Completely custom colourspace: 62 | - Eg: `R{0.64,0.33}G{0.3,0.6}B{0.15,0.06}@D50^sRGB` 63 | 64 | ### `dynamic range` [optional]: 65 | Currently there is no spec to describe the encoded dynamic range beyond implicit parameters according to a specific colour space (ie, `HDR10`, etc). 66 | 67 | TODO: the industry hasn't really settled on standard expressions. We'll need to do a little more research to decide on a good strategy. 68 | 69 | ### `"BE"` [optional]: 70 | All formats should be read in bit-order, and encoded as little-endian bit-streams. This marker says to emit the bitstream as big-endian. 71 | 72 | It should be noted that this will have the effect of reversing the order of the components when they are byte-aligned, and may appear contrary to a struct with separate element members. 73 | 74 | While `rgb_8_8_8` is equivalent to `bgr_8_8_8_BE`, formats where elements straddle byte boundaries require the `BE` specifier to be expressed correctly. 75 | 76 | Eg: 77 | `rrrrrggg gggbbbbb` - `rgb_565` 78 | `bbbbbggg gggrrrrr` - `bgr_565` 79 | `gggbbbbb rrrrrggg` - `rgb_565_BE` 80 | `gggrrrrr bbbbbggg` - `bgr_565_BE` 81 | 82 | ### `swizzle parameters` [optional]: 83 | TODO: develop an expression for swizzling parameters that cover known hardware. 84 | I think there's no hardware that will fail to be expressed by `[bytes-in-row]:[num-rows]`. 85 | 86 | We could use something like `Z32:16` to specify eg: swizzle tiles of 16 rows of 32bytes. 87 | 88 | ### `userdata` [optional]: 89 | A string of user data starting with `#`, eg: `#userdata-string`. 90 | May not contain `_` characters. 91 | 92 | ## Alternative strategy 93 | 94 | I like `rgb_8_8_8` because it's very readable, and the `8_8_8` can be omitted and inferred for the most common colour formats. 95 | An alternative strategy that eliminates the underscores would be to have the encoding follow the channel immediately, eg: `R8G8B8` 96 | I feel this becomes very difficult to read with longer formats, eg: `R10fG10fB10fA2`, but it is gramatically sound. 97 | --------------------------------------------------------------------------------