// Copyright (C) 1999-2017 // Smithsonian Astrophysical Observatory, Cambridge, MA, USA // For conditions of distribution and use, see copyright notice in "copyright" #include #include #include using namespace std; #include "gzip.h" #include "zlib.h" #include "util.h" template FitsGzipm::FitsGzipm(FitsFile* fits) : FitsCompressm(fits) { FitsCompressm::uncompress(fits); } template int FitsGzipm::compressed(T* dest, char* sptr, char* heap, int kkstart, int kkstop, int jjstart, int jjstop, int iistart, int iistop) { double zs = FitsCompressm::bscale_; if (FitsCompressm::zscale_) zs = FitsCompressm::zscale_->value(sptr,0); double zz = FitsCompressm::bzero_; if (FitsCompressm::zzero_) zz = FitsCompressm::zzero_->value(sptr,0); int blank = FitsCompressm::blank_; if (FitsCompressm::zblank_) blank = (int)FitsCompressm::zblank_->value(sptr,0); int icnt=0; unsigned char* ibuf = (unsigned char*)((FitsBinColumnArray*)FitsCompressm::compress_)->get(heap, sptr, &icnt); // ibuf can be NULL if (!ibuf || !icnt) return 0; int ocnt = FitsCompressm::tilesize_; char* obuf = new char[ocnt*sizeof(long long)]; if (!obuf) { internalError("Fitsy++ gzip unable to alloc."); return 0; } z_stream zstrm; zstrm.next_in = NULL; zstrm.avail_in = 0; zstrm.zalloc = NULL; zstrm.zfree = NULL; zstrm.opaque = NULL; // look for both zlib and gzip headers if (inflateInit2(&zstrm, MAX_WBITS+32) != Z_OK) { internalError("Fitsy++ gzip inflateInit error"); if (obuf) delete [] obuf; return 0; } zstrm.avail_in = icnt; zstrm.next_in = ibuf; zstrm.avail_out = ocnt*sizeof(long long); zstrm.next_out = (Bytef*)obuf; if (DebugCompress) cerr << " inflate START: avail_in " << zstrm.avail_in << " avail_out " << zstrm.avail_out << " total_in " << zstrm.total_in << " total_out " << zstrm.total_out << endl; int result = ::inflate(&zstrm, Z_FINISH); switch (result) { case Z_OK: if (DebugCompress) cerr << " inflate OK: avail_in " << zstrm.avail_in << " avail_out " << zstrm.avail_out << " total_in " << zstrm.total_in << " total_out " << zstrm.total_out << endl; break; case Z_STREAM_END: if (DebugCompress) cerr << " inflate STREAM_END: avail_in " << zstrm.avail_in << " avail_out " << zstrm.avail_out << " total_in " << zstrm.total_in << " total_out " << zstrm.total_out << endl; break; case Z_BUF_ERROR: if (DebugCompress) cerr << " inflate BUF_ERROR: avail_in " << zstrm.avail_in << " avail_out " << zstrm.avail_out << endl; if (obuf) delete [] obuf; return 0; default: internalError("Fitsy++ gzip inflate error"); if (obuf) delete [] obuf; return 0; } int bytepix = zstrm.total_out/FitsCompressm::tilesize_; inflateEnd(&zstrm); // GZIP_2- unshuffle if needed if (!strncmp(FitsCompressm::type_,"GZIP_2",6)) { switch (bytepix) { case 1: break; case 2: { int ll = ocnt*sizeof(short); char* nbuf = new char[ll]; if (!nbuf) { internalError("Fitsy++ gzip unable to alloc."); if (obuf) delete [] obuf; return 0; } char* optr = obuf+ll-1; char* nptr = nbuf+ll-1; for (int ii=0; ii::width_*FitsCompressm::height_ + jj*FitsCompressm::width_ + ii; // very carefull about type conversions T val = FitsCompressm::getValue(obuf+ll,zs,zz,blank); dest[id] = val; } break; case 2: for (int kk=kkstart; kk::byteswap_) { const char* p = (const char*)((short*)obuf+ll); union { char c[2]; short s; } u; u.c[1] = *p++; u.c[0] = *p; *((short*)obuf+ll) = u.s; } // very carefull about type conversions size_t id = kk*FitsCompressm::width_*FitsCompressm::height_ + jj*FitsCompressm::width_ + ii; T val = FitsCompressm::getValue((short*)obuf+ll,zs,zz,blank); dest[id] = val; } break; case 4: for (int kk=kkstart; kk::byteswap_) { const char* p = (const char*)((int*)obuf+ll); union { char c[4]; int i; } u; u.c[3] = *p++; u.c[2] = *p++; u.c[1] = *p++; u.c[0] = *p; *((int*)obuf+ll) = u.i; } // very carefull about type conversions size_t id = kk*FitsCompressm::width_*FitsCompressm::height_ + jj*FitsCompressm::width_ + ii; T val =0; switch (FitsCompressm::quantize_) { case FitsCompress::NONE: val = FitsCompressm::getValue((float*)obuf+ll,zs,zz,blank); break; case FitsCompress::NODITHER: case FitsCompress::SUBDITHER1: case FitsCompress::SUBDITHER2: val = FitsCompressm::getValue((int*)obuf+ll,zs,zz,blank); break; } dest[id] = val; } break; case 8: for (int kk=kkstart; kk::byteswap_) { const char* p = (const char*)((long long*)obuf+ll); union { char c[8]; long long i; } u; u.c[7] = *p++; u.c[6] = *p++; u.c[5] = *p++; u.c[4] = *p++; u.c[3] = *p++; u.c[2] = *p++; u.c[1] = *p++; u.c[0] = *p; *((long long*)obuf+ll) = u.i; } // very carefull about type conversions size_t id = kk*FitsCompressm::width_*FitsCompressm::height_ + jj*FitsCompressm::width_ + ii; T val =0; switch (FitsCompressm::quantize_) { case FitsCompress::NONE: val = FitsCompressm::getValue((double*)obuf+ll,zs,zz,blank); break; case FitsCompress::NODITHER: case FitsCompress::SUBDITHER1: case FitsCompress::SUBDITHER2: val = FitsCompressm::getValue((long long*)obuf+ll,zs,zz,blank); break; } dest[id] = val; } break; default: internalError("Fitsy++ gzip illegal bytepix"); if (obuf) delete [] obuf; return 0; } if (obuf) delete [] obuf; return 1; } template class FitsGzipm; template class FitsGzipm; template class FitsGzipm; template class FitsGzipm; template class FitsGzipm; template class FitsGzipm; template class FitsGzipm;