00001 #include "asset.h"
00002 #include "edit.h"
00003 #include "file.h"
00004 #include "filetiff.h"
00005 #include "interlacemodes.h"
00006 #include "language.h"
00007 #include "vframe.h"
00008
00009 #include <stdint.h>
00010 #include <string.h>
00011 #include <unistd.h>
00012
00013 FileTIFF::FileTIFF(Asset *asset, File *file)
00014 : FileList(asset, file, "TIFFLIST", ".tif", FILE_TIFF, FILE_TIFF_LIST)
00015 {
00016 asset->video_data = 1;
00017 temp = 0;
00018 }
00019
00020 FileTIFF::~FileTIFF()
00021 {
00022 if(temp) delete temp;
00023 }
00024
00025
00026 void FileTIFF::get_parameters(BC_WindowBase *parent_window,
00027 Asset *asset,
00028 BC_WindowBase* &format_window,
00029 int audio_options,
00030 int video_options)
00031 {
00032 if(video_options)
00033 {
00034 TIFFConfigVideo *window = new TIFFConfigVideo(parent_window, asset);
00035 format_window = window;
00036 window->create_objects();
00037 window->run_window();
00038 delete window;
00039 }
00040 }
00041
00042
00043 int FileTIFF::check_sig(Asset *asset)
00044 {
00045 FILE *stream = fopen(asset->path, "rb");
00046
00047 if(stream)
00048 {
00049 char test[10];
00050 fread(test, 10, 1, stream);
00051 fclose(stream);
00052
00053 if(test[0] == 'I' && test[1] == 'I')
00054 {
00055 return 1;
00056 }
00057 else
00058 if(test[0] == 'T' && test[1] == 'I' && test[2] == 'F' && test[3] == 'F' &&
00059 test[4] == 'L' && test[5] == 'I' && test[6] == 'S' && test[7] == 'T')
00060 {
00061 return 1;
00062 }
00063 else
00064 if(strlen(asset->path) > 4 &&
00065 !strcasecmp(asset->path + strlen(asset->path) - 4, ".tif"))
00066 {
00067 return 1;
00068 }
00069 else
00070 if(strlen(asset->path) > 5 &&
00071 !strcasecmp(asset->path + strlen(asset->path) - 5, ".tiff"))
00072 {
00073 return 1;
00074 }
00075 }
00076 return 0;
00077 }
00078
00079 char* FileTIFF::compression_to_str(int value)
00080 {
00081 switch(value)
00082 {
00083 case FileTIFF::NONE: return "None"; break;
00084 case FileTIFF::LZW: return "LZW"; break;
00085 case FileTIFF::PACK_BITS: return "Pack Bits"; break;
00086 case FileTIFF::DEFLATE: return "Deflate"; break;
00087 case FileTIFF::JPEG: return "JPEG"; break;
00088 default:
00089 return "None";
00090 break;
00091 }
00092 }
00093
00094 char* FileTIFF::cmodel_to_str(int value)
00095 {
00096 switch(value)
00097 {
00098 case FileTIFF::GREYSCALE: return "Greyscale"; break;
00099 case FileTIFF::RGB_888: return "RGB-8 Bit"; break;
00100 case FileTIFF::RGB_161616: return "RGB-16 Bit"; break;
00101 case FileTIFF::RGBA_8888: return "RGBA-8 Bit"; break;
00102 case FileTIFF::RGBA_16161616: return "RGBA-16 Bit"; break;
00103 case FileTIFF::RGB_FLOAT: return "RGB-FLOAT"; break;
00104 case FileTIFF::RGBA_FLOAT: return "RGBA-FLOAT"; break;
00105 default:
00106 return "RGB-8 Bit";
00107 break;
00108 }
00109 }
00110
00111
00112 int FileTIFF::can_copy_from(Edit *edit, int64_t position)
00113 {
00114 if(edit->asset->format == FILE_TIFF_LIST ||
00115 edit->asset->format == FILE_TIFF)
00116 return 1;
00117
00118 return 0;
00119 }
00120
00121
00122
00123 int FileTIFF::read_frame_header(char *path)
00124 {
00125 TIFF *stream;
00126 int result = 0;
00127
00128 if(!(stream = TIFFOpen(path, "rb")))
00129 {
00130 fprintf(stderr, "FileTIFF::read_frame_header failed from %s\n", asset->path);
00131 return 1;
00132 }
00133
00134 char *ptr = 0;
00135 TIFFGetField(stream, TIFFTAG_MODEL, &ptr);
00136
00137 if(ptr && !strcmp(ptr, "Canon EOS-1DS"))
00138 {
00139 printf("FileTIFF::read_frame_header: got a %s.\n",
00140 ptr);
00141 }
00142
00143
00144
00145 TIFFGetField(stream, TIFFTAG_IMAGEWIDTH, &(asset->width));
00146 TIFFGetField(stream, TIFFTAG_IMAGELENGTH, &(asset->height));
00147
00148 int components = 0;
00149 TIFFGetField(stream, TIFFTAG_SAMPLESPERPIXEL, &components);
00150 int bitspersample = 0;
00151 TIFFGetField(stream, TIFFTAG_BITSPERSAMPLE, &bitspersample);
00152 int sampleformat = 0;
00153 TIFFGetField(stream, TIFFTAG_SAMPLEFORMAT, &sampleformat);
00154
00155 if(bitspersample == 8 && components == 3)
00156 asset->tiff_cmodel = FileTIFF::RGB_888;
00157 else
00158 if(bitspersample == 16 && components == 3)
00159 asset->tiff_cmodel = FileTIFF::RGB_161616;
00160 else
00161 if(bitspersample == 8 && components == 4)
00162 asset->tiff_cmodel = FileTIFF::RGBA_8888;
00163 else
00164 if(bitspersample == 16 && components == 4)
00165 asset->tiff_cmodel = FileTIFF::RGBA_16161616;
00166 else
00167 if(bitspersample == 32 && components == 3)
00168 asset->tiff_cmodel = FileTIFF::RGB_FLOAT;
00169 else
00170 if(bitspersample == 32 && components == 4)
00171 asset->tiff_cmodel = FileTIFF::RGBA_FLOAT;
00172 else
00173 if(bitspersample == 8 && components == 1)
00174 asset->tiff_cmodel = FileTIFF::GREYSCALE;
00175
00176
00177 TIFFClose(stream);
00178
00179 asset->interlace_mode = BC_ILACE_MODE_NOTINTERLACED;
00180
00181 return result;
00182 }
00183
00184 int FileTIFF::colormodel_supported(int colormodel)
00185 {
00186 switch(asset->tiff_cmodel)
00187 {
00188 case FileTIFF::RGB_888: return BC_RGB888; break;
00189 case FileTIFF::RGB_161616: return BC_RGB_FLOAT; break;
00190 case FileTIFF::GREYSCALE: return BC_RGB888; break;
00191 case FileTIFF::RGBA_8888: return BC_RGBA8888; break;
00192 case FileTIFF::RGBA_16161616: return BC_RGBA_FLOAT; break;
00193 case FileTIFF::RGB_FLOAT: return BC_RGB_FLOAT; break;
00194 case FileTIFF::RGBA_FLOAT: return BC_RGBA_FLOAT; break;
00195 default: return BC_RGB888; break;
00196 }
00197 }
00198
00199 int FileTIFF::get_best_colormodel(Asset *asset, int driver)
00200 {
00201 switch(asset->tiff_cmodel)
00202 {
00203 case FileTIFF::GREYSCALE: return BC_RGB888; break;
00204 case FileTIFF::RGB_888: return BC_RGB888; break;
00205 case FileTIFF::RGB_161616: return BC_RGB_FLOAT; break;
00206 case FileTIFF::RGBA_8888: return BC_RGBA8888; break;
00207 case FileTIFF::RGBA_16161616: return BC_RGBA_FLOAT; break;
00208 case FileTIFF::RGB_FLOAT: return BC_RGB_FLOAT; break;
00209 case FileTIFF::RGBA_FLOAT: return BC_RGBA_FLOAT; break;
00210 default: return BC_RGB888; break;
00211 }
00212 }
00213
00214
00215 static tsize_t tiff_read(thandle_t ptr, tdata_t buf, tsize_t size)
00216 {
00217 FileTIFFUnit *tiff_unit = (FileTIFFUnit*)ptr;
00218 if(tiff_unit->data->get_compressed_size() < tiff_unit->offset + size)
00219 return 0;
00220 memcpy(buf, tiff_unit->data->get_data() + tiff_unit->offset, size);
00221 tiff_unit->offset += size;
00222 return size;
00223 }
00224
00225 static tsize_t tiff_write(thandle_t ptr, tdata_t buf, tsize_t size)
00226 {
00227 FileTIFFUnit *tiff_unit = (FileTIFFUnit*)ptr;
00228 if(tiff_unit->data->get_compressed_allocated() < tiff_unit->offset + size)
00229 {
00230 tiff_unit->data->allocate_compressed_data((tiff_unit->offset + size) * 2);
00231 }
00232
00233
00234 if(tiff_unit->data->get_compressed_size() < tiff_unit->offset + size)
00235 tiff_unit->data->set_compressed_size(tiff_unit->offset + size);
00236 memcpy(tiff_unit->data->get_data() + tiff_unit->offset,
00237 buf,
00238 size);
00239 tiff_unit->offset += size;
00240 return size;
00241 }
00242
00243 static toff_t tiff_seek(thandle_t ptr, toff_t off, int whence)
00244 {
00245 FileTIFFUnit *tiff_unit = (FileTIFFUnit*)ptr;
00246 switch(whence)
00247 {
00248 case SEEK_SET:
00249 tiff_unit->offset = off;
00250 break;
00251 case SEEK_CUR:
00252 tiff_unit->offset += off;
00253 break;
00254 case SEEK_END:
00255 tiff_unit->offset = tiff_unit->data->get_compressed_size() + off;
00256 break;
00257 }
00258 return tiff_unit->offset;
00259 }
00260
00261 static int tiff_close(thandle_t ptr)
00262 {
00263 return 0;
00264 }
00265
00266 static toff_t tiff_size(thandle_t ptr)
00267 {
00268 FileTIFFUnit *tiff_unit = (FileTIFFUnit*)ptr;
00269 return tiff_unit->data->get_compressed_size();
00270 }
00271
00272 static int tiff_mmap(thandle_t ptr, tdata_t* pbase, toff_t* psize)
00273 {
00274 FileTIFFUnit *tiff_unit = (FileTIFFUnit*)ptr;
00275 *pbase = tiff_unit->data->get_data();
00276 *psize = tiff_unit->data->get_compressed_size();
00277 return 0;
00278 }
00279
00280 void tiff_unmap(thandle_t ptr, tdata_t base, toff_t size)
00281 {
00282 }
00283
00284 int FileTIFF::read_frame(VFrame *output, VFrame *input)
00285 {
00286 FileTIFFUnit *unit = new FileTIFFUnit(this, 0);
00287 TIFF *stream;
00288 unit->offset = 0;
00289 unit->data = input;
00290
00291 stream = TIFFClientOpen("FileTIFF",
00292 "r",
00293 (void*)unit,
00294 tiff_read,
00295 tiff_write,
00296 tiff_seek,
00297 tiff_close,
00298 tiff_size,
00299 tiff_mmap,
00300 tiff_unmap);
00301
00302
00303
00304
00305 for(int i = 0; i < asset->height; i++)
00306 {
00307 TIFFReadScanline(stream, output->get_rows()[i], i, 0);
00308
00309
00310 if(asset->tiff_cmodel == FileTIFF::GREYSCALE)
00311 {
00312 unsigned char *row = output->get_rows()[i];
00313 for(int j = output->get_w() - 1; j >= 0; j--)
00314 {
00315 unsigned char value = row[j];
00316 row[j * 3] = value;
00317 row[j * 3 + 1] = value;
00318 row[j * 3 + 2] = value;
00319 }
00320 }
00321
00322 else
00323 if(asset->tiff_cmodel == FileTIFF::RGB_161616)
00324 {
00325 uint16_t *input_row = (uint16_t*)output->get_rows()[i];
00326 float *output_row = (float*)output->get_rows()[i];
00327 for(int j = output->get_w() - 1; j >= 0; j--)
00328 {
00329 uint16_t r = input_row[j * 3];
00330 uint16_t g = input_row[j * 3 + 1];
00331 uint16_t b = input_row[j * 3 + 2];
00332 output_row[j * 3] = (float)r / 65535;
00333 output_row[j * 3 + 1] = (float)g / 65535;
00334 output_row[j * 3 + 2] = (float)b / 65535;
00335 }
00336 }
00337 else
00338 if(asset->tiff_cmodel == FileTIFF::RGBA_16161616)
00339 {
00340 uint16_t *input_row = (uint16_t*)output->get_rows()[i];
00341 float *output_row = (float*)output->get_rows()[i];
00342 for(int j = output->get_w() - 1; j >= 0; j--)
00343 {
00344 uint16_t r = input_row[j * 4];
00345 uint16_t g = input_row[j * 4 + 1];
00346 uint16_t b = input_row[j * 4 + 2];
00347 output_row[j * 4] = (float)r / 65535;
00348 output_row[j * 4 + 1] = (float)g / 65535;
00349 output_row[j * 4 + 2] = (float)b / 65535;
00350 }
00351 }
00352 }
00353 TIFFClose(stream);
00354 delete unit;
00355
00356 return 0;
00357 }
00358
00359 int FileTIFF::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit)
00360 {
00361
00362 FileTIFFUnit *tiff_unit = (FileTIFFUnit*)unit;
00363 int result = 0;
00364 TIFF *stream;
00365 tiff_unit->offset = 0;
00366 tiff_unit->data = data;
00367 tiff_unit->data->set_compressed_size(0);
00368
00369 stream = TIFFClientOpen("FileTIFF",
00370 "w",
00371 (void*)tiff_unit,
00372 tiff_read,
00373 tiff_write,
00374 tiff_seek,
00375 tiff_close,
00376 tiff_size,
00377 tiff_mmap,
00378 tiff_unmap);
00379
00380 int components, color_model, bits, type, compression;
00381 int sampleformat = SAMPLEFORMAT_UINT;
00382 int bytesperrow;
00383 switch(asset->tiff_cmodel)
00384 {
00385 case FileTIFF::RGB_888:
00386 components = 3;
00387 color_model = BC_RGB888;
00388 bits = 8;
00389 type = TIFF_BYTE;
00390 bytesperrow = 3 * asset->width;
00391 break;
00392 case FileTIFF::RGB_161616:
00393 components = 3;
00394 color_model = BC_RGB_FLOAT;
00395 bits = 16;
00396 type = TIFF_SHORT;
00397 bytesperrow = 6 * asset->width;
00398 break;
00399 case FileTIFF::RGBA_8888:
00400 components = 4;
00401 color_model = BC_RGBA8888;
00402 bits = 8;
00403 type = TIFF_BYTE;
00404 bytesperrow = 4 * asset->width;
00405 break;
00406 case FileTIFF::RGBA_16161616:
00407 components = 4;
00408 color_model = BC_RGBA_FLOAT;
00409 bits = 16;
00410 type = TIFF_SHORT;
00411 bytesperrow = 8 * asset->width;
00412 break;
00413 case FileTIFF::RGB_FLOAT:
00414 components = 3;
00415 color_model = BC_RGB_FLOAT;
00416 bits = 32;
00417 type = TIFF_FLOAT;
00418 sampleformat = SAMPLEFORMAT_IEEEFP;
00419 bytesperrow = 12 * asset->width;
00420 break;
00421 case FileTIFF::RGBA_FLOAT:
00422 components = 4;
00423 color_model = BC_RGBA_FLOAT;
00424 bits = 32;
00425 type = TIFF_FLOAT;
00426 sampleformat = SAMPLEFORMAT_IEEEFP;
00427 bytesperrow = 16 * asset->width;
00428 break;
00429 default:
00430 components = 3;
00431 color_model = BC_RGB888;
00432 bits = 8;
00433 type = TIFF_BYTE;
00434 bytesperrow = 3 * asset->width;
00435 break;
00436 }
00437
00438
00439 switch(asset->tiff_compression)
00440 {
00441 case FileTIFF::LZW:
00442 compression = COMPRESSION_LZW;
00443 break;
00444 case FileTIFF::PACK_BITS:
00445 compression = COMPRESSION_PACKBITS;
00446 break;
00447 case FileTIFF::DEFLATE:
00448 compression = COMPRESSION_DEFLATE;
00449 break;
00450 case FileTIFF::JPEG:
00451 compression = COMPRESSION_JPEG;
00452 break;
00453 default:
00454 compression = COMPRESSION_NONE;
00455 break;
00456 }
00457
00458 TIFFSetField(stream, TIFFTAG_IMAGEWIDTH, asset->width);
00459 TIFFSetField(stream, TIFFTAG_IMAGELENGTH, asset->height);
00460 TIFFSetField(stream, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
00461 TIFFSetField(stream, TIFFTAG_SAMPLESPERPIXEL, components);
00462 TIFFSetField(stream, TIFFTAG_BITSPERSAMPLE, bits);
00463 TIFFSetField(stream, TIFFTAG_SAMPLEFORMAT, sampleformat);
00464 TIFFSetField(stream, TIFFTAG_COMPRESSION, compression);
00465 TIFFSetField(stream, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00466 TIFFSetField(stream, TIFFTAG_ROWSPERSTRIP,
00467 TIFFDefaultStripSize(stream, (uint32_t)-1));
00468
00469
00470 TIFFSetField(stream, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
00471
00472 if(frame->get_color_model() == color_model)
00473 {
00474 for(int i = 0; i < asset->height; i++)
00475 {
00476 TIFFWriteScanline(stream, frame->get_rows()[i], i, 0);
00477 }
00478 }
00479 else
00480 {
00481 if(tiff_unit->temp &&
00482 tiff_unit->temp->get_color_model() != color_model)
00483 {
00484 delete tiff_unit->temp;
00485 tiff_unit->temp = 0;
00486 }
00487 if(!tiff_unit->temp)
00488 {
00489 tiff_unit->temp = new VFrame(0,
00490 asset->width,
00491 asset->height,
00492 color_model);
00493 }
00494
00495 cmodel_transfer(tiff_unit->temp->get_rows(),
00496 frame->get_rows(),
00497 tiff_unit->temp->get_y(),
00498 tiff_unit->temp->get_u(),
00499 tiff_unit->temp->get_v(),
00500 frame->get_y(),
00501 frame->get_u(),
00502 frame->get_v(),
00503 0,
00504 0,
00505 frame->get_w(),
00506 frame->get_h(),
00507 0,
00508 0,
00509 frame->get_w(),
00510 frame->get_h(),
00511 frame->get_color_model(),
00512 color_model,
00513 0,
00514 frame->get_w(),
00515 frame->get_w());
00516 for(int i = 0; i < asset->height; i++)
00517 {
00518 TIFFWriteScanline(stream, tiff_unit->temp->get_rows()[i], i, 0);
00519 }
00520 }
00521
00522 TIFFClose(stream);
00523
00524
00525 return result;
00526 }
00527
00528 FrameWriterUnit* FileTIFF::new_writer_unit(FrameWriter *writer)
00529 {
00530 return new FileTIFFUnit(this, writer);
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540 FileTIFFUnit::FileTIFFUnit(FileTIFF *file, FrameWriter *writer)
00541 : FrameWriterUnit(writer)
00542 {
00543 this->file = file;
00544 temp = 0;
00545 }
00546
00547 FileTIFFUnit::~FileTIFFUnit()
00548 {
00549 if(temp) delete temp;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 TIFFConfigVideo::TIFFConfigVideo(BC_WindowBase *parent_window, Asset *asset)
00564 : BC_Window(PROGRAM_NAME ": Video Compression",
00565 parent_window->get_abs_cursor_x(1),
00566 parent_window->get_abs_cursor_y(1),
00567 400,
00568 200)
00569 {
00570 this->parent_window = parent_window;
00571 this->asset = asset;
00572 }
00573
00574 TIFFConfigVideo::~TIFFConfigVideo()
00575 {
00576 }
00577
00578 int TIFFConfigVideo::create_objects()
00579 {
00580 int x = 10, y = 10;
00581
00582 add_subwindow(new BC_Title(x, y, "Colorspace:"));
00583 TIFFColorspace *menu1;
00584 add_subwindow(menu1 = new TIFFColorspace(this, x + 150, y, 200));
00585 menu1->create_objects();
00586 y += 40;
00587 add_subwindow(new BC_Title(x, y, "Compression:"));
00588 TIFFCompression *menu2;
00589 add_subwindow(menu2 = new TIFFCompression(this, x + 150, y, 200));
00590 menu2->create_objects();
00591
00592 add_subwindow(new BC_OKButton(this));
00593 return 0;
00594 }
00595
00596 int TIFFConfigVideo::close_event()
00597 {
00598 set_done(0);
00599 return 1;
00600 }
00601
00602
00603
00604
00605
00606
00607 TIFFColorspace::TIFFColorspace(TIFFConfigVideo *gui, int x, int y, int w)
00608 : BC_PopupMenu(x,
00609 y,
00610 w,
00611 FileTIFF::cmodel_to_str(gui->asset->tiff_cmodel))
00612 {
00613 this->gui = gui;
00614 }
00615 int TIFFColorspace::handle_event()
00616 {
00617 return 1;
00618 }
00619 void TIFFColorspace::create_objects()
00620 {
00621 add_item(new TIFFColorspaceItem(gui, FileTIFF::RGB_888));
00622
00623 add_item(new TIFFColorspaceItem(gui, FileTIFF::RGBA_8888));
00624
00625 add_item(new TIFFColorspaceItem(gui, FileTIFF::RGB_FLOAT));
00626 add_item(new TIFFColorspaceItem(gui, FileTIFF::RGBA_FLOAT));
00627 }
00628
00629
00630 TIFFColorspaceItem::TIFFColorspaceItem(TIFFConfigVideo *gui, int value)
00631 : BC_MenuItem(FileTIFF::cmodel_to_str(value))
00632 {
00633 this->gui = gui;
00634 this->value = value;
00635 }
00636 int TIFFColorspaceItem::handle_event()
00637 {
00638 gui->asset->tiff_cmodel = value;
00639 return 0;
00640 }
00641
00642
00643
00644
00645
00646
00647
00648 TIFFCompression::TIFFCompression(TIFFConfigVideo *gui, int x, int y, int w)
00649 : BC_PopupMenu(x, y, w, FileTIFF::compression_to_str(gui->asset->tiff_compression))
00650 {
00651 this->gui = gui;
00652 }
00653 int TIFFCompression::handle_event()
00654 {
00655 return 1;
00656 }
00657 void TIFFCompression::create_objects()
00658 {
00659 add_item(new TIFFCompressionItem(gui, FileTIFF::NONE));
00660
00661 add_item(new TIFFCompressionItem(gui, FileTIFF::PACK_BITS));
00662
00663
00664 }
00665
00666
00667
00668
00669
00670 TIFFCompressionItem::TIFFCompressionItem(TIFFConfigVideo *gui, int value)
00671 : BC_MenuItem(FileTIFF::compression_to_str(value))
00672 {
00673 this->gui = gui;
00674 this->value = value;
00675 }
00676 int TIFFCompressionItem::handle_event()
00677 {
00678 gui->asset->tiff_compression = value;
00679 return 0;
00680 }
00681
00682
00683