11 #define _(String) gettext(String)
12 #define gettext_noop(String) String
13 #define N_(String) gettext_noop (String)
15 /* Known image types. */
16 #define TGA_TYPE_MAPPED 1
17 #define TGA_TYPE_COLOR 2
18 #define TGA_TYPE_GRAY 3
20 /* Only known compression is RLE */
21 #define TGA_COMP_NONE 0
22 #define TGA_COMP_RLE 1
25 FileTGA::FileTGA(Asset *asset, File *file)
26 : FileList(asset, file, "TGALIST", ".tga", FILE_TGA, FILE_TGA_LIST)
36 int FileTGA::check_sig(Asset *asset)
38 //printf("FileTGA::check_sig 1\n");
39 // Test file extension
41 char *ext = strrchr(asset->path, '.');
44 if(!strncasecmp(ext, ".tga", 4)) result = 1;
52 if(!(stream = fopen(asset->path, "rb")))
60 fread(test, 16, 1, stream);
62 if(test[0] == 'T' && test[1] == 'G' && test[2] == 'A' &&
63 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' &&
71 //printf("FileTGA::check_sig 2\n");
76 void FileTGA::get_parameters(BC_WindowBase *parent_window,
78 BC_WindowBase* &format_window,
84 TGAConfigVideo *window = new TGAConfigVideo(parent_window, asset);
85 format_window = window;
86 window->create_objects();
95 N_("RGB uncompressed")
96 N_("RGBA uncompressed")
99 #define TGA_RGB_RLE "rle "
100 #define TGA_RGBA_RLE "rlea"
101 #define TGA_RGB "raw "
102 #define TGA_RGBA "rawa"
104 #define TGA_RGB_RLE_NAME "RGB compressed"
105 #define TGA_RGBA_RLE_NAME "RGBA compressed"
106 #define TGA_RGB_NAME "RGB uncompressed"
107 #define TGA_RGBA_NAME "RGBA uncompressed"
109 char* FileTGA::compression_to_str(char *compression)
111 if(!strcasecmp(compression, TGA_RGB_RLE)) return _(TGA_RGB_RLE_NAME);
112 if(!strcasecmp(compression, TGA_RGBA_RLE)) return _(TGA_RGBA_RLE_NAME);
113 if(!strcasecmp(compression, TGA_RGB)) return _(TGA_RGB_NAME);
114 if(!strcasecmp(compression, TGA_RGBA)) return _(TGA_RGBA_NAME);
118 char* FileTGA::str_to_compression(char *string)
120 if(!strcasecmp(compression_to_str(TGA_RGB_RLE), string)) return TGA_RGB_RLE;
121 if(!strcasecmp(compression_to_str(TGA_RGBA_RLE), string)) return TGA_RGBA_RLE;
122 if(!strcasecmp(compression_to_str(TGA_RGB), string)) return TGA_RGB;
123 if(!strcasecmp(compression_to_str(TGA_RGBA), string)) return TGA_RGBA;
127 int FileTGA::can_copy_from(Edit *edit, int64_t position)
129 if(edit->asset->format == FILE_TGA_LIST ||
130 edit->asset->format == FILE_TGA)
137 int FileTGA::colormodel_supported(int colormodel)
142 int FileTGA::get_best_colormodel(Asset *asset, int driver)
144 if(!strcasecmp(asset->vcodec, TGA_RGB_RLE) ||
145 !strcasecmp(asset->vcodec, TGA_RGB)) return BC_RGB888;
146 if(!strcasecmp(asset->vcodec, TGA_RGBA_RLE) ||
147 !strcasecmp(asset->vcodec, TGA_RGBA)) return BC_RGBA8888;
151 int FileTGA::read_frame(VFrame *frame, VFrame *data)
153 read_tga(asset, frame, data, temp);
157 int FileTGA::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
159 TGAUnit *tga_unit = (TGAUnit*)unit;
161 write_tga(asset, frame, data, tga_unit->temp);
165 FrameWriterUnit* FileTGA::new_writer_unit(FrameWriter *writer)
167 return new TGAUnit(this, writer);
179 #define FOOTERSIZE 26
180 #define HEADERSIZE 18
181 int FileTGA::read_frame_header(char *path)
185 //printf("FileTGA::read_frame_header 1\n");
188 if(!(stream = fopen(path, "rb")))
190 perror("FileTGA::read_frame_header");
194 unsigned char header[HEADERSIZE];
195 fread(header, HEADERSIZE, 1, stream);
198 asset->width = header[12] | (header[13] << 8);
199 asset->height = header[14] | (header[15] << 8);
200 int bpp = header[16];
201 int rle = header[2] & 0x8;
206 strcpy(asset->vcodec, TGA_RGBA_RLE);
208 strcpy(asset->vcodec, TGA_RGBA);
212 strcpy(asset->vcodec, TGA_RGB_RLE);
214 strcpy(asset->vcodec, TGA_RGB);
217 //printf("FileTGA::read_frame_header 2 %d %d\n", asset->width, asset->height);
222 void FileTGA::read_tga(Asset *asset, VFrame *frame, VFrame *data, VFrame* &temp)
224 //printf("FileTGA::read_tga 1\n");
226 unsigned char *footer, *header;
228 int64_t file_offset = 0;
230 footer = data->get_data() +
231 data->get_compressed_size() -
233 header = data->get_data();
234 file_offset += HEADERSIZE;
237 int image_compression;
241 image_type = TGA_TYPE_MAPPED;
242 image_compression = TGA_COMP_NONE;
245 image_type = TGA_TYPE_COLOR;
246 image_compression = TGA_COMP_NONE;
249 image_type = TGA_TYPE_GRAY;
250 image_compression = TGA_COMP_NONE;
253 image_type = TGA_TYPE_MAPPED;
254 image_compression = TGA_COMP_RLE;
257 image_type = TGA_TYPE_COLOR;
258 image_compression = TGA_COMP_RLE;
261 image_type = TGA_TYPE_GRAY;
262 image_compression = TGA_COMP_RLE;
268 int idlength = header[0];
269 int colormaptype = header[1];
270 int colormapindex = header[3] + header[4] * 256;
271 int colormaplength = header[5] + header[6] * 256;
272 int colormapsize = header[7];
273 int xorigin = header[8] + header[9] * 256;
274 int yorigin = header[10] + header[11] * 256;
275 int width = header[12] + header[13] * 256;
276 int height = header[14] + header[15] * 256;
277 int bpp = header[16];
278 int bytes = (bpp + 7) / 8;
279 int alphabits = header[17] & 0x0f;
280 int fliphoriz = (header[17] & 0x10) ? 1 : 0;
281 int flipvert = (header[17] & 0x20) ? 0 : 1;
282 int data_size = data->get_compressed_size();
284 if(idlength) file_offset += idlength;
287 unsigned char *tga_cmap;
288 unsigned char colormap[4 * 256];
290 if(colormaptype == 1)
292 int cmap_bytes = (colormapsize + 7) / 8;
293 tga_cmap = data->get_data() + file_offset;
294 file_offset += colormaplength * cmap_bytes;
299 bgr2rgb(colormap, tga_cmap, colormaplength, cmap_bytes, 1);
302 bgr2rgb(colormap, tga_cmap, colormaplength, cmap_bytes, 0);
305 upsample(colormap, tga_cmap, colormaplength, cmap_bytes);
310 int source_cmodel = BC_RGB888;
314 source_cmodel = BC_RGBA8888;
317 source_cmodel = BC_RGB888;
322 VFrame *output_frame;
323 if(frame->get_color_model() == source_cmodel)
325 output_frame = frame;
329 if(temp && temp->get_color_model() != source_cmodel)
337 temp = new VFrame(0, width, height, source_cmodel);
344 for(int i = height - 1; i >= 0; i--)
346 read_line(output_frame->get_rows()[i],
361 for(int i = 0; i < height; i++)
363 read_line(output_frame->get_rows()[i],
377 if(output_frame != frame)
379 cmodel_transfer(frame->get_rows(),
380 output_frame->get_rows(),
384 output_frame->get_y(),
385 output_frame->get_u(),
386 output_frame->get_v(),
395 output_frame->get_color_model(),
396 frame->get_color_model(),
401 //printf("FileTGA::read_tga 2 %d %d\n", frame->get_color_model(), output_frame->get_color_model());
404 void FileTGA::write_tga(Asset *asset, VFrame *frame, VFrame *data, VFrame* &temp)
406 unsigned char header[18];
407 unsigned char footer[26];
408 int64_t file_offset = 0;
411 int dest_cmodel = BC_RGB888;
413 //printf("FileTGA::write_tga 1\n");
417 if(!strcasecmp(asset->vcodec, TGA_RGBA_RLE))
422 header[16] = 32; /* bpp */
423 header[17] = 0x28; /* alpha + orientation */
424 dest_cmodel = BC_RGBA8888;
427 if(!strcasecmp(asset->vcodec, TGA_RGBA))
432 header[16] = 32; /* bpp */
433 header[17] = 0x28; /* alpha + orientation */
434 dest_cmodel = BC_RGBA8888;
437 if(!strcasecmp(asset->vcodec, TGA_RGB_RLE))
442 header[16] = 24; /* bpp */
443 header[17] = 0x20; /* alpha + orientation */
444 dest_cmodel = BC_RGB888;
451 header[16] = 24; /* bpp */
452 header[17] = 0x20; /* alpha + orientation */
453 dest_cmodel = BC_RGB888;
455 header[3] = header[4] = header[5] = header[6] = header[7] = 0;
456 //printf("FileTGA::write_tga 1\n");
459 if(frame->get_color_model() == dest_cmodel)
465 if(temp && temp->get_color_model() != dest_cmodel)
473 temp = new VFrame(0, frame->get_w(), frame->get_h(), dest_cmodel);
477 cmodel_transfer(input_frame->get_rows(),
479 input_frame->get_y(),
480 input_frame->get_u(),
481 input_frame->get_v(),
493 frame->get_color_model(),
494 input_frame->get_color_model(),
499 //printf("FileTGA::write_tga 1\n");
503 header[8] = header[9] = 0;
504 header[10] = header[11] = 0;
506 header[12] = input_frame->get_w() % 256;
507 header[13] = input_frame->get_w() / 256;
509 header[14] = input_frame->get_h() % 256;
510 header[15] = input_frame->get_h() / 256;
511 //printf("FileTGA::write_tga 1\n");
513 write_data(header, data, file_offset, sizeof(header));
514 //printf("FileTGA::write_tga 1\n");
516 unsigned char *output = new unsigned char[out_bpp * input_frame->get_w()];
517 //printf("FileTGA::write_tga 1\n");
518 for(int i = 0; i < input_frame->get_h(); i++)
520 //printf("FileTGA::write_tga 2\n");
521 bgr2rgb(output, input_frame->get_rows()[i], input_frame->get_w(), out_bpp, (out_bpp == 4));
522 //printf("FileTGA::write_tga 3\n");
526 //printf("FileTGA::write_tga 4\n");
528 input_frame->get_w(),
532 //printf("FileTGA::write_tga 5\n");
536 //printf("FileTGA::write_tga 6\n");
540 input_frame->get_w() * out_bpp);
541 //printf("FileTGA::write_tga 7\n");
544 //printf("FileTGA::write_tga 8\n");
546 //printf("FileTGA::write_tga 9\n");
549 void FileTGA::write_data(unsigned char *buffer,
551 int64_t &file_offset,
554 //printf("FileTGA::write_data 1 %d\n", len);
555 if(data->get_compressed_allocated() <= data->get_compressed_size() + len)
557 data->allocate_compressed_data((data->get_compressed_size() + len) * 2);
559 //printf("FileTGA::write_data 1 %d\n", len);
561 bcopy(buffer, data->get_data() + file_offset, len);
562 //printf("FileTGA::write_data 1 %d\n", len);
564 //printf("FileTGA::write_data 1 %d\n", len);
565 data->set_compressed_size(file_offset);
566 //printf("FileTGA::write_data 2 %d\n", len);
569 void FileTGA::read_line(unsigned char *row,
571 int64_t &file_offset,
574 int image_compression,
581 if(file_offset >= data_size) return;
582 if(image_compression == TGA_COMP_RLE)
592 if(file_offset + bytes * width <= data_size)
593 bcopy(data + file_offset, row, bytes * width);
594 file_offset += bytes * width;
599 flip_line(row, bytes, width);
602 if(image_type == TGA_TYPE_COLOR)
606 upsample(row, row, width, bytes);
610 bgr2rgb(row, row, width, bytes, alphabits);
619 void FileTGA::flip_line(unsigned char *row, int bytes, int width)
625 alt = row + (bytes * (width - 1));
627 for (x = 0; x * 2 <= width; x++)
629 for(s = 0; s < bytes; ++s)
641 void FileTGA::rle_read(unsigned char *row,
643 int64_t &file_offset,
649 unsigned char sample[4];
652 for(int x = 0; x < width; x++)
654 if(repeat == 0 && direct == 0)
656 head = data[file_offset++];
665 bcopy(data + file_offset, sample, bytes);
666 file_offset += bytes;
676 for(int k = 0; k < bytes; k++)
685 bcopy(data + file_offset, row, bytes);
686 file_offset += bytes;
695 void FileTGA::rle_write(unsigned char *buffer,
699 int64_t &file_offset)
703 unsigned char *from = buffer;
704 unsigned char output;
707 for(x = 1; x < width; ++x)
709 /* next pixel is different */
710 if(memcmp(buffer, buffer + bytes, bytes))
714 output = 128 + repeat;
715 write_data(&output, frame, file_offset, 1);
716 write_data(from, frame, file_offset, bytes);
717 from = buffer + bytes;
727 /* next pixel is the same */
732 write_data(&output, frame, file_offset, 1);
733 write_data(from, frame, file_offset, bytes * direct);
747 write_data(&output, frame, file_offset, 1);
748 write_data(from, frame, file_offset, bytes);
749 from = buffer + bytes;
757 write_data(&output, frame, file_offset, 1);
758 write_data(from, frame, file_offset, direct * bytes);
759 from = buffer + bytes;
769 output = 128 + repeat;
770 write_data(&output, frame, file_offset, 1);
771 write_data(from, frame, file_offset, bytes);
776 write_data(&output, frame, file_offset, 1);
777 write_data(from, frame, file_offset, bytes * (direct + 1));
782 void FileTGA::bgr2rgb(unsigned char *dest,
789 unsigned char r, g, b;
793 for(x = 0; x < width; x++)
808 for(x = 0; x < width; x++)
822 void FileTGA::upsample(unsigned char *dest,
829 dest += (width - 1) * 3;
830 src += (width - 1) * bytes;
831 for(x = width - 1; x >= 0; x--)
833 dest[0] = ((src[1] << 1) & 0xf8);
834 dest[0] += (dest[0] >> 5);
836 dest[1] = ((src[0] & 0xe0) >> 2) + ((src[1] & 0x03) << 6);
837 dest[1] += (dest[1] >> 5);
839 dest[2] = ((src[0] << 3) & 0xf8);
840 dest[2] += (dest[2] >> 5);
855 TGAUnit::TGAUnit(FileTGA *file, FrameWriter *writer)
856 : FrameWriterUnit(writer)
864 if(temp) delete temp;
879 TGAConfigVideo::TGAConfigVideo(BC_WindowBase *gui, Asset *asset)
880 : BC_Window(PROGRAM_NAME ": Video Compression",
881 gui->get_abs_cursor_x(),
882 gui->get_abs_cursor_y(),
889 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGB_RLE)));
890 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGBA_RLE)));
891 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGB)));
892 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGBA)));
895 TGAConfigVideo::~TGAConfigVideo()
897 compression_items.remove_all_objects();
900 int TGAConfigVideo::create_objects()
904 add_subwindow(new BC_Title(x, y, _("Compression:")));
905 TGACompression *textbox = new TGACompression(this,
910 textbox->create_objects();
911 add_subwindow(new BC_OKButton(this));
915 int TGAConfigVideo::close_event()
922 TGACompression::TGACompression(TGAConfigVideo *gui,
926 ArrayList<BC_ListBoxItem*> *compression_items)
927 : BC_PopupTextBox(gui,
929 FileTGA::compression_to_str(gui->asset->vcodec),
937 int TGACompression::handle_event()
939 strcpy(asset->vcodec, FileTGA::str_to_compression(get_text()));