Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / cinelerra / filetga.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "bcsignals.h"
24 #include "edit.h"
25 #include "filetga.h"
26 #include "language.h"
27 #include "mwindow.inc"
28 #include "vframe.h"
29 #include "mainerror.h"
30
31 #include <string.h>
32 #include <unistd.h>
33
34 /* Known image types. */
35 #define TGA_TYPE_MAPPED      1
36 #define TGA_TYPE_COLOR       2
37 #define TGA_TYPE_GRAY        3
38
39 /* Only known compression is RLE */
40 #define TGA_COMP_NONE        0
41 #define TGA_COMP_RLE         1
42
43
44 FileTGA::FileTGA(Asset *asset, File *file)
45  : FileList(asset, file, "TGALIST", ".tga", FILE_TGA, FILE_TGA_LIST)
46 {
47         temp = 0;
48 }
49
50 FileTGA::~FileTGA()
51 {
52         if(temp) delete temp;
53 }
54
55 int FileTGA::check_sig(Asset *asset)
56 {
57
58
59 // Test file extension
60         int result = 0;
61         char *ext = strrchr(asset->path, '.');
62
63         if(ext)
64         {
65
66                 if(!strncasecmp(ext, ".tga", 4)) result = 1;
67
68         }
69
70
71
72 // Test for list
73         if(!result)
74         {
75                 FILE *stream;
76                 if(!(stream = fopen(asset->path, "rb")))
77                 {
78 // file not found
79                         result = 0;
80                 }
81                 else
82                 {
83                         char test[16];
84                         (void)fread(test, 16, 1, stream);
85                         fclose(stream);
86                         if(test[0] == 'T' && test[1] == 'G' && test[2] == 'A' &&
87                                 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' &&
88                                 test[6] == 'T')
89                         {
90                                 result = 1;
91                         }
92
93                 }
94         }
95
96
97         return result;
98 }
99
100 void FileTGA::get_parameters(BC_WindowBase *parent_window,
101                 Asset *asset,
102                 BC_WindowBase* &format_window,
103                 int audio_options,
104                 int video_options)
105 {
106         if(video_options)
107         {
108                 TGAConfigVideo *window = new TGAConfigVideo(parent_window, asset);
109                 format_window = window;
110                 window->create_objects();
111                 window->run_window();
112                 delete window;
113         }
114 }
115
116 #if 0
117 N_("RGB compressed")
118 N_("RGBA compressed")
119 N_("RGB uncompressed")
120 N_("RGBA uncompressed")
121 #endif
122
123 #define TGA_RGB_RLE "rle "
124 #define TGA_RGBA_RLE "rlea"
125 #define TGA_RGB "raw "
126 #define TGA_RGBA "rawa"
127
128 #define TGA_RGB_RLE_NAME "RGB compressed"
129 #define TGA_RGBA_RLE_NAME "RGBA compressed"
130 #define TGA_RGB_NAME "RGB uncompressed"
131 #define TGA_RGBA_NAME "RGBA uncompressed"
132
133 const char* FileTGA::compression_to_str(const char *compression)
134 {
135         if(!strcasecmp(compression, TGA_RGB_RLE)) return _(TGA_RGB_RLE_NAME);
136         if(!strcasecmp(compression, TGA_RGBA_RLE)) return _(TGA_RGBA_RLE_NAME);
137         if(!strcasecmp(compression, TGA_RGB)) return _(TGA_RGB_NAME);
138         if(!strcasecmp(compression, TGA_RGBA)) return _(TGA_RGBA_NAME);
139         return TGA_RGB_NAME;
140 }
141
142 const char* FileTGA::str_to_compression(const char *string)
143 {
144         if(!strcasecmp(compression_to_str(TGA_RGB_RLE), string)) return TGA_RGB_RLE;
145         if(!strcasecmp(compression_to_str(TGA_RGBA_RLE), string)) return TGA_RGBA_RLE;
146         if(!strcasecmp(compression_to_str(TGA_RGB), string)) return TGA_RGB;
147         if(!strcasecmp(compression_to_str(TGA_RGBA), string)) return TGA_RGBA;
148         return TGA_RGB;
149 }
150
151 int FileTGA::can_copy_from(Asset *asset, int64_t position)
152 {
153         if(asset->format == FILE_TGA_LIST ||
154                 asset->format == FILE_TGA)
155                 return 1;
156
157         return 0;
158 }
159
160
161 int  FileTGA::colormodel_supported(int colormodel)
162 {
163         return colormodel;
164 }
165
166 int FileTGA::get_best_colormodel(Asset *asset, int driver)
167 {
168         if(!strcasecmp(asset->vcodec, TGA_RGB_RLE) ||
169                 !strcasecmp(asset->vcodec, TGA_RGB)) return BC_RGB888;
170         if(!strcasecmp(asset->vcodec, TGA_RGBA_RLE) ||
171                 !strcasecmp(asset->vcodec, TGA_RGBA)) return BC_RGBA8888;
172         return BC_RGB888;
173 }
174
175 int FileTGA::read_frame(VFrame *frame, VFrame *data)
176 {
177         read_tga(asset, frame, data, temp);
178         return 0;
179 }
180
181 int FileTGA::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
182 {
183         TGAUnit *tga_unit = (TGAUnit*)unit;
184
185         write_tga(asset, frame, data, tga_unit->temp);
186         return 0;
187 }
188
189 FrameWriterUnit* FileTGA::new_writer_unit(FrameWriter *writer)
190 {
191         return new TGAUnit(this, writer);
192 }
193
194 int64_t FileTGA::get_memory_usage()
195 {
196         int64_t result = FileList::get_memory_usage();
197         if(temp) result += temp->get_data_size();
198         return result;
199 }
200
201
202
203
204
205
206
207
208 #define FOOTERSIZE 26
209 #define HEADERSIZE 18
210 int FileTGA::read_frame_header(char *path)
211 {
212         int result = 0;
213
214 //printf("FileTGA::read_frame_header 1\n");
215         FILE *stream;
216
217         if(!(stream = fopen(path, "rb")))
218         {
219                 eprintf(_("Error while opening \"%s\" for reading. \n%m\n"), asset->path);
220                 return 1;
221         }
222
223         unsigned char header[HEADERSIZE];
224         (void)fread(header, HEADERSIZE, 1, stream);
225         fclose(stream);
226
227         asset->width = header[12] | (header[13] << 8);
228         asset->height = header[14] | (header[15] << 8);
229         int bpp = header[16];
230         int rle = header[2] & 0x8;
231         switch(bpp)
232         {
233                 case 32:
234                         if(rle)
235                                 strcpy(asset->vcodec, TGA_RGBA_RLE);
236                         else
237                                 strcpy(asset->vcodec, TGA_RGBA);
238                         break;
239                 case 24:
240                         if(rle)
241                                 strcpy(asset->vcodec, TGA_RGB_RLE);
242                         else
243                                 strcpy(asset->vcodec, TGA_RGB);
244                         break;
245         }
246 //printf("FileTGA::read_frame_header 2 %d %d\n", asset->width, asset->height);
247
248         return result;
249 }
250
251 void FileTGA::read_tga(Asset *asset, VFrame *frame, VFrame *data, VFrame* &temp)
252 {
253 // Read header
254         int64_t file_offset = 0;
255
256 //      unsigned char *footer = data->get_data() +
257 //              data->get_compressed_size() - FOOTERSIZE;
258         unsigned char *header = data->get_data();
259         file_offset += HEADERSIZE;
260
261         int image_type = 0;
262         int image_compression = 0;
263         switch(header[2])
264         {
265                 case 1:
266                         image_type = TGA_TYPE_MAPPED;
267                         image_compression = TGA_COMP_NONE;
268                         break;
269                 case 2:
270                         image_type = TGA_TYPE_COLOR;
271                         image_compression = TGA_COMP_NONE;
272                         break;
273                 case 3:
274                         image_type = TGA_TYPE_GRAY;
275                         image_compression = TGA_COMP_NONE;
276                         break;
277                 case 9:
278                         image_type = TGA_TYPE_MAPPED;
279                         image_compression = TGA_COMP_RLE;
280                         break;
281                 case 10:
282                         image_type = TGA_TYPE_COLOR;
283                         image_compression = TGA_COMP_RLE;
284                         break;
285                 case 11:
286                         image_type = TGA_TYPE_GRAY;
287                         image_compression = TGA_COMP_RLE;
288                         break;
289         }
290
291         int idlength = header[0];
292         int colormaptype = header[1];
293         //int colormapindex = header[3] + header[4] * 256;
294         int colormaplength = header[5] + header[6] * 256;
295         int colormapsize = header[7];
296         //int xorigin = header[8] + header[9] * 256;
297         //int yorigin = header[10] + header[11] * 256;
298         int width = header[12] + header[13] * 256;
299         int height = header[14] + header[15] * 256;
300         int bpp = header[16];
301         int bytes = (bpp + 7) / 8;
302         int alphabits = header[17] & 0x0f;
303         int fliphoriz = (header[17] & 0x10) ? 1 : 0;
304         int flipvert = (header[17] & 0x20) ? 0 : 1;
305         int data_size = data->get_compressed_size();
306
307         if(idlength) file_offset += idlength;
308
309 // Get colormap
310         unsigned char *tga_cmap;
311         unsigned char colormap[4 * 256];
312
313         if(colormaptype == 1)
314         {
315                 int cmap_bytes = (colormapsize + 7) / 8;
316                 tga_cmap = data->get_data() + file_offset;
317                 file_offset += colormaplength * cmap_bytes;
318
319                 switch(colormapsize)
320                 {
321                         case 32:
322                                 bgr2rgb(colormap, tga_cmap, colormaplength, cmap_bytes, 1);
323                                 break;
324                         case 24:
325                                 bgr2rgb(colormap, tga_cmap, colormaplength, cmap_bytes, 0);
326                                 break;
327                         case 16:
328                                 upsample(colormap, tga_cmap, colormaplength, cmap_bytes);
329                                 break;
330                 }
331         }
332
333         int source_cmodel = BC_RGB888;
334         switch(bpp)
335         {
336                 case 32:
337                         source_cmodel = BC_RGBA8888;
338                         break;
339                 case 24:
340                         source_cmodel = BC_RGB888;
341                         break;
342         }
343
344 // Read image
345         VFrame *output_frame;
346         if(frame->get_color_model() == source_cmodel)
347         {
348                 output_frame = frame;
349         }
350         else
351         {
352                 if(temp && temp->get_color_model() != source_cmodel)
353                 {
354                         delete temp;
355                         temp = 0;
356                 }
357
358                 if(!temp)
359                 {
360                         temp = new VFrame(0, -1, width, height, source_cmodel, -1);
361                 }
362                 output_frame = temp;
363         }
364
365         if(flipvert)
366         {
367                 for(int i = height - 1; i >= 0; i--)
368                 {
369                         read_line(output_frame->get_rows()[i],
370                                 data->get_data(),
371                                 file_offset,
372                                 image_type,
373                                 bpp,
374                                 image_compression,
375                                 bytes,
376                                 width,
377                                 fliphoriz,
378                                 alphabits,
379                                 data_size);
380                 }
381         }
382         else
383         {
384                 for(int i = 0; i < height; i++)
385                 {
386                         read_line(output_frame->get_rows()[i],
387                                 data->get_data(),
388                                 file_offset,
389                                 image_type,
390                                 bpp,
391                                 image_compression,
392                                 bytes,
393                                 width,
394                                 fliphoriz,
395                                 alphabits,
396                                 data_size);
397                 }
398         }
399
400         if(output_frame != frame)
401         {
402                 BC_CModels::transfer(frame->get_rows(),
403                         output_frame->get_rows(),
404                         frame->get_y(),
405                         frame->get_u(),
406                         frame->get_v(),
407                         output_frame->get_y(),
408                         output_frame->get_u(),
409                         output_frame->get_v(),
410                         0,
411                         0,
412                         width,
413                         height,
414                         0,
415                         0,
416                         frame->get_w(),
417                         frame->get_h(),
418                         output_frame->get_color_model(),
419                         frame->get_color_model(),
420                         0,
421                         width,
422                         frame->get_w());
423         }
424 }
425
426 void FileTGA::write_tga(Asset *asset, VFrame *frame, VFrame *data, VFrame* &temp)
427 {
428         unsigned char header[18];
429         //unsigned char footer[26];
430         int64_t file_offset = 0;
431         int out_bpp = 0;
432         int rle = 0;
433         int dest_cmodel = BC_RGB888;
434
435 //printf("FileTGA::write_tga 1\n");
436
437         header[0] = 0;
438         header[1] = 0;
439         if(!strcasecmp(asset->vcodec, TGA_RGBA_RLE))
440         {
441                 header[2] = 10;
442                 out_bpp = 4;
443                 rle = 1;
444                 header[16] = 32; /* bpp */
445                 header[17] = 0x28; /* alpha + orientation */
446                 dest_cmodel = BC_RGBA8888;
447         }
448         else
449         if(!strcasecmp(asset->vcodec, TGA_RGBA))
450         {
451                 header[2] = 2;
452                 out_bpp = 4;
453                 rle = 0;
454                 header[16] = 32; /* bpp */
455                 header[17] = 0x28; /* alpha + orientation */
456                 dest_cmodel = BC_RGBA8888;
457         }
458         else
459         if(!strcasecmp(asset->vcodec, TGA_RGB_RLE))
460         {
461                 header[2] = 10;
462                 out_bpp = 3;
463                 rle = 1;
464                 header[16] = 24; /* bpp */
465                 header[17] = 0x20; /* alpha + orientation */
466                 dest_cmodel = BC_RGB888;
467         }
468         else
469         {
470                 header[2] = 2;
471                 out_bpp = 3;
472                 rle = 0;
473                 header[16] = 24; /* bpp */
474                 header[17] = 0x20; /* alpha + orientation */
475                 dest_cmodel = BC_RGB888;
476         }
477         header[3] = header[4] = header[5] = header[6] = header[7] = 0;
478 //printf("FileTGA::write_tga 1\n");
479
480         VFrame *input_frame;
481         if(frame->get_color_model() == dest_cmodel)
482         {
483                 input_frame = frame;
484         }
485         else
486         {
487                 if(temp && temp->get_color_model() != dest_cmodel)
488                 {
489                         delete temp;
490                         temp = 0;
491                 }
492
493                 if(!temp)
494                 {
495                         temp = new VFrame(0, -1, frame->get_w(), frame->get_h(), dest_cmodel, -1);
496                 }
497                 input_frame = temp;
498
499                 BC_CModels::transfer(input_frame->get_rows(),
500                         frame->get_rows(),
501                         input_frame->get_y(),
502                         input_frame->get_u(),
503                         input_frame->get_v(),
504                         frame->get_y(),
505                         frame->get_u(),
506                         frame->get_v(),
507                         0,
508                         0,
509                         frame->get_w(),
510                         frame->get_h(),
511                         0,
512                         0,
513                         frame->get_w(),
514                         frame->get_h(),
515                         frame->get_color_model(),
516                         input_frame->get_color_model(),
517                         0,
518                         frame->get_w(),
519                         frame->get_w());
520         }
521 //printf("FileTGA::write_tga 1\n");
522
523 // xorigin
524 // yorigin
525         header[8]  = header[9]  = 0;
526         header[10] = header[11] = 0;
527
528         header[12] = input_frame->get_w() % 256;
529         header[13] = input_frame->get_w() / 256;
530
531         header[14] = input_frame->get_h() % 256;
532         header[15] = input_frame->get_h() / 256;
533 //printf("FileTGA::write_tga 1\n");
534
535         write_data(header, data, file_offset, sizeof(header));
536 //printf("FileTGA::write_tga 1\n");
537
538         unsigned char *output = new unsigned char[out_bpp * input_frame->get_w()];
539 //printf("FileTGA::write_tga 1\n");
540         for(int i = 0; i < input_frame->get_h(); i++)
541         {
542 //printf("FileTGA::write_tga 2\n");
543                 bgr2rgb(output, input_frame->get_rows()[i], input_frame->get_w(), out_bpp, (out_bpp == 4));
544 //printf("FileTGA::write_tga 3\n");
545
546                 if(rle)
547                 {
548 //printf("FileTGA::write_tga 4\n");
549                         rle_write(output,
550                                 input_frame->get_w(),
551                                 out_bpp,
552                                 data,
553                                 file_offset);
554 //printf("FileTGA::write_tga 5\n");
555                 }
556                 else
557                 {
558 //printf("FileTGA::write_tga 6\n");
559                         write_data(output,
560                                 data,
561                                 file_offset,
562                                 input_frame->get_w() * out_bpp);
563 //printf("FileTGA::write_tga 7\n");
564                 }
565         }
566 //printf("FileTGA::write_tga 8\n");
567         delete [] output;
568 //printf("FileTGA::write_tga 9\n");
569 }
570
571 void FileTGA::write_data(unsigned char *buffer,
572         VFrame *data,
573         int64_t &file_offset,
574         int64_t len)
575 {
576 //printf("FileTGA::write_data 1 %d\n", len);
577         if(data->get_compressed_allocated() <= data->get_compressed_size() + len)
578         {
579                 data->allocate_compressed_data((data->get_compressed_size() + len) * 2);
580         }
581 //printf("FileTGA::write_data 1 %d\n", len);
582
583         bcopy(buffer, data->get_data() + file_offset, len);
584 //printf("FileTGA::write_data 1 %d\n", len);
585         file_offset += len;
586 //printf("FileTGA::write_data 1 %d\n", len);
587         data->set_compressed_size(file_offset);
588 //printf("FileTGA::write_data 2 %d\n", len);
589 }
590
591 void FileTGA::read_line(unsigned char *row,
592         unsigned char *data,
593         int64_t &file_offset,
594         int image_type,
595         int bpp,
596         int image_compression,
597         int bytes,
598         int width,
599         int fliphoriz,
600         int alphabits,
601         int data_size)
602 {
603         if(file_offset >= data_size) return;
604         if(image_compression == TGA_COMP_RLE)
605         {
606                 rle_read(row,
607                         data,
608                         file_offset,
609                         bytes,
610                         width);
611         }
612         else
613         {
614                 if(file_offset + bytes * width <= data_size)
615                         bcopy(data + file_offset, row, bytes * width);
616                 file_offset += bytes * width;
617         }
618
619         if(fliphoriz)
620         {
621                 flip_line(row, bytes, width);
622         }
623
624         if(image_type == TGA_TYPE_COLOR)
625         {
626                 if(bpp == 16)
627                 {
628                         upsample(row, row, width, bytes);
629                 }
630                 else
631                 {
632                         bgr2rgb(row, row, width, bytes, alphabits);
633                 }
634         }
635         else
636         {
637                 ;
638         }
639 }
640
641 void FileTGA::flip_line(unsigned char *row, int bytes, int width)
642 {
643         unsigned char temp;
644         unsigned char *alt;
645         int x, s;
646
647         alt = row + (bytes * (width - 1));
648
649         for (x = 0; x * 2 <= width; x++)
650     {
651         for(s = 0; s < bytes; ++s)
652                 {
653                         temp = row[s];
654                         row[s] = alt[s];
655                         alt[s] = temp;
656                 }
657
658         row += bytes;
659         alt -= bytes;
660     }
661 }
662
663 void FileTGA::rle_read(unsigned char *row,
664         unsigned char *data,
665         int64_t &file_offset,
666         int bytes,
667         int width)
668 {
669         int repeat = 0;
670         int direct = 0;
671         unsigned char sample[4];
672         int head;
673
674         for(int x = 0; x < width; x++)
675         {
676                 if(repeat == 0 && direct == 0)
677                 {
678                         head = data[file_offset++];
679                         if(head == EOF)
680                         {
681                                 return;
682                         }
683                         else
684                         if(head >= 128)
685                         {
686                                 repeat = head - 127;
687                                 bcopy(data + file_offset, sample, bytes);
688                                 file_offset += bytes;
689                         }
690                         else
691                         {
692                                 direct = head + 1;
693                         }
694                 }
695
696                 if(repeat > 0)
697                 {
698                         for(int k = 0; k < bytes; k++)
699                         {
700                                 row[k] = sample[k];
701                         }
702
703                         repeat--;
704                 }
705                 else
706                 {
707                         bcopy(data + file_offset, row, bytes);
708                         file_offset += bytes;
709
710                         direct--;
711                 }
712
713                 row += bytes;
714         }
715 }
716
717 void FileTGA::rle_write(unsigned char *buffer,
718         int width,
719         int bytes,
720         VFrame *frame,
721         int64_t &file_offset)
722 {
723         int repeat = 0;
724         int direct = 0;
725         unsigned char *from = buffer;
726         unsigned char output;
727         int x;
728
729         for(x = 1; x < width; ++x)
730         {
731 /* next pixel is different */
732                 if(memcmp(buffer, buffer + bytes, bytes))
733                 {
734                         if(repeat)
735                         {
736                                 output = 128 + repeat;
737                                 write_data(&output, frame, file_offset, 1);
738                                 write_data(from, frame, file_offset, bytes);
739                                 from = buffer + bytes;
740                                 repeat = 0;
741                                 direct = 0;
742                         }
743                         else
744                         {
745                                 direct++;
746                         }
747                 }
748                 else
749 /* next pixel is the same */
750                 {
751                         if(direct)
752                         {
753                                 output = direct - 1;
754                                 write_data(&output, frame, file_offset, 1);
755                                 write_data(from, frame, file_offset, bytes * direct);
756                                 from = buffer;
757                                 direct = 0;
758                                 repeat = 1;
759                         }
760                         else
761                         {
762                                 repeat++;
763                         }
764                 }
765
766                 if(repeat == 128)
767                 {
768                         output = 255;
769                         write_data(&output, frame, file_offset, 1);
770                         write_data(from, frame, file_offset, bytes);
771                         from = buffer + bytes;
772                         direct = 0;
773                         repeat = 0;
774                 }
775                 else
776                 if(direct == 128)
777                 {
778                         output = 127;
779                         write_data(&output, frame, file_offset, 1);
780                         write_data(from, frame, file_offset, direct * bytes);
781                         from = buffer + bytes;
782                         direct = 0;
783                         repeat = 0;
784                 }
785
786                 buffer += bytes;
787         }
788
789         if(repeat > 0)
790         {
791                 output = 128 + repeat;
792                 write_data(&output, frame, file_offset, 1);
793                 write_data(from, frame, file_offset, bytes);
794         }
795         else
796         {
797                 output = direct;
798                 write_data(&output, frame, file_offset, 1);
799                 write_data(from, frame, file_offset, bytes * (direct + 1));
800         }
801 }
802
803
804 void FileTGA::bgr2rgb(unsigned char *dest,
805          unsigned char *src,
806          int width,
807          int bytes,
808          int alpha)
809 {
810         int x;
811         unsigned char r, g, b;
812
813         if(alpha)
814     {
815         for(x = 0; x < width; x++)
816                 {
817                         r = src[2];
818                         g = src[1];
819                         b = src[0];
820                         *(dest++) = r;
821                         *(dest++) = g;
822                         *(dest++) = b;
823                         *(dest++) = src[3];
824
825                         src += bytes;
826                 }
827     }
828         else
829     {
830         for(x = 0; x < width; x++)
831                 {
832                         r = src[2];
833                         g = src[1];
834                         b = src[0];
835                         *(dest++) = r;
836                         *(dest++) = g;
837                         *(dest++) = b;
838
839                         src += bytes;
840                 }
841     }
842 }
843
844 void FileTGA::upsample(unsigned char *dest,
845           unsigned char *src,
846           int width,
847           int bytes)
848 {
849         int x;
850
851         dest += (width - 1) * 3;
852         src += (width - 1) * bytes;
853         for(x = width - 1; x >= 0; x--)
854     {
855         dest[0] =  ((src[1] << 1) & 0xf8);
856         dest[0] += (dest[0] >> 5);
857
858         dest[1] =  ((src[0] & 0xe0) >> 2) + ((src[1] & 0x03) << 6);
859         dest[1] += (dest[1] >> 5);
860
861         dest[2] =  ((src[0] << 3) & 0xf8);
862         dest[2] += (dest[2] >> 5);
863
864         dest -= 3;
865         src -= bytes;
866     }
867 }
868
869
870
871
872
873
874
875
876
877 TGAUnit::TGAUnit(FileTGA *file, FrameWriter *writer)
878  : FrameWriterUnit(writer)
879 {
880         temp = 0;
881         this->file = file;
882 }
883
884 TGAUnit::~TGAUnit()
885 {
886         if(temp) delete temp;
887 }
888
889
890
891
892
893
894
895
896
897
898
899
900
901 TGAConfigVideo::TGAConfigVideo(BC_WindowBase *gui, Asset *asset)
902  : BC_Window(_(PROGRAM_NAME ": Video Compression"),
903         gui->get_abs_cursor_x(1),
904         gui->get_abs_cursor_y(1),
905         400,
906         100)
907 {
908         this->gui = gui;
909         this->asset = asset;
910
911         compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGB_RLE)));
912         compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGBA_RLE)));
913         compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGB)));
914         compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGBA)));
915 }
916
917 TGAConfigVideo::~TGAConfigVideo()
918 {
919         compression_items.remove_all_objects();
920 }
921
922 void TGAConfigVideo::create_objects()
923 {
924         lock_window("TGAConfigVideo::create_objects()");
925         int x = 10, y = 10;
926
927         add_subwindow(new BC_Title(x, y, _("Compression:")));
928         TGACompression *textbox = new TGACompression(this,
929                 x + 110,
930                 y,
931                 asset,
932                 &compression_items);
933         textbox->create_objects();
934         add_subwindow(new BC_OKButton(this));
935         show_window(1);
936         unlock_window();
937 }
938
939 int TGAConfigVideo::close_event()
940 {
941         set_done(0);
942         return 1;
943 }
944
945
946 TGACompression::TGACompression(TGAConfigVideo *gui,
947         int x,
948         int y,
949         Asset *asset,
950         ArrayList<BC_ListBoxItem*> *compression_items)
951  : BC_PopupTextBox(gui,
952         compression_items,
953         FileTGA::compression_to_str(gui->asset->vcodec),
954         x,
955         y,
956         200,
957         200)
958 {
959         this->asset = asset;
960 }
961 int TGACompression::handle_event()
962 {
963         strcpy(asset->vcodec, FileTGA::str_to_compression(get_text()));
964         return 1;
965 }