File: TextureAtlas.pm

package info (click to toggle)
0ad 0.0.17-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 51,248 kB
  • ctags: 46,933
  • sloc: cpp: 223,208; ansic: 31,240; python: 16,343; perl: 4,083; sh: 1,011; makefile: 915; xml: 733; java: 621; ruby: 229; erlang: 53; sql: 40
file content (93 lines) | stat: -rw-r--r-- 2,342 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package TextureAtlas;

# Incredibly rubbish texture packer

use strict;
use warnings;

use Image::Magick;

sub new
{
    my ($class, $width) = @_;
    my $self = {
        width => $width,
        x => 0,
        y => 0,
        rowheight => 0,
        images => {},
    };
    bless $self, $class;
}

sub add
{
    my ($self, $filename) = @_;
    return if $self->{images}{$filename};

    my $img = new Image::Magick;
    $img->ReadImage($filename);
    my $w = $img->Get("width");
    my $h = $img->Get("height");

    if ($filename =~ /\.tga$/i) {
        for my $y (0..$h-1) {
            for my $x (0..$w-1) {
                my @p = $img->GetPixel(x => $x, y => $y, channel => "RGBA");
                if ($p[0] == $p[2] and $p[1] == 0) {
                    my $a = $p[0] * 1.5;
                    $a = 0.95 if $a > 0.95; # prevent premul ugliness
                    my $c = $a;
                    $img->SetPixel(x => $x, y => $y, color => [$c,$c,$c,$a], channel => "RGBA");
                } else {
                    $img->SetPixel(x => $x, y => $y, color => [$p[0],$p[1],$p[2],0], channel => "RGBA");
                }
            }
        }
    }

    die if $w > $self->{width};
    if ($self->{x} + $w > $self->{width}) {
        $self->{x} = 0;
        $self->{y} += $self->{rowheight};
        $self->{rowheight} = 0;
    }

    $self->{images}{$filename} = { img => $img, w => $w, h => $h, x => $self->{x}, y => $self->{y} };

    $self->{rowheight} = $h if $h > $self->{rowheight};
    $self->{x} += $w;
}

sub finish
{
    my ($self, $filename) = @_;

    my $h = $self->{y} + $self->{rowheight};
    my $hlog = log($h)/log(2);
    $hlog = int($hlog+1) if $hlog != int($hlog);
    $h = 2**$hlog;
    $self->{height} = $h;

    my $image = new Image::Magick;
    $image->Set(size => $self->{width}."x".$h, depth => 8);
    $image->ReadImage("xc:transparent");
    for my $t (values %{ $self->{images} }) {
        $image->Composite(image => $t->{img}, x => $t->{x}, y => $t->{y});
    }
    $image->Write($filename);
}

sub get_texcoords
{
    my ($self, $filename) = @_;
    my $t = $self->{images}{$filename} or die;
    return (
        $t->{x} / $self->{width},
        1 - ($t->{y} / $self->{height}),
        ($t->{x} + $t->{w}) / $self->{width},
        1 - (($t->{y} + $t->{h}) / $self->{height}),
    );
}

1;