Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Batch Processing Images: Conversion between RGB and Indexed
#1
So I had to convert a lot of files from RGB to Indexed pixel format (in order to make them compressed) and doing this by hand is way too tedious. I gathered some python scripts and made few trivial yet useful plugins for Gimp 2 out of it.
In order to use them you need to save these into a file (ex: "batch-convert-indexed.py") and then copy it to Gimp's plugin directory. Plugin path will probably vary between systems but it should be similar to "C:\Program Files\GIMP 2\lib\gimp\2.0\plug-ins" or so.
The last one is a standalone script for erasing color space information on bmp files, it may come in handy at times -since LF2 can't read sprites if color space info is present, sigh...


Screenshots
[Image: 2016-09-10%2015_27_58-Greenshot_zpsdcnzuyrc.png]
[Image: 2016-09-10%2015_25_56-python-fu-batch_co...fdiwgg.png]


Warning
Gimp automatically creates best color palette for images but it may change absolute black areas' color code of some images (particularly pixel based transparent images) which makes LF2 render sprites including black areas. It's highy recommended to back up your sprite folder before proceeding.


batch-convert-indexed.py
    PYTHON-Code:
#!/usr/bin/env python
 
import math, glob, struct
from gimpfu import *
 
gettext.install("gimp20-python", gimp.locale_directory, unicode=True)
 
V4_HEADER_SIZE = 108
COLOR_INFO_SIZE = 68
HEADER_OFF = 14
DATA_OFF_FIELD = 10
SIZE_OFF = 2
 
def strip_color_info(old_bmp_name, new_bmp_name=None):
	if new_bmp_name is None:
		new_bmp_name = old_bmp_name
	data = bytearray(open(old_bmp_name, "rb").read())
	header_size = struct.unpack("I", data[HEADER_OFF: HEADER_OFF + 4])[0]
	if header_size == 108:
		# Remove 68	 - the size for the extra data-chunk from both headers
		data[HEADER_OFF: HEADER_OFF + 4] = struct.pack("I", V4_HEADER_SIZE - COLOR_INFO_SIZE)
		data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4] = struct.pack("I",
			struct.unpack("I",data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4])[0] - COLOR_INFO_SIZE)
		# Offset image data:
		data[HEADER_OFF + header_size - COLOR_INFO_SIZE:] = data[HEADER_OFF + header_size:]
		data[SIZE_OFF: SIZE_OFF + 4] = struct.pack("I", len(data))
	with open(new_bmp_name, "wb") as output_file:
		output_file.write(data)
 
def batch_convert_indexed(pattern):
	for file in glob.glob(pattern):
		image = pdb.gimp_file_load(file, RUN_NONINTERACTIVE)
		drawable = pdb.gimp_image_get_active_layer(image)
		if pdb.gimp_image_base_type(image) != INDEXED:
			pdb.gimp_convert_indexed(image, NO_DITHER, MAKE_PALETTE, 256, False, True, "")
			pdb.gimp_file_save(image, drawable, file, file)
		pdb.gimp_image_delete(image)
		strip_color_info(file)
 
register(
        "batch_convert_indexed",
        "Batch process files and convert to indexed color palette",
        "Batch process files and convert to indexed color palette",
        "NightmareX1337",
        "NightmareX1337",
        "2016",
        "<Toolbox>/LF2 Tools/Batch Convert _Indexed...",
        None,
        [
                (PF_STRING, "pattern", "File Glob", "*.bmp")
        ],
        [],
        batch_convert_indexed)
 
main()


batch-convert-rgb.py
    PYTHON-Code:
#!/usr/bin/env python
 
import math, glob, struct
from gimpfu import *
 
gettext.install("gimp20-python", gimp.locale_directory, unicode=True)
 
V4_HEADER_SIZE = 108
COLOR_INFO_SIZE = 68
HEADER_OFF = 14
DATA_OFF_FIELD = 10
SIZE_OFF = 2
 
def strip_color_info(old_bmp_name, new_bmp_name=None):
	if new_bmp_name is None:
		new_bmp_name = old_bmp_name
	data = bytearray(open(old_bmp_name, "rb").read())
	header_size = struct.unpack("I", data[HEADER_OFF: HEADER_OFF + 4])[0]
	if header_size == 108:
		# Remove 68	 - the size for the extra data-chunk from both headers
		data[HEADER_OFF: HEADER_OFF + 4] = struct.pack("I", V4_HEADER_SIZE - COLOR_INFO_SIZE)
		data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4] = struct.pack("I",
			struct.unpack("I",data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4])[0] - COLOR_INFO_SIZE)
		# Offset image data:
		data[HEADER_OFF + header_size - COLOR_INFO_SIZE:] = data[HEADER_OFF + header_size:]
		data[SIZE_OFF: SIZE_OFF + 4] = struct.pack("I", len(data))
	with open(new_bmp_name, "wb") as output_file:
		output_file.write(data)
 
