3 #include "bcwidgetgrid.h"
14 /* Known image types. */
15 #define TGA_TYPE_MAPPED 1
16 #define TGA_TYPE_COLOR 2
17 #define TGA_TYPE_GRAY 3
19 /* Only known compression is RLE */
20 #define TGA_COMP_NONE 0
21 #define TGA_COMP_RLE 1
24 FileTGA::FileTGA(Asset_GC asset, File *file)
25 : FileList(asset, file, "TGALIST", ".tga", FILE_TGA, FILE_TGA_LIST)
35 int FileTGA::check_sig(Asset_GC asset)
39 // Test file extension
41 char *ext = strrchr(asset->path, '.');
46 if(!strncasecmp(ext, ".tga", 4)) result = 1;
56 if(!(stream = fopen(asset->path, "rb")))
64 fread(test, 16, 1, stream);
66 if(test[0] == 'T' && test[1] == 'G' && test[2] == 'A' &&
67 test[3] == 'L' && test[4] == 'I' && test[5] == 'S' &&
80 void FileTGA::get_parameters(BC_WindowBase *parent_window,
82 BC_WindowBase* &format_window,
88 TGAConfigVideo *window = new TGAConfigVideo(parent_window, asset);
89 format_window = window;
90 window->create_objects();
99 N_("RGB uncompressed")
100 N_("RGBA uncompressed")
103 #define TGA_RGB_RLE "rle "
104 #define TGA_RGBA_RLE "rlea"
105 #define TGA_RGB "raw "
106 #define TGA_RGBA "rawa"
108 #define TGA_RGB_RLE_NAME "RGB compressed"
109 #define TGA_RGBA_RLE_NAME "RGBA compressed"
110 #define TGA_RGB_NAME "RGB uncompressed"
111 #define TGA_RGBA_NAME "RGBA uncompressed"
113 char* FileTGA::compression_to_str(char *compression)
115 if(!strcasecmp(compression, TGA_RGB_RLE)) return _(TGA_RGB_RLE_NAME);
116 if(!strcasecmp(compression, TGA_RGBA_RLE)) return _(TGA_RGBA_RLE_NAME);
117 if(!strcasecmp(compression, TGA_RGB)) return _(TGA_RGB_NAME);
118 if(!strcasecmp(compression, TGA_RGBA)) return _(TGA_RGBA_NAME);
122 char* FileTGA::str_to_compression(char *string)
124 if(!strcasecmp(compression_to_str(TGA_RGB_RLE), string)) return TGA_RGB_RLE;
125 if(!strcasecmp(compression_to_str(TGA_RGBA_RLE), string)) return TGA_RGBA_RLE;
126 if(!strcasecmp(compression_to_str(TGA_RGB), string)) return TGA_RGB;
127 if(!strcasecmp(compression_to_str(TGA_RGBA), string)) return TGA_RGBA;
131 int FileTGA::can_copy_from(Edit *edit, int64_t position)
133 if(edit->asset->format == FILE_TGA_LIST ||
134 edit->asset->format == FILE_TGA)
141 int FileTGA::colormodel_supported(int colormodel)
146 int FileTGA::get_best_colormodel(Asset_GC asset, int driver)
148 if(!strcasecmp(asset->vcodec, TGA_RGB_RLE) ||
149 !strcasecmp(asset->vcodec, TGA_RGB)) return BC_RGB888;
150 if(!strcasecmp(asset->vcodec, TGA_RGBA_RLE) ||
151 !strcasecmp(asset->vcodec, TGA_RGBA)) return BC_RGBA8888;
155 int FileTGA::read_frame(VFrame *frame, VFrame *data)
157 read_tga(asset, frame, data, temp);
161 int FileTGA::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
163 TGAUnit *tga_unit = (TGAUnit*)unit;
165 write_tga(asset, frame, data, tga_unit->temp);
169 FrameWriterUnit* FileTGA::new_writer_unit(FrameWriter *writer)
171 return new TGAUnit(this, writer);
174 int64_t FileTGA::get_memory_usage()
176 int64_t result = FileList::get_memory_usage();
177 if(temp) result += temp->get_data_size();
188 #define FOOTERSIZE 26
189 #define HEADERSIZE 18
190 int FileTGA::read_frame_header(char *path)
194 //printf("FileTGA::read_frame_header 1\n");
197 if(!(stream = fopen(path, "rb")))
199 eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path);
203 unsigned char header[HEADERSIZE];
204 fread(header, HEADERSIZE, 1, stream);
207 asset->width = header[12] | (header[13] << 8);
208 asset->height = header[14] | (header[15] << 8);
209 int bpp = header[16];
210 int rle = header[2] & 0x8;
215 strcpy(asset->vcodec, TGA_RGBA_RLE);
217 strcpy(asset->vcodec, TGA_RGBA);
221 strcpy(asset->vcodec, TGA_RGB_RLE);
223 strcpy(asset->vcodec, TGA_RGB);
226 //printf("FileTGA::read_frame_header 2 %d %d\n", asset->width, asset->height);
231 void FileTGA::read_tga(Asset_GC asset, VFrame *frame, VFrame *data, VFrame* &temp)
234 unsigned char *footer, *header;
236 int64_t file_offset = 0;
238 footer = data->get_data() +
239 data->get_compressed_size() -
241 header = data->get_data();
242 file_offset += HEADERSIZE;
245 int image_compression;
249 image_type = TGA_TYPE_MAPPED;
250 image_compression = TGA_COMP_NONE;
253 image_type = TGA_TYPE_COLOR;
254 image_compression = TGA_COMP_NONE;
257 image_type = TGA_TYPE_GRAY;
258 image_compression = TGA_COMP_NONE;
261 image_type = TGA_TYPE_MAPPED;
262 image_compression = TGA_COMP_RLE;
265 image_type = TGA_TYPE_COLOR;
266 image_compression = TGA_COMP_RLE;
269 image_type = TGA_TYPE_GRAY;
270 image_compression = TGA_COMP_RLE;
276 int idlength = header[0];
277 int colormaptype = header[1];
278 int colormapindex = header[3] + header[4] * 256;
279 int colormaplength = header[5] + header[6] * 256;
280 int colormapsize = header[7];
281 int xorigin = header[8] + header[9] * 256;
282 int yorigin = header[10] + header[11] * 256;
283 int width = header[12] + header[13] * 256;
284 int height = header[14] + header[15] * 256;
285 int bpp = header[16];
286 int bytes = (bpp + 7) / 8;
287 int alphabits = header[17] & 0x0f;
288 int fliphoriz = (header[17] & 0x10) ? 1 : 0;
289 int flipvert = (header[17] & 0x20) ? 0 : 1;
290 int data_size = data->get_compressed_size();
292 if(idlength) file_offset += idlength;
295 unsigned char *tga_cmap;
296 unsigned char colormap[4 * 256];
298 if(colormaptype == 1)
300 int cmap_bytes = (colormapsize + 7) / 8;
301 tga_cmap = data->get_data() + file_offset;
302 file_offset += colormaplength * cmap_bytes;
307 bgr2rgb(colormap, tga_cmap, colormaplength, cmap_bytes, 1);
310 bgr2rgb(colormap, tga_cmap, colormaplength, cmap_bytes, 0);
313 upsample(colormap, tga_cmap, colormaplength, cmap_bytes);
318 int source_cmodel = BC_RGB888;
322 source_cmodel = BC_RGBA8888;
325 source_cmodel = BC_RGB888;
330 VFrame *output_frame;
331 if(frame->get_color_model() == source_cmodel)
333 output_frame = frame;
337 if(temp && temp->get_color_model() != source_cmodel)
345 temp = new VFrame(0, width, height, source_cmodel);
352 for(int i = height - 1; i >= 0; i--)
354 read_line(output_frame->get_rows()[i],
369 for(int i = 0; i < height; i++)
371 read_line(output_frame->get_rows()[i],
385 if(output_frame != frame)
387 cmodel_transfer(frame->get_rows(),
388 output_frame->get_rows(),
392 output_frame->get_y(),
393 output_frame->get_u(),
394 output_frame->get_v(),
403 output_frame->get_color_model(),
404 frame->get_color_model(),
411 void FileTGA::write_tga(Asset_GC asset, VFrame *frame, VFrame *data, VFrame* &temp)
413 unsigned char header[18];
414 unsigned char footer[26];
415 int64_t file_offset = 0;
418 int dest_cmodel = BC_RGB888;
420 //printf("FileTGA::write_tga 1\n");
424 if(!strcasecmp(asset->vcodec, TGA_RGBA_RLE))
429 header[16] = 32; /* bpp */
430 header[17] = 0x28; /* alpha + orientation */
431 dest_cmodel = BC_RGBA8888;
434 if(!strcasecmp(asset->vcodec, TGA_RGBA))
439 header[16] = 32; /* bpp */
440 header[17] = 0x28; /* alpha + orientation */
441 dest_cmodel = BC_RGBA8888;
444 if(!strcasecmp(asset->vcodec, TGA_RGB_RLE))
449 header[16] = 24; /* bpp */
450 header[17] = 0x20; /* alpha + orientation */
451 dest_cmodel = BC_RGB888;
458 header[16] = 24; /* bpp */
459 header[17] = 0x20; /* alpha + orientation */
460 dest_cmodel = BC_RGB888;
462 header[3] = header[4] = header[5] = header[6] = header[7] = 0;
463 //printf("FileTGA::write_tga 1\n");
466 if(frame->get_color_model() == dest_cmodel)
472 if(temp && temp->get_color_model() != dest_cmodel)
480 temp = new VFrame(0, frame->get_w(), frame->get_h(), dest_cmodel);
484 cmodel_transfer(input_frame->get_rows(),
486 input_frame->get_y(),
487 input_frame->get_u(),
488 input_frame->get_v(),
500 frame->get_color_model(),
501 input_frame->get_color_model(),
506 //printf("FileTGA::write_tga 1\n");
510 header[8] = header[9] = 0;
511 header[10] = header[11] = 0;
513 header[12] = input_frame->get_w() % 256;
514 header[13] = input_frame->get_w() / 256;
516 header[14] = input_frame->get_h() % 256;
517 header[15] = input_frame->get_h() / 256;
518 //printf("FileTGA::write_tga 1\n");
520 write_data(header, data, file_offset, sizeof(header));
521 //printf("FileTGA::write_tga 1\n");
523 unsigned char *output = new unsigned char[out_bpp * input_frame->get_w()];
524 //printf("FileTGA::write_tga 1\n");
525 for(int i = 0; i < input_frame->get_h(); i++)
527 //printf("FileTGA::write_tga 2\n");
528 bgr2rgb(output, input_frame->get_rows()[i], input_frame->get_w(), out_bpp, (out_bpp == 4));
529 //printf("FileTGA::write_tga 3\n");
533 //printf("FileTGA::write_tga 4\n");
535 input_frame->get_w(),
539 //printf("FileTGA::write_tga 5\n");
543 //printf("FileTGA::write_tga 6\n");
547 input_frame->get_w() * out_bpp);
548 //printf("FileTGA::write_tga 7\n");
551 //printf("FileTGA::write_tga 8\n");
553 //printf("FileTGA::write_tga 9\n");
556 void FileTGA::write_data(unsigned char *buffer,
558 int64_t &file_offset,
561 //printf("FileTGA::write_data 1 %d\n", len);
562 if(data->get_compressed_allocated() <= data->get_compressed_size() + len)
564 data->allocate_compressed_data((data->get_compressed_size() + len) * 2);
566 //printf("FileTGA::write_data 1 %d\n", len);
568 bcopy(buffer, data->get_data() + file_offset, len);
569 //printf("FileTGA::write_data 1 %d\n", len);
571 //printf("FileTGA::write_data 1 %d\n", len);
572 data->set_compressed_size(file_offset);
573 //printf("FileTGA::write_data 2 %d\n", len);
576 void FileTGA::read_line(unsigned char *row,
578 int64_t &file_offset,
581 int image_compression,
588 if(file_offset >= data_size) return;
589 if(image_compression == TGA_COMP_RLE)
599 if(file_offset + bytes * width <= data_size)
600 bcopy(data + file_offset, row, bytes * width);
601 file_offset += bytes * width;
606 flip_line(row, bytes, width);
609 if(image_type == TGA_TYPE_COLOR)
613 upsample(row, row, width, bytes);
617 bgr2rgb(row, row, width, bytes, alphabits);
626 void FileTGA::flip_line(unsigned char *row, int bytes, int width)
632 alt = row + (bytes * (width - 1));
634 for (x = 0; x * 2 <= width; x++)
636 for(s = 0; s < bytes; ++s)
648 void FileTGA::rle_read(unsigned char *row,
650 int64_t &file_offset,
656 unsigned char sample[4];
659 for(int x = 0; x < width; x++)
661 if(repeat == 0 && direct == 0)
663 head = data[file_offset++];
672 bcopy(data + file_offset, sample, bytes);
673 file_offset += bytes;
683 for(int k = 0; k < bytes; k++)
692 bcopy(data + file_offset, row, bytes);
693 file_offset += bytes;
702 void FileTGA::rle_write(unsigned char *buffer,
706 int64_t &file_offset)
710 unsigned char *from = buffer;
711 unsigned char output;
714 for(x = 1; x < width; ++x)
716 /* next pixel is different */
717 if(memcmp(buffer, buffer + bytes, bytes))
721 output = 128 + repeat;
722 write_data(&output, frame, file_offset, 1);
723 write_data(from, frame, file_offset, bytes);
724 from = buffer + bytes;
734 /* next pixel is the same */
739 write_data(&output, frame, file_offset, 1);
740 write_data(from, frame, file_offset, bytes * direct);
754 write_data(&output, frame, file_offset, 1);
755 write_data(from, frame, file_offset, bytes);
756 from = buffer + bytes;
764 write_data(&output, frame, file_offset, 1);
765 write_data(from, frame, file_offset, direct * bytes);
766 from = buffer + bytes;
776 output = 128 + repeat;
777 write_data(&output, frame, file_offset, 1);
778 write_data(from, frame, file_offset, bytes);
783 write_data(&output, frame, file_offset, 1);
784 write_data(from, frame, file_offset, bytes * (direct + 1));
789 void FileTGA::bgr2rgb(unsigned char *dest,
796 unsigned char r, g, b;
800 for(x = 0; x < width; x++)
815 for(x = 0; x < width; x++)
829 void FileTGA::upsample(unsigned char *dest,
836 dest += (width - 1) * 3;
837 src += (width - 1) * bytes;
838 for(x = width - 1; x >= 0; x--)
840 dest[0] = ((src[1] << 1) & 0xf8);
841 dest[0] += (dest[0] >> 5);
843 dest[1] = ((src[0] & 0xe0) >> 2) + ((src[1] & 0x03) << 6);
844 dest[1] += (dest[1] >> 5);
846 dest[2] = ((src[0] << 3) & 0xf8);
847 dest[2] += (dest[2] >> 5);
862 TGAUnit::TGAUnit(FileTGA *file, FrameWriter *writer)
863 : FrameWriterUnit(writer)
871 if(temp) delete temp;
886 TGAConfigVideo::TGAConfigVideo(BC_WindowBase *gui, Asset_GC asset)
887 : BC_Window(PROGRAM_NAME ": Video Compression",
888 gui->get_abs_cursor_x(1),
889 gui->get_abs_cursor_y(1),
900 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGB_RLE)));
901 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGBA_RLE)));
902 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGB)));
903 compression_items.append(new BC_ListBoxItem(FileTGA::compression_to_str(TGA_RGBA)));
906 TGAConfigVideo::~TGAConfigVideo()
908 compression_items.remove_all_objects();
911 int TGAConfigVideo::create_objects()
916 BC_RelocatableWidget *rw;
918 wg = add_widgetgrid(new BC_WidgetGrid(10, 10, 10, 10, 3, 3));
921 add_subwindow(new BC_Title(x, y, _("Compression:")));
922 TGACompression *textbox = new TGACompression(this,
927 textbox->create_objects();
930 wg->add(textbox, 0, 1);
933 add_subwindow(new BC_OKButton(this));
936 resize_window(wg->get_w_wm(), wg->get_h_wm() + rw->get_h());
940 int TGAConfigVideo::close_event()
947 TGACompression::TGACompression(TGAConfigVideo *gui,
951 ArrayList<BC_ListBoxItem*> *compression_items)
952 : BC_PopupTextBox(gui,
954 FileTGA::compression_to_str(gui->asset->vcodec),
962 int TGACompression::handle_event()
964 strcpy(asset->vcodec, FileTGA::str_to_compression(get_text()));
970 // c-file-style: "linux"