Repository navigation
PictureProcessor
The PictureProcessor utility is designed to help take exports of 3D models and convert them into Factorio textures with associated suggested alignment values for the offset. It also calculates alignment between a 3D model's export and the associated shadow export.
The PictureProcessor has two primary modes: one texture and multi-textures. It detects between them automatically depending on the provided input. The structure of the command is as follows:
Description:
A utility for processing pictures for Factorio mods.
Usage:
PictureProcessor [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
--textures (REQUIRED) One or more texture files to process.
--shadow A shadow image file to process.
--variants The number of variants in a sprite sheet. [default: 1]
--scale Scale factor for resizing images. [default: 1]
--alignment Alignment for image placement. [default: (0, 0)]Example usage is as follows:
.\PictureProcessor --textures ./Downloads/my-texture-with-variants.png --shadow --variants 5 --scale 1.2 --alignment bottom-centerThe single texture mode is very similar to the multi-texture mode, so below is only described the multi-texture mode. To do single texture mode, only provide one file for --textures and ensure you do not use the --variants parameter.
For the following example, our directory structure will look as follows:
Graphics/
PictureProcessor.exe
WoodenFence/
wooden-fence-horizontal-shadow.png
wooden-fence-horizontal-variant1.png
wooden-fence-horizontal-variant2.png
wooden-fence-horizontal-variant3.png
wooden-fence-horizontal-variant4.png
wooden-fence-horizontal-variant5.pngSome things to note about how the program works:
- When using the
--variantsflag, the picture processor will automatically take your provided input file and append "-variant#" to the end of the file name. - When a file path is not provided to the
--shadowflag, a "-shadow" will be appended to your provided input file.
For clarity, here is what the wooden-fence-horizontal-variant1.png file may potentially look like:
And here's what the associated wooden-fence-horizontal-shadow.png file might look like:
Notice how each of these images are raw Blender exports, and are square with transparency. Additionally, take note that the shadow's positioning within the image can be perfectly overlayed with the variant's model export. These are vital traits of the input files for the program to work correctly.
Now we want to process these pictures to be used in a Factorio texture, such as an entity. In this example, we have 5 variants of the "wooden-fence-horizontal" texture. We want to scale the texture to be 1.2-times the scale of a Factorio tile (64x64 pixels) (so it expands slightly outside of the tile), and we want to anchor the texture to the bottom-center (meaning the expanded part of the tile will be upwards and horizontally, not downwards).
Here is what our command would look like:
.\PictureProcessor --textures ./WoodenFence/wooden-fence-horizontal.png --shadow --variants 5 --scale 1.2 --alignment bottom-centerNotice how our input texture is "wooden-fence-horizontal.png". Even though this texture does not technically exist, because we are using the --variants flag, we only use variants of the texture rather than the provided file itself.
If we instead wanted to provide each variant individually, we could also do so:
.\PictureProcessor --textures ./WoodenFence/wooden-fence-horizontal-variant1.png ./WoodenFence/wooden-fence-horizontal-variant2.png ./WoodenFence/wooden-fence-horizontal-variant3.png --shadow ./WoodenFence/wooden-fence-horizontal-shadow.png --scale 1.2 --alignment bottom-centerThe output of our command will appear as follows:
Loaded image: [fullpath]\Graphics\WoodenFence\wooden-fence-horizontal-variant1.png (2048x2048)
Loaded image: [fullpath]\Graphics\WoodenFence\wooden-fence-horizontal-variant2.png (2048x2048)
Loaded image: [fullpath]\Graphics\WoodenFence\wooden-fence-horizontal-variant3.png (2048x2048)
Loaded image: [fullpath]\Factorio\Graphics\WoodenFence\wooden-fence-horizontal-variant4.png (2048x2048)
Loaded image: [fullpath]\Factorio\Graphics\WoodenFence\wooden-fence-horizontal-variant5.png (2048x2048)
Loaded shadow: [fullpath]\Graphics\WoodenFence\wooden-fence-horizontal-shadow.png (2048x2048)
Trimmed whitespace, cropped image 1 to: 815x833
Resized image 1 to: 75x77
Trimmed whitespace, cropped image 2 to: 815x833
Resized image 2 to: 75x77
Trimmed whitespace, cropped image 3 to: 815x833
Resized image 3 to: 75x77
Trimmed whitespace, cropped image 4 to: 815x833
Resized image 4 to: 75x77
Trimmed whitespace, cropped image 5 to: 815x833
Resized image 5 to: 75x77
Trimmed whitespace, cropped shadow to: 1345x711
Resized shadow to: 124x66
Loaded spritesheet: 375x77
Individual sprite size: 75x77
Variation count: 5
Line length: 5
Shadow repeat: 5
Using alignment: (0.5, 1.0)
Suggested offset for image alignment: (-0, -3.25)
Suggested offset for shadow alignment: (15.25, 27)And two new files will be written to disk:
wooden-fence-horizontal-variant1-processed.png
wooden-fence-horizontal-shadow-processed.png
These files are your new texture files which can be used directly in your mod.
In addition to the files, the output provides us with some extremely helpful information based on our inputs. The reason we provide an --alignment argument is to help us position the texture and shadow correctly in the game.
Factorio will automatically center-align all images regardless of size within a tile. By scaling and providing an alignment value, the
PictureProcessorcan mathematically determine the offsets we need to provide based on the processed output to align the two images correctly within the game.
The values that will matter to us here are the "Suggested offset for image alignment" and "Suggested offset for shadow alignment." For example, in the wooden fence, we might have a picture field which is based on the wall, like so:
layers = {
{
filename = "__base__/graphics/entity/wall/wall-single.png",
priority = "extra-high",
width = 64,
height = 86,
variation_count = 2,
line_length = 2,
shift = util.by_pixel(0, -5),
scale = 0.5
},
{
filename = "__base__/graphics/entity/wall/wall-single-shadow.png",
priority = "extra-high",
width = 98,
height = 60,
repeat_count = 2,
shift = util.by_pixel(10, 17),
draw_as_shadow = true,
scale = 0.5
}
}We'll need to update the filename, width, height, variation_count/line_length/repeat_count, and shift values.
- The
filenamewill be dependent on the texture file relative to your mod. For our purposes, we'll assume it's at "ourmod/[filename]". - The
widthandheightare provided by the "Resized shadow to" output and the "Individual sprite size" output (for variations) or the "Resized image to" (for single). - The
variation_count,line_length, andrepeat_countwill all be the same value, which is the total number of variations passed to the command. In our example, we'll set these to5. - The
shiftvalues are provided by the suggested alignment values discussed earlier.
Taking this information to process the previous response, our new outputted file would appear as follows:
layers = {
{
filename = "__ourmod__wooden-fence-horizontal.png",
priority = "extra-high",
width = 75,
height = 77,
variation_count = 5,
line_length = 5,
shift = util.by_pixel(0, -3.25),
scale = 0.5
},
{
filename = "__ourmod__wooden-fence-shadow.png",
priority = "extra-high",
width = 124,
height = 66,
repeat_count = 5,
shift = util.by_pixel(15.25, 27),
draw_as_shadow = true,
scale = 0.5
}
}And just like that, you now have your new textures right where they need to be in the game. This greatly simplifies the process of manually performing the mathematical calculations needed to determine the correct offsets in addition to the constant opening and closing of the game to get just the right pixel value offsets.