Module bytemap
Byte-flavored memory bitmap, useful for loading image-style assets from byte streams (and vice versa), where components are integers ranging from 0 to 255.
While bytemaps can be used like Corona's memory bitmap, the latter should be preferred for per-pixel operations. More typical bytemap usage will involve bulk operations, such as reading entire images from memory or network downloads.
To use the plugin, add the following in build.settings
:
plugins = {
["plugin.Bytemap"] = { publisherId = "com.xibalbastudios" }
}
On Android, the AssetReader plugin may also be included to improve file-reading support:
plugins = {
["plugin.Bytemap"] = { publisherId = "com.xibalbastudios" },
["plugin.AssetReader"] = { publisherId = "com.xibalbastudios" }
}
A require("plugin.AssetReader")
will then install support. (Down the road, this will ideally be automatic.)
Sample code is available here.
The Bytes type—specified in a few of the bytemap methods—may be any object that implements ByteReader, including strings.
Functions and sections that begin with (WIP) describe work in progress. These features are not considered stable, but give a reasonable idea of what to expect.
This plugin is designed to be called safely from other Lua processes.
Functions
newTexture (config) | Create a new Bytemap, a two-dimensional memory-structuring mechanism. |
loadTexture (config) | Create and populate a new Bytemap from a JPEG or PNG file. |
Bytemap:BindBlob (blob) | Bind a memory blob to the bytemap, making it the data source. |
Bytemap:Deallocate () | (WIP) Deallocate a bytemap's memory, for instance when no further invalidate()s are needed. |
Bytemap:GetBlob () | Get the memory blob, if any, bound to the bytemap. |
Bytemap:GetBytes (opts) | Get a bytemap's bytes. |
Bytemap:SetBytes (bytes, opts) | Set a bytemap's bytes. |
Functions
- newTexture (config)
-
Create a new Bytemap, a two-dimensional memory-structuring mechanism.
Normally, bytemaps are external textures and thus integrate with Corona's display objects via their
filename
andbaseDir
properties, e.g. in paints, as arguments to display.newImage, etc.Bytes are ordered linearly left-to-right, with rows going top-to-bottom. For instance, a 2 × 2, four-pixel RGBA bytemap would be arranged thus:
R1 G1 B1 A1 | R2 G2 B2 A2 ------------------------- R3 G3 B3 A3 | R4 G4 B4 A4
In flat memory, this will have the pattern
R1 G1 B1 A1 R2 G2 B2 A2 R3 G3 B3 A3 R4 G4 B4 A4
Bytemaps created outside Corona's own process lose the connection with the display hierarchy: invalidate and releaseSelf become no-ops, whereas
filename
andbaseDir
will throw errors if accessed.Parameters:
- config
table
Parameters used to initialize the bytemap:
- format: Underlying data format, which may be
"mask", "rgb", or "rgba" (the default).
The bytemap will have a corresponding bytes_per_pixel of 1, 3, or 4, respectively. - width: Number of pixels wide...
- height: ...and tall.
- is_non_external: If true, the bytemap will be non-external as described above, even in Corona's process.
Bytemaps have (read-only) properties with the same names that supply these values.
- format: Underlying data format, which may be
"mask", "rgb", or "rgba" (the default).
Returns:
-
Bytemap or nil
The new bytemap, or nil on error.
- config
table
Parameters used to initialize the bytemap:
- loadTexture (config)
-
Create and populate a new Bytemap from a JPEG or PNG file.
Compare the details about those image formats here for an idea of what limitations are in place, as this uses similar machinery.
Further details about bytemaps may be found in newTexture's summary.
Parameters:
- config
table
Parameters used to initialize the bytemap:
- filename: Name of file to load. The dimensions will be extracted from the file.
- baseDir: If provided, the directory where filename can be found, cf. system.pathForFile.
- format: As per newTexture. (Importantly, the number of components in the file is not consulted.)
- is_absolute: If true, filename is interpreted as an absolute path (any baseDir is ignored).
Using this is an error on non-desktop platforms. - is_non_external: As per newTexture.
- TODO: A premultiply flag is under consideration.
Returns:
-
Bytemap or nil
The new bytemap, or nil on error.
- config
table
- Bytemap:BindBlob (blob)
-
Bind a memory blob to the bytemap,
making it the data source.
When a blob is first bound, the bytemap's normal memory is deallocated. If a blob is later detached without being replaced, this memory is reallocated, with format-appropriate default bytes.
While not necessary, the bound blob's size should be at least w * h * bytes_per_pixel (cf. newTexture). Otherwise, Bytemap:invalidate and Bytemap:GetBytes must copy the contents into a temporary buffer (padding it with default bytes) and work from that instead, negating many of the blob's benefits.
(N.B. At the moment there is also a leaky abstraction on Windows: an external RGB texture must be promoted to RGBA internally when its width is not a multiple of 4. To deal with this in a sane way, the copy process must also be performed here. This is a workaround until the (reported) issue is fixed.)
A call to Bytemap:SetBytes will detach the blob, though it will reallocate normal memory first and render the blob contents into that. A corollary is that bytemaps regard blobs as read-only, so that locked blobs may be bound without any problems.
Parameters:
- blob optional MemoryBlob Any currently bound blob is detached. If present, blob is then bound.
Returns:
-
MemoryBlob or nil
Previously bound blob, or nil if none was bound.
See also:
- Bytemap:Deallocate ()
-
(WIP) Deallocate a bytemap's memory, for instance when no further invalidate()s
are needed.
This is a convenience method that performs
self:BindBlob(dummy)
, where dummy is a (lazily created) zero-length, fixed-size blob. See Bytemap:BindBlob for details.Returns:
-
MemoryBlob or nil
Previously bound blob, or nil if none was bound.
- Bytemap:GetBlob ()
-
Get the memory blob, if any, bound to the bytemap.
Returns:
-
MemoryBlob or nil
Blob, or nil if none is bound.
See also:
- Bytemap:GetBytes (opts)
-
Get a bytemap's bytes.
More specifically, get the region from (x1, y1) in the upper-left to (x2, y2) in the lower-right. By default, these have values (1, 1) and (width, height) respectively (cf. newTexture), meaning the full bytemap.
Coordinates outside the bytemap will be clipped to stay within bounds. When the whole region lies outside—x1 and x2 are both < 1, for instance—no bytes are available, so a zero-length string is returned.
Parameters:
- opts
optional table
Options for getting bytes, which include:
- format: Output format.
When absent, the requested pixels are returned as-is.
Otherwise, when this is "mask", "rgb", or "rgba", they are converted to the named format (cf. newTexture), lopping off or adding bytes as needed—in the latter case, green and blue channels are padded with0
bytes, alpha with255
.
This may instead be one of "red", "green", "blue", or "alpha", in which case a one-byte-per-pixel result is found by gathering the named component from each of the pixels. If the channel is missing (e.g. the bytemap's format is "mask", but "green" or "alpha" was requested), a zero-length string is returned, indicating "no bytes".
(Since red is the first component, it follows that "red" and "mask" are synonyms.) - x1, y1, x2, y2: Custom region coordinates, cf. the summary.
These are sorted to ensure x1 ≤ x2 and y1 ≤ y2. - get_info: If true, a table is populated with some final results (described below). The value may be a table, in which case it will be the one used; otherwise, a new table is created.
- format: Output format.
Returns:
- string A copy of the requested bytes.
-
optional table
If get_info was provided as an option, the info table.
The final region coordinates will be added under the x1, y1, x2, and y2 fields. In the case of out-of-bounds regions these will be the original values (though sorted).
Additionally, a format field will be assigned one of "mask", "rgb", or "rgba", describing the underlying format of the returned bytes. In particular, if anything other than "rgb" or "rgba" was given as the output format option, this will be "mask".
For within-bounds regions, the returned bytes are to be understood as a (x2 - x1 + 1) × (y2 - y1 + 1)-sized rectangle with bytes_per_pixel (cf. newTexture) corresponding to the output format.
- opts
optional table
- Bytemap:SetBytes (bytes, opts)
-
Set a bytemap's bytes.
The region details largely carry over from Bytemap:GetBytes, although see the note for bytes below. No bytes are written when the region is out-of-bounds.
If too few bytes are provided, the requested region will be clipped against the last line containing pixels. (Color-keyed pixels are considered present for purposes of this analysis.) As many pixels as possible will be written in the final line. Furthermore, any incomplete final pixel is discarded.
Regardless of whether bytes are written, any blob is detached, cf. Bytemap:BindBlob.
Parameters:
- bytes
Bytes
Bytes to assign, interpreted as a (x2 - x1 + 1) × (y2 - y1 + 1)-sized rectangle.
N.B. These are the pre-clipping values of the region coordinates (though sorted).
- opts
optional table
Options for setting bytes, which include:
- format: Format of bytes.
If absent, the bytemap's format is used.
Otherwise, when this is "mask", "rgb", or "rgba", discrepancies are handled as follows: if bytes has more components than the bytemap (cf. newTexture), the extra bytes are not written; with fewer, the additional channels in the bytemap are left alone.
This may instead be one of "red", "green", "blue", or "alpha", in which case bytes is interpreted as having one byte per pixel. Each byte is written to the named channel in the corresponding pixel (this is a no-op if the bytemap has no such channel, cf. the similar note for Bytemap:GetBytes).
Lastly, the format may be "grayscale". Again, bytes is understood to have one per byte per pixel, but now a byte is sent to each non-alpha channel of its target pixel. - x1, y1, x2, y2: Custom region coordinates, cf. the summary.
- colorkey: If this is a Bytes value of one or more bytes, pixels from bytes will be compared
against it. Those that match are skipped, leaving the bytemap contents intact.
If necessary,0
bytes are added to agree with bytes's format, or excess bytes are dropped. - (WIP) extrude: If this is an integer > 0, the pixels along each edge will be extruded so many rows or
columns. Extrusion in a given direction stops if it reaches the side of the bytemap.
Extrusion is performed after writing bytes, ignoring any clipping done for insufficient bytes. - get_info: As per GetBytes.
- format: Format of bytes.
Returns:
-
optional table
The info table, if requested.
The table contents match those for Bytemap:GetBytes, except now they describe the assigned—rather than returned—bytes.
- bytes
Bytes
Bytes to assign, interpreted as a (x2 - x1 + 1) × (y2 - y1 + 1)-sized rectangle.