00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "imageFile.h"
00016 #include "palettizer.h"
00017 #include "filenameUnifier.h"
00018 #include "paletteGroup.h"
00019
00020 #include "pnmImage.h"
00021 #include "pnmFileType.h"
00022 #include "eggTexture.h"
00023 #include "datagram.h"
00024 #include "datagramIterator.h"
00025 #include "bamReader.h"
00026 #include "bamWriter.h"
00027
00028 TypeHandle ImageFile::_type_handle;
00029
00030
00031
00032
00033
00034
00035 ImageFile::
00036 ImageFile() {
00037 _alpha_file_channel = 0;
00038 _size_known = false;
00039 _x_size = 0;
00040 _y_size = 0;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 bool ImageFile::
00056 make_shadow_image(const string &basename) {
00057 bool any_changed = false;
00058
00059 if (_properties._color_type != pal->_shadow_color_type ||
00060 _properties._alpha_type != pal->_shadow_alpha_type) {
00061
00062 _properties._color_type = pal->_shadow_color_type;
00063 _properties._alpha_type = pal->_shadow_alpha_type;
00064 any_changed = true;
00065 }
00066
00067 if (set_filename(pal->_shadow_dirname, basename)) {
00068 any_changed = true;
00069 }
00070
00071 return any_changed;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080 bool ImageFile::
00081 is_size_known() const {
00082 return _size_known;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092 int ImageFile::
00093 get_x_size() const {
00094 nassertr(is_size_known(), 0);
00095 return _x_size;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105 int ImageFile::
00106 get_y_size() const {
00107 nassertr(is_size_known(), 0);
00108 return _y_size;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117 bool ImageFile::
00118 has_num_channels() const {
00119 return _properties.has_num_channels();
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 int ImageFile::
00130 get_num_channels() const {
00131 return _properties.get_num_channels();
00132 }
00133
00134
00135
00136
00137
00138
00139 const TextureProperties &ImageFile::
00140 get_properties() const {
00141 return _properties;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 void ImageFile::
00153 clear_basic_properties() {
00154 _properties.clear_basic();
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 void ImageFile::
00164 update_properties(const TextureProperties &properties) {
00165 _properties.update_properties(properties);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 bool ImageFile::
00181 set_filename(PaletteGroup *group, const string &basename) {
00182
00183
00184 string dirname;
00185 string::iterator pi;
00186 pi = pal->_map_dirname.begin();
00187 while (pi != pal->_map_dirname.end()) {
00188 if (*pi == '%') {
00189 ++pi;
00190 switch (*pi) {
00191 case '%':
00192 dirname += '%';
00193 break;
00194
00195 case 'g':
00196 if (group != (PaletteGroup *)NULL) {
00197 dirname += group->get_dirname();
00198 }
00199 break;
00200 }
00201 } else {
00202 dirname += *pi;
00203 }
00204 ++pi;
00205 }
00206
00207 return set_filename(dirname, basename);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 bool ImageFile::
00223 set_filename(const string &dirname, const string &basename) {
00224 Filename orig_filename = _filename;
00225 Filename orig_alpha_filename = _alpha_filename;
00226
00227 _filename = Filename(dirname, basename);
00228 _filename.standardize();
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 if (_properties._color_type != (PNMFileType *)NULL) {
00241 _filename.set_extension
00242 (_properties._color_type->get_suggested_extension());
00243 }
00244
00245 if (_properties._alpha_type != (PNMFileType *)NULL) {
00246 _alpha_filename = _filename.get_fullpath_wo_extension() + "_a.";
00247 _alpha_filename.set_extension
00248 (_properties._alpha_type->get_suggested_extension());
00249 } else {
00250 _alpha_filename = Filename();
00251 }
00252
00253 return (_filename != orig_filename ||
00254 _alpha_filename != orig_alpha_filename);
00255 }
00256
00257
00258
00259
00260
00261
00262 const Filename &ImageFile::
00263 get_filename() const {
00264 return _filename;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 const Filename &ImageFile::
00276 get_alpha_filename() const {
00277 return _alpha_filename;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 int ImageFile::
00291 get_alpha_file_channel() const {
00292 return _alpha_file_channel;
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302 bool ImageFile::
00303 exists() const {
00304 if (!_filename.exists()) {
00305 return false;
00306 }
00307 if (_properties._alpha_type != (PNMFileType *)NULL &&
00308 _properties.uses_alpha() &&
00309 !_alpha_filename.empty()) {
00310 if (!_alpha_filename.exists()) {
00311 return false;
00312 }
00313 }
00314
00315 return true;
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325 bool ImageFile::
00326 read(PNMImage &image) const {
00327 nassertr(!_filename.empty(), false);
00328
00329 image.set_type(_properties._color_type);
00330 nout << "Reading " << FilenameUnifier::make_user_filename(_filename) << "\n";
00331 if (!image.read(_filename)) {
00332 nout << "Unable to read.\n";
00333 return false;
00334 }
00335
00336 if (!_alpha_filename.empty() && _alpha_filename.exists()) {
00337
00338 PNMImage alpha_image;
00339 alpha_image.set_type(_properties._alpha_type);
00340 nout << "Reading " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n";
00341 if (!alpha_image.read(_alpha_filename)) {
00342 nout << "Unable to read.\n";
00343 return false;
00344 }
00345 if (image.get_x_size() != alpha_image.get_x_size() ||
00346 image.get_y_size() != alpha_image.get_y_size()) {
00347 return false;
00348 }
00349
00350 image.add_alpha();
00351
00352 if (_alpha_file_channel == 4 ||
00353 (_alpha_file_channel == 2 && alpha_image.get_num_channels() == 2)) {
00354
00355 for (int x = 0; x < image.get_x_size(); x++) {
00356 for (int y = 0; y < image.get_y_size(); y++) {
00357 image.set_alpha(x, y, alpha_image.get_alpha(x, y));
00358 }
00359 }
00360
00361 } else if (_alpha_file_channel >= 1 && _alpha_file_channel <= 3 &&
00362 alpha_image.get_num_channels() >= 3) {
00363
00364 for (int x = 0; x < image.get_x_size(); x++) {
00365 for (int y = 0; y < image.get_y_size(); y++) {
00366 image.set_alpha(x, y, alpha_image.get_channel_val(x, y, _alpha_file_channel - 1));
00367 }
00368 }
00369
00370 } else {
00371
00372 for (int x = 0; x < image.get_x_size(); x++) {
00373 for (int y = 0; y < image.get_y_size(); y++) {
00374 image.set_alpha(x, y, alpha_image.get_gray(x, y));
00375 }
00376 }
00377 }
00378 }
00379
00380 return true;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390 bool ImageFile::
00391 write(const PNMImage &image) const {
00392 nassertr(!_filename.empty(), false);
00393
00394 if (!image.has_alpha() ||
00395 _properties._alpha_type == (PNMFileType *)NULL) {
00396 if (!_alpha_filename.empty() && _alpha_filename.exists()) {
00397 nout << "Deleting " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n";
00398 _alpha_filename.unlink();
00399 }
00400 nout << "Writing " << FilenameUnifier::make_user_filename(_filename) << "\n";
00401 _filename.make_dir();
00402 if (!image.write(_filename, _properties._color_type)) {
00403 nout << "Unable to write.\n";
00404 return false;
00405 }
00406 return true;
00407 }
00408
00409
00410 PNMImage alpha_image(image.get_x_size(), image.get_y_size(), 1,
00411 image.get_maxval());
00412 for (int y = 0; y < image.get_y_size(); y++) {
00413 for (int x = 0; x < image.get_x_size(); x++) {
00414 alpha_image.set_gray_val(x, y, image.get_alpha_val(x, y));
00415 }
00416 }
00417
00418 PNMImage image_copy(image);
00419 image_copy.remove_alpha();
00420 nout << "Writing " << FilenameUnifier::make_user_filename(_filename) << "\n";
00421 _filename.make_dir();
00422 if (!image_copy.write(_filename, _properties._color_type)) {
00423 nout << "Unable to write.\n";
00424 return false;
00425 }
00426
00427 nout << "Writing " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n";
00428 _alpha_filename.make_dir();
00429 if (!alpha_image.write(_alpha_filename, _properties._alpha_type)) {
00430 nout << "Unable to write.\n";
00431 return false;
00432 }
00433 return true;
00434 }
00435
00436
00437
00438
00439
00440
00441 void ImageFile::
00442 unlink() {
00443 if (!_filename.empty() && _filename.exists()) {
00444 nout << "Deleting " << FilenameUnifier::make_user_filename(_filename) << "\n";
00445 _filename.unlink();
00446 }
00447 if (!_alpha_filename.empty() && _alpha_filename.exists()) {
00448 nout << "Deleting " << FilenameUnifier::make_user_filename(_alpha_filename) << "\n";
00449 _alpha_filename.unlink();
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458 void ImageFile::
00459 update_egg_tex(EggTexture *egg_tex) const {
00460 nassertv(egg_tex != (EggTexture *)NULL);
00461
00462 egg_tex->set_filename(FilenameUnifier::make_egg_filename(_filename));
00463
00464 if (_properties.uses_alpha() &&
00465 !_alpha_filename.empty()) {
00466 egg_tex->set_alpha_filename(FilenameUnifier::make_egg_filename(_alpha_filename));
00467 egg_tex->set_alpha_file_channel(_alpha_file_channel);
00468 } else {
00469 egg_tex->clear_alpha_filename();
00470 egg_tex->clear_alpha_file_channel();
00471 }
00472
00473 _properties.update_egg_tex(egg_tex);
00474 }
00475
00476
00477
00478
00479
00480
00481
00482 void ImageFile::
00483 output_filename(ostream &out) const {
00484 out << FilenameUnifier::make_user_filename(_filename);
00485 if (_properties.uses_alpha() && !_alpha_filename.empty()) {
00486 out << " " << FilenameUnifier::make_user_filename(_alpha_filename);
00487 }
00488 }
00489
00490
00491
00492
00493
00494
00495
00496
00497 void ImageFile::
00498 write_datagram(BamWriter *writer, Datagram &datagram) {
00499 TypedWritable::write_datagram(writer, datagram);
00500 _properties.write_datagram(writer, datagram);
00501 datagram.add_string(FilenameUnifier::make_bam_filename(_filename));
00502 datagram.add_string(FilenameUnifier::make_bam_filename(_alpha_filename));
00503 datagram.add_uint8(_alpha_file_channel);
00504 datagram.add_bool(_size_known);
00505 datagram.add_int32(_x_size);
00506 datagram.add_int32(_y_size);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 int ImageFile::
00519 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00520 int pi = TypedWritable::complete_pointers(p_list, manager);
00521
00522 pi += _properties.complete_pointers(p_list + pi, manager);
00523
00524 return pi;
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534 void ImageFile::
00535 fillin(DatagramIterator &scan, BamReader *manager) {
00536 TypedWritable::fillin(scan, manager);
00537 _properties.fillin(scan, manager);
00538 _filename = FilenameUnifier::get_bam_filename(scan.get_string());
00539 _alpha_filename = FilenameUnifier::get_bam_filename(scan.get_string());
00540 if (Palettizer::_read_pi_version >= 10) {
00541 _alpha_file_channel = scan.get_uint8();
00542 } else {
00543 _alpha_file_channel = 0;
00544 }
00545 _size_known = scan.get_bool();
00546 _x_size = scan.get_int32();
00547 _y_size = scan.get_int32();
00548 }