Example #1
0
    def testCreateAtlas(self):
        # Verify that atlas is correct based on sampling pixels and output size.
        atlas_settings = montage.SpriteAtlasSettings(img_format='png')
        source_paths = [
            '/some/path/file' + str(i) + '.jpg' for i in range(0, 4)
        ]
        images_with_statuses = [
            (Image.new('RGBA', (50, 50), self.orange_rgb), ''),
            (Image.new('RGBA', (50, 50), self.red_rgb), ''),
            (Image.new('RGBA', (50, 50), self.green_rgb), ''),
            (Image.new('RGBA', (50, 50), self.yellow_rgb), '')
        ]

        atlas_generator = montage.SpriteAtlasGenerator(
            images_with_statuses=images_with_statuses,
            img_src_paths=source_paths,
            atlas_settings=atlas_settings,
            default_img=Image.new('RGBA', (50, 50), self.black_rgb))
        atlases, manifests = atlas_generator.create_atlas()
        atlas = atlases[0]  # Only care about a single atlas
        del manifests

        self.assertEqual(atlas.size, (100, 100))
        # Verify pixels in corners of atlas.
        self.assertEqual(atlas.getpixel((0, 0))[0:3], self.orange_rgb)
        self.assertEqual(atlas.getpixel((99, 0))[0:3], self.red_rgb)
        self.assertEqual(atlas.getpixel((0, 99))[0:3], self.green_rgb)
        self.assertEqual(atlas.getpixel((99, 99))[0:3], self.yellow_rgb)
        # Verify pixels in center of atlas
        self.assertEqual(atlas.getpixel((49, 49))[0:3], self.orange_rgb)
        self.assertEqual(atlas.getpixel((50, 49))[0:3], self.red_rgb)
        self.assertEqual(atlas.getpixel((49, 50))[0:3], self.green_rgb)
        self.assertEqual(atlas.getpixel((50, 50))[0:3], self.yellow_rgb)
Example #2
0
    def testAtlasGeneratorDifferentInputSizes(self):
        # Should raise error if image count does not match source path count.
        atlas_settings = montage.SpriteAtlasSettings(img_format='png')
        source_images_with_statuses = [(Image.new('RGBA', (50, 30)), '')] * 5
        source_paths = [
            '/some/path/file' + str(i) + '.jpg' for i in range(0, 4)
        ]

        with self.assertRaises(ValueError):
            montage.SpriteAtlasGenerator(
                images_with_statuses=source_images_with_statuses,
                img_src_paths=source_paths,
                atlas_settings=atlas_settings,
                default_img=Image.new('RGBA', (50, 30)))
Example #3
0
    def testAtlasGeneratorDifferentImageSizes(self):
        # Should raise error if converted images are different sizes.
        atlas_settings = montage.SpriteAtlasSettings(img_format='png')
        source_images_with_statuses = [(Image.new('RGBA', (50, 30)), ''),
                                       (Image.new('RGBA', (50, 30)), ''),
                                       (Image.new('RGBA', (50, 30)), ''),
                                       (Image.new('RGBA', (50, 10)), '')]
        source_paths = [
            '/some/path/file' + str(i) + '.jpg' for i in range(0, 4)
        ]

        with self.assertRaises(ValueError):
            montage.SpriteAtlasGenerator(
                images_with_statuses=source_images_with_statuses,
                img_src_paths=source_paths,
                atlas_settings=atlas_settings,
                default_img=Image.new('RGBA', (50, 30)))
Example #4
0
    def testCreateAtlasIfNoSizeSpecified(self):
        # Verify that manifests and atlases contains single items.
        # and verify atlas size is correct.
        atlas_settings = montage.SpriteAtlasSettings(img_format='png')
        source_images_with_statuses = [(Image.new('RGBA', (50, 30)), '')] * 20
        source_paths = [
            '/some/path/file' + str(i) + '.jpg' for i in range(0, 20)
        ]

        atlas_generator = montage.SpriteAtlasGenerator(
            images_with_statuses=source_images_with_statuses,
            img_src_paths=source_paths,
            atlas_settings=atlas_settings,
            default_img=Image.new('RGBA', (50, 30)))
        atlases, manifests = atlas_generator.create_atlas()

        self.assertEqual(len(atlases), 1)
        self.assertEqual(atlases[0].size, (250, 150))
        self.assertEqual(len(manifests), 1)
        self.assertEqual(len(manifests[0]), 20)
Example #5
0
    def testCreateAtlasManifestWithImgFailures(self):
        # Verify manifest contains correct data when one image failed.
        atlas_settings = montage.SpriteAtlasSettings(img_format='png')
        source_images_with_statuses = [(Image.new('RGBA',
                                                  (50, 30)), '')] * 3 + [
                                                      (None, 'Failure msg')
                                                  ]
        source_paths = [
            '/some/path/file' + str(i) + '.jpg' for i in range(0, 4)
        ]
        expected_manifest = [{
            'source_image': '/some/path/file0.jpg',
            'offset_x': 0,
            'image_name': 'file0.jpg',
            'offset_y': 0
        }, {
            'source_image': '/some/path/file1.jpg',
            'offset_x': 50,
            'image_name': 'file1.jpg',
            'offset_y': 0
        }, {
            'source_image': '/some/path/file2.jpg',
            'offset_x': 0,
            'image_name': 'file2.jpg',
            'offset_y': 30
        }, {
            'source_image': '/some/path/file3.jpg',
            'offset_x': 50,
            'image_name': 'file3.jpg',
            'offset_y': 30,
            'errors': 'Failure msg'
        }]

        atlas_generator = montage.SpriteAtlasGenerator(
            images_with_statuses=source_images_with_statuses,
            img_src_paths=source_paths,
            atlas_settings=atlas_settings,
            default_img=Image.new('RGBA', (50, 50), self.black_rgb))
        atlases, manifests = atlas_generator.create_atlas()
        del atlases  # linter
        self.assertEqual(manifests[0], expected_manifest)
