2 * based on: XreaL's x_r_img_tga.* (http://www.sourceforge.net/projects/xreal/)
6 * Copyright (c) 2002 Tilman Sauerbeck <tsauerbeck@users.sourceforge.net>
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include "libvo/fastmemcpy.h"
35 #include "vd_internal.h"
37 static const vd_info_t info
=
41 "Tilman Sauerbeck, A'rpi",
43 "only 24bpp and 32bpp RGB targa files support so far"
62 unsigned short img_type
;
65 unsigned short height
;
68 unsigned char origin
; /* 0 = lower left, 1 = upper left */
69 unsigned short start_row
;
73 static unsigned int out_fmt
= 0;
75 static int last_w
= -1;
76 static int last_h
= -1;
77 static int last_c
= -1;
80 /* to set/get/query special features/parameters */
81 static int control(sh_video_t
*sh
, int cmd
, void *arg
, ...)
85 case VDCTRL_QUERY_FORMAT
:
86 if (*((int *) arg
) == out_fmt
) return CONTROL_TRUE
;
89 return CONTROL_UNKNOWN
;
93 static int init(sh_video_t
*sh
)
95 sh
->context
= (TGAInfo
*) calloc(1, sizeof(TGAInfo
));
103 static void uninit(sh_video_t
*sh
)
105 TGAInfo
*info
= sh
->context
;
111 /* decode a runlength-encoded tga */
112 static void decode_rle_tga(TGAInfo
*info
, unsigned char *data
, mp_image_t
*mpi
)
114 int row
, col
, replen
, i
, num_bytes
= info
->bpp
/ 8;
115 unsigned char repetitions
, packet_header
, *final
;
117 /* see line 207 to see why this loop is set up like this */
118 for (row
= info
->start_row
; (!info
->origin
&& row
) || (info
->origin
&& row
< info
->height
); row
+= info
->increment
)
120 final
= mpi
->planes
[0] + mpi
->stride
[0] * row
;
122 for (col
= 0; col
< info
->width
; col
+= repetitions
)
124 packet_header
= *data
++;
125 repetitions
= (1 + (packet_header
& 0x7f));
126 replen
= repetitions
* num_bytes
;
128 if (packet_header
& 0x80) /* runlength encoded packet */
130 memcpy(final
, data
, num_bytes
);
132 // Note: this will be slow when DR to vram!
135 memcpy(final
+i
,final
,i
);
138 memcpy(final
+i
,final
,replen
-i
);
141 else /* raw packet */
143 fast_memcpy(final
, data
, replen
);
155 static void decode_uncompressed_tga(TGAInfo
*info
, unsigned char *data
, mp_image_t
*mpi
)
157 unsigned char *final
;
158 int row
, num_bytes
= info
->bpp
/ 8;
160 /* see line 207 to see why this loop is set up like this */
161 for (row
= info
->start_row
; (!info
->origin
&& row
) || (info
->origin
&& row
< info
->height
); row
+= info
->increment
)
163 final
= mpi
->planes
[0] + mpi
->stride
[0] * row
;
164 fast_memcpy(final
, data
, info
->width
* num_bytes
);
165 data
+= info
->width
* num_bytes
;
172 static short read_tga_header(unsigned char *buf
, TGAInfo
*info
)
174 info
->id_len
= buf
[0];
176 info
->img_type
= buf
[2];
178 /* targa data is always stored in little endian byte order */
179 info
->width
= le2me_16(*(unsigned short *) &buf
[12]);
180 info
->height
= le2me_16(*(unsigned short *) &buf
[14]);
184 info
->origin
= (buf
[17] & 0x20) >> 5;
186 /* FIXME check for valid targa data */
193 static mp_image_t
*decode(sh_video_t
*sh
, void *raw
, int len
, int flags
)
195 TGAInfo
*info
= sh
->context
;
196 unsigned char *data
= raw
;
201 return NULL
; /* skip frame */
203 read_tga_header(data
, info
); /* read information about the file */
206 out_fmt
= IMGFMT_BGR24
;
207 else if (info
->bpp
== 32)
208 out_fmt
= IMGFMT_BGR32
;
211 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
, "Unsupported TGA type! depth=%d\n",info
->bpp
);
215 if (info
->img_type
!= TGA_UNCOMP_TRUECOLOR
&& info
->img_type
!= TGA_RLE_TRUECOLOR
) /* not a true color image */
217 mp_msg(MSGT_DECVIDEO
, MSGL_INFO
, "Unsupported TGA type: %i!\n", info
->img_type
);
221 /* if img.origin is 0, we decode from bottom to top. if it's 1, we decode from top to bottom */
222 info
->start_row
= (info
->origin
) ? 0 : info
->height
- 1;
223 info
->increment
= (info
->origin
) ? 1 : -1;
225 /* set data to the beginning of the image data */
226 data
+= 18 + info
->id_len
;
228 /* (re)init libvo if image parameters changed (width/height/colorspace) */
229 if (last_w
!= info
->width
|| last_h
!= info
->height
|| last_c
!= out_fmt
)
231 last_w
= info
->width
;
232 last_h
= info
->height
;
235 if (!out_fmt
|| !mpcodecs_config_vo(sh
, info
->width
, info
->height
, out_fmt
))
239 if (!(mpi
= mpcodecs_get_image(sh
, MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_STRIDE
, info
->width
, info
->height
)))
242 /* finally decode the image */
243 if (info
->img_type
== TGA_UNCOMP_TRUECOLOR
)
244 decode_uncompressed_tga(info
, data
, mpi
);
245 else if (info
->img_type
== TGA_RLE_TRUECOLOR
)
246 decode_rle_tga(info
, data
, mpi
);