<commit_before>"""Script for encoding a payload into an image."""

import argparse
import pathlib

from PIL import Image, ImageMath

import utilities


def argument_parser():
    # type: () -> argparse.ArgumentParser
    """Returns a configured argparser.ArgumentParser for this program."""
    parser = argparse.ArgumentParser(
        description='Encode SECRETS into a picture',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument(
        'host_image',
        type=pathlib.Path,
        help='The image that will hide the information.')
    parser.add_argument(
        'payload_image',
        type=pathlib.Path,
        help='The image that will be hidden within the host image.')
    parser.add_argument(
        '--least_significant_digits',
        type=int,
        default=1,
        help='The number of least significant digits available to encode over.')
    parser.add_argument(
        '--display',
        action='store_true',
        default=False,
        help='Display the encoded image generated by this program.')
    parser.add_argument(
        '--save',
        action='store_true',
        help='Save the encoded image generated by this program.')
    parser.add_argument(
        '--output_dir',
        type=pathlib.Path,
        default='.',
        help=(
            'A specific location to which the processed image will be saved. '
            'If not specified, the current working directory will be used.'))

    return parser


def encode(host, payload, n_significant_digits):
    # type: (PIL.Image, PIL.Image, int) -> PIL.Image
    """Encode a payload into an image (using the last n_significant_digits)."""
    output_rgb_channels = []
    for host_channel, payload_channel in zip(host.split(), payload.split()):
        # Mask out all but the least significant byte, encoding payload there
        mask = utilities.bit_mask(n_significant_digits)
        expression = (
            "convert("
                "(host & (0xff - {mask})) | (payload & {mask}), 'L')".format(
                    mask=mask))
        output_rgb_channels.append(
            ImageMath.eval(
                expression,
                host=host_channel,
                payload=payload_channel))
    return Image.merge('RGB', output_rgb_channels)


def main():
    args = argument_parser().parse_args()

    host = Image.open(args.host_image)
    payload = Image.open(args.payload_image)

    encoded = encode(host, payload, args.least_significant_digits)

    # Display the encoded image
    if args.display:
        encoded.show()

    # Save the encoded image, if the user wants us to
    if args.save:
        user_response = (
            utilities.query_user(
                'GONNA SAVE ENCODED IMAGE to "{0:s}"; GAR, IS THAT K???'.format(
                    str(args.output_dir.absolute()))))
        if user_response:
            p = args.host_image  # Short reference to the host_image path
            filename = '{0:s}{1:s}{2:s}'.format(p.stem, '.encoded', p.suffix)
            encoded.save(args.output_dir.joinpath(filename), format='jpeg')


if __name__ == '__main__':
    main()
<commit_msg>Change a flag name to be nicer.<commit_after>"""Script for encoding a payload into an image."""

import argparse
import pathlib

from PIL import Image, ImageMath

import utilities


def argument_parser():
    # type: () -> argparse.ArgumentParser
    """Returns a configured argparser.ArgumentParser for this program."""
    parser = argparse.ArgumentParser(
        description='Encode SECRETS into a picture',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument(
        'host_image',
        type=pathlib.Path,
        help='The image that will hide the information.')
    parser.add_argument(
        'payload_image',
        type=pathlib.Path,
        help='The image that will be hidden within the host image.')
    parser.add_argument(
        '--significant_digits',
        type=int,
        default=1,
        help='The number of least significant digits available to encode over.')
    parser.add_argument(
        '--display',
        action='store_true',
        default=False,
        help='Display the encoded image generated by this program.')
    parser.add_argument(
        '--save',
        action='store_true',
        help='Save the encoded image generated by this program.')
    parser.add_argument(
        '--output_dir',
        type=pathlib.Path,
        default='.',
        help=(
            'A specific location to which the processed image will be saved. '
            'If not specified, the current working directory will be used.'))

    return parser


def encode(host, payload, n_significant_digits):
    # type: (PIL.Image, PIL.Image, int) -> PIL.Image
    """Encode a payload into an image (using the last n_significant_digits)."""
    output_rgb_channels = []
    for host_channel, payload_channel in zip(host.split(), payload.split()):
        # Mask out all but the least significant byte, encoding payload there
        mask = utilities.bit_mask(n_significant_digits)
        expression = (
            "convert("
                "(host & (0xff - {mask})) | (payload & {mask}), 'L')".format(
                    mask=mask))
        output_rgb_channels.append(
            ImageMath.eval(
                expression,
                host=host_channel,
                payload=payload_channel))
    return Image.merge('RGB', output_rgb_channels)


def main():
    args = argument_parser().parse_args()

    host = Image.open(args.host_image)
    payload = Image.open(args.payload_image)

    encoded = encode(host, payload, args.significant_digits)

    # Display the encoded image
    if args.display:
        encoded.show()

    # Save the encoded image, if the user wants us to
    if args.save:
        user_response = (
            utilities.query_user(
                'GONNA SAVE ENCODED IMAGE to "{0:s}"; GAR, IS THAT K???'.format(
                    str(args.output_dir.absolute()))))
        if user_response:
            p = args.host_image  # Short reference to the host_image path
            filename = '{0:s}{1:s}{2:s}'.format(p.stem, '.encoded', p.suffix)
            encoded.save(args.output_dir.joinpath(filename), format='jpeg')


if __name__ == '__main__':
    main()

{'fraction_non_alphanumeric': 0.10701865317736327, 'fraction_numerical': 0.0018969332911792601, 'mean_word_length': 2.457377049180328, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5161623', 'n_tokens_mistral': 1794, 'n_tokens_neox': 1722, 'n_words': 500}