Example #6
0
def main(argv):
    del argv  # Unused.
    # TODO: Add more flag validations.
    if FLAGS.max_failures is not None and FLAGS.max_failures > 0:
        raise NotImplementedError(
            'Does not yet handle image retrieval/conversion '
            'failures')

    if FLAGS.atlas_width is not None or FLAGS.atlas_height is not None:
        print(FLAGS.atlas_width, FLAGS.atlas_height)
    # raise NotImplementedError(
    #     'Does not yet support specifying an atlas size.')

    if FLAGS.sourcelist is None:
        raise flags.ValidationError(
            'You must specify a list of image sources.')

    bg_color_rgb = _determine_bg_rgb()

    outputdir = FLAGS.output_dir
    if outputdir is None:
        outputdir = os.path.join(os.getcwd())

    image_source_list = atlasmaker_io.read_src_list_csvfile(
        FLAGS.sourcelist, FLAGS.sourcelist_dups_handling)

    # Provide some useful confirmation info about settings to user.
    logging.info(
        'Desired output size in pixels width, height for each image is: '
        '(%d, %d)' % (FLAGS.image_width, FLAGS.image_height))
    logging.info('Image format for Atlas is: %s' % FLAGS.image_format)
    logging.info('Background RGB is set to %s' % str(bg_color_rgb))
    logging.info('Background opacity is set to %d' % FLAGS.image_opacity)
    logging.info(
        'Should we preserve image aspect ratio during conversion? %s' %
        FLAGS.keep_aspect_ratio)

    image_convert_settings = convert.ImageConvertSettings(
        img_format=FLAGS.image_format,
        width=FLAGS.image_width,
        height=FLAGS.image_height,
        bg_color_rgb=bg_color_rgb,
        opacity=FLAGS.image_opacity,
        preserve_aspect_ratio=FLAGS.keep_aspect_ratio,
        resize_if_larger=FLAGS.resize_if_larger)

    # Ensure we can write to the output dir or fail fast.
    atlasmaker_io.create_output_dir_if_not_exist(FLAGS.output_dir)

    # Create default image to be used for images that we can't get or convert.
    if FLAGS.default_image_path is not None:
        logging.info('Using image %s as default image when a specified image '
                     'can\'t be fetched or converted' %
                     FLAGS.default_image_path)
        default_img = parallelize.convert_default_image(
            FLAGS.default_image_path, image_convert_settings)
    else:
        logging.info(
            'No default image for failures specified by user, so just '
            'using the background as the default image.')
        default_img = convert.create_default_image(image_convert_settings)

    # Verify we can write the specified output format, or fail fast.
    try:
        testimage_file_name = '{}.{}'.format('testimage',
                                             str(FLAGS.image_format).lower())
        atlasmaker_io.save_image(default_img,
                                 os.path.join(FLAGS.output_dir,
                                              testimage_file_name),
                                 delete_after_write=True)
        logging.info('Confirmed we can output images in %s format' %
                     FLAGS.image_format)
    except:
        logging.error('Unable to write test image in desired output format. '
                      'Please confirm that \'%s\' is a supported PIL output '
                      'format.' % FLAGS.image_format)
        raise

    # Convert images in parallel.
    logging.info('Scheduling %d tasks.' % len(image_source_list))
    converted_images_with_statuses = parallelize.get_and_convert_images_parallel(
        image_source_list,
        image_convert_settings,
        n_jobs=FLAGS.num_parallel_jobs,
        verbose=FLAGS.parallelization_verbosity,
        allow_truncated_images=FLAGS.use_truncated_images,
        request_timeout=FLAGS.http_request_timeout,
        http_max_retries=FLAGS.http_max_retries)

    sprite_atlas_settings = montage.SpriteAtlasSettings(
        img_format=FLAGS.image_format,
        height=FLAGS.atlas_height,
        width=FLAGS.atlas_width,
        filename=FLAGS.filename)
    # width=FLAGS.atlas_width)

    # Generate the atlas from converted images.
    sprite_atlas_generator = montage.SpriteAtlasGenerator(
        images_with_statuses=converted_images_with_statuses,
        img_src_paths=image_source_list,
        atlas_settings=sprite_atlas_settings,
        default_img=default_img)

    atlases, manifests = sprite_atlas_generator.create_atlas()

    atlasmaker_io.save_atlas_and_manifests(
        outdir=outputdir,
        atlases=atlases,
        manifests=manifests,
        sprite_atlas_settings=sprite_atlas_settings)