def batch_convert_rgb(pattern):
	for file in glob.glob(pattern):
		image = pdb.gimp_file_load(file, RUN_NONINTERACTIVE)
		drawable = pdb.gimp_image_get_active_layer(image)
		if pdb.gimp_image_base_type(image) != RGB:
			pdb.gimp_convert_rgb(image)
			pdb.gimp_file_save(image, drawable, file, file)
		pdb.gimp_image_delete(image)
		strip_color_info(file)
 
register(
		"batch_convert_rgb",
		"Batch process files and convert to RGB color palette",
		"Batch process files and convert to RGB color palette",
		"NightmareX1337",
		"NightmareX1337",
		"2016",
		"<Toolbox>/LF2 Tools/Batch Convert _RGB...",
		None,
		[
				(PF_STRING, "pattern", "File Glob", "*.bmp")
		],
		[],
		batch_convert_rgb)
 
main()


batch-strip-color-space-info.py
    PYTHON-Code:
#!/usr/bin/env python
 
import math, glob, struct
from gimpfu import *
 
gettext.install("gimp20-python", gimp.locale_directory, unicode=True)
 
V4_HEADER_SIZE = 108
COLOR_INFO_SIZE = 68
HEADER_OFF = 14
DATA_OFF_FIELD = 10
SIZE_OFF = 2
 
def strip_color_info(old_bmp_name, new_bmp_name=None):
	if new_bmp_name is None:
		new_bmp_name = old_bmp_name
	data = bytearray(open(old_bmp_name, "rb").read())
	header_size = struct.unpack("I", data[HEADER_OFF: HEADER_OFF + 4])[0]
	if header_size == 108:
		# Remove 68	 - the size for the extra data-chunk from both headers
		data[HEADER_OFF: HEADER_OFF + 4] = struct.pack("I", V4_HEADER_SIZE - COLOR_INFO_SIZE)
		data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4] = struct.pack("I",
			struct.unpack("I",data[DATA_OFF_FIELD: DATA_OFF_FIELD + 4])[0] - COLOR_INFO_SIZE)
		# Offset image data:
		data[HEADER_OFF + header_size - COLOR_INFO_SIZE:] = data[HEADER_OFF + header_size:]
		data[SIZE_OFF: SIZE_OFF + 4] = struct.pack("I", len(data))
	with open(new_bmp_name, "wb") as output_file:
		output_file.write(data)
 
def batch_strip_color_space_info(pattern):
	for file in glob.glob(pattern):
		strip_color_info(file)
 
register(
        "batch_strip_color_space_info",
        "Batch process files and strip color space informations",
        "Batch process files and strip color space informations",
        "NightmareX1337",
        "NightmareX1337",
        "2016",
        "<Toolbox>/LF2 Tools/Batch _Strip Color Space Info...",
        None,
        [
                (PF_STRING, "pattern", "File Glob", "*.bmp")
        ],
        [],
        batch_strip_color_space_info)
 
main()


THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Ultimately, my constant dissatisfaction with the way things are becomes the driving force behind everything I do.
[Image: sigline.png]
LF2 IDE - Advanced visual data changer featuring instant data loader
LF2 Sprite Sheet Generator - Template based sprite sheet generator based on Gad's method
[Image: sigline.png]
There is no perfect language, but C++ is the worst.
Reply
Thanks given by: mfc , kairunotabi
#2
Wouldnt it be possible to force adding #000000?
Not rly usable nowadays i think, since BMP is almost dead. Although gj.
Reply
Thanks given by:
#3
(09-13-2016, 07:14 PM)Gad Wrote:  Wouldnt it be possible to force adding #000000?
Not rly usable nowadays i think, since BMP is almost dead. Although gj.

I could not find any way of forcing an individual color to take place in Gimp but it works %90 of the time and when it doesn't, you're better off using RGB for those images. I believe it's doable by manually editing image file (like the way color space stripper works) but it would be a huge hack.

I encourage everyone to add if they have a solution to this.
Ultimately, my constant dissatisfaction with the way things are becomes the driving force behind everything I do.
[Image: sigline.png]
LF2 IDE - Advanced visual data changer featuring instant data loader
LF2 Sprite Sheet Generator - Template based sprite sheet generator based on Gad's method
[Image: sigline.png]
There is no perfect language, but C++ is the worst.
Reply
Thanks given by:




Users browsing this thread: 1 Guest(s)