diff options
Diffstat (limited to 'src/im_format_ecw.cpp')
-rw-r--r-- | src/im_format_ecw.cpp | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/src/im_format_ecw.cpp b/src/im_format_ecw.cpp new file mode 100644 index 0000000..0b77b56 --- /dev/null +++ b/src/im_format_ecw.cpp @@ -0,0 +1,375 @@ +/** \file + * \brief ECW - ECW JPEG 2000 + * + * See Copyright Notice in im_lib.h + */ + +#include "im_format.h" +#include "im_util.h" +#include "im_format_ecw.h" +#include "im_counter.h" + +#include <NCSECWClient.h> +// #include <NCSEcwCompressClient.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> + +static const char* iECWCompTable[2] = +{ + "ECW", + "JPEG-2000", +}; + +class imFormatECW: public imFormat +{ + NCSFileView *pNCSFileView; +// NCSEcwCompressClient *pClient; + +public: + imFormatECW() + :imFormat("ECW", + "ECW JPEG-2000 File Format", + "*.ecw;*.jp2;*.j2k;*.jpc;*.j2c;", + iECWCompTable, + 2, + 0) + {} + + int Open(const char* file_name); + int New(const char* file_name); + void Close(); + void* Handle(int index); + int ReadImageInfo(int index); + int ReadImageData(void* data); + int WriteImageInfo(){return 0;} // do nothing for now; + int WriteImageData(void* data){(void)data; return 0;} // do nothing for now; + int CanWrite(const char* compression, int color_mode, int data_type) const; +}; + +void imFormatRegisterECW(void) +{ + imFormatRegister(new imFormatECW()); +} + +int imFormatECW::Open(const char* file_name) +{ + NCSError eError = NCScbmOpenFileView((char*)file_name, &this->pNCSFileView, NULL); + if (eError != NCS_SUCCESS) + { + if (eError == NCS_FILE_OPEN_ERROR || + eError == NCS_FILE_NOT_FOUND || + eError == NCS_FILE_INVALID) + return IM_ERR_OPEN; + else if (eError == NCS_FILE_OPEN_FAILED) + return IM_ERR_FORMAT; + else + return IM_ERR_ACCESS; + } + + NCSFileType fileType = NCScbmGetFileType(this->pNCSFileView); + if (fileType == NCS_FILE_ECW) + strcpy(this->compression, "ECW"); + else if (fileType == NCS_FILE_JP2) + strcpy(this->compression, "JPEG-2000"); + else + return IM_ERR_COMPRESS; + + this->image_count = 1; + + return IM_ERR_NONE; +} + +int imFormatECW::New(const char* file_name) +{ + strcpy(this->compression, "JPEG-2000"); + this->image_count = 1; + + (void)file_name; + return IM_ERR_FORMAT; +} + +void imFormatECW::Close() +{ + if (this->is_new) + ;// NCSEcwCompressClose(this->pClient); + else + NCScbmCloseFileView(this->pNCSFileView); +} + +void* imFormatECW::Handle(int index) +{ + (void)index; + + if (this->is_new) + return NULL; // return (void*)this->pClient; + else + return (void*)this->pNCSFileView; +} + +int imFormatECW::ReadImageInfo(int index) +{ + NCSFileViewFileInfoEx *pNCSFileInfo; + imAttribTable* attrib_table = AttribTable(); + (void)index; + + if (NCScbmGetViewFileInfoEx(this->pNCSFileView, &pNCSFileInfo) != NCS_SUCCESS) + return IM_ERR_ACCESS; + + this->width = pNCSFileInfo->nSizeX; + this->height = pNCSFileInfo->nSizeY; + + switch(pNCSFileInfo->eColorSpace) + { + case NCSCS_GREYSCALE: + this->file_color_mode = IM_GRAY; + break; + case NCSCS_YUV: + case NCSCS_sRGB: + this->file_color_mode = IM_RGB; + break; + case NCSCS_YCbCr: + this->file_color_mode = IM_YCBCR; + break; + case NCSCS_MULTIBAND: + /* multiband data, we read only one band */ + this->file_color_mode = IM_GRAY; + attrib_table->Set("MultiBandCount", IM_USHORT, 1, (void*)&pNCSFileInfo->nBands); + break; + default: + return IM_ERR_DATA; + } + + switch(pNCSFileInfo->eCellType) + { + case NCSCT_INT8: + case NCSCT_UINT8: + this->file_data_type = IM_BYTE; + break; + case NCSCT_INT16: + case NCSCT_UINT16: + this->file_data_type = IM_USHORT; + break; + case NCSCT_UINT64: + case NCSCT_INT64: + case NCSCT_UINT32: + case NCSCT_INT32: + // Should be: this->file_data_type = IM_INT; + // but 32bits ints are not supported by the NCScbmReadViewLineBILEx function + this->file_data_type = IM_USHORT; + break; + case NCSCT_IEEE4: + case NCSCT_IEEE8: + this->file_data_type = IM_FLOAT; + break; + default: + return IM_ERR_DATA; + } + + int prec = pNCSFileInfo->pBands->nBits; + if (prec < 8) + this->convert_bpp = -prec; // just expand to 0-255 + + if (prec == 1 && this->file_color_mode == IM_GRAY) + this->file_color_mode = IM_BINARY; + + if (pNCSFileInfo->nBands > imColorModeDepth(this->file_color_mode)) + this->file_color_mode |= IM_ALPHA; + + if (this->file_color_mode != IM_GRAY) + this->file_color_mode |= IM_PACKED; + + this->file_color_mode |= IM_TOPDOWN; + + float float_value = (float)pNCSFileInfo->fOriginX; + attrib_table->Set("OriginX", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fOriginY; + attrib_table->Set("OriginY", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fCWRotationDegrees; + attrib_table->Set("Rotation", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fCellIncrementX; + attrib_table->Set("CellIncrementX", IM_FLOAT, 1, (void*)&float_value); + + float_value = (float)pNCSFileInfo->fCellIncrementY; + attrib_table->Set("CellIncrementY", IM_FLOAT, 1, (void*)&float_value); + + attrib_table->Set("Datum", IM_BYTE, strlen(pNCSFileInfo->szDatum)+1, pNCSFileInfo->szDatum); + attrib_table->Set("Projection", IM_BYTE, strlen(pNCSFileInfo->szProjection)+1, pNCSFileInfo->szProjection); + + switch (pNCSFileInfo->eCellSizeUnits) + { + case ECW_CELL_UNITS_INVALID: + attrib_table->Set("CellUnits", IM_BYTE, 8, "INVALID"); + break; + case ECW_CELL_UNITS_METERS: + attrib_table->Set("CellUnits", IM_BYTE, 7, "METERS"); + break; + case ECW_CELL_UNITS_DEGREES: + attrib_table->Set("CellUnits", IM_BYTE, 7, "DEGREES"); + break; + case ECW_CELL_UNITS_FEET: + attrib_table->Set("CellUnits", IM_BYTE, 5, "FEET"); + break; + case ECW_CELL_UNITS_UNKNOWN: + attrib_table->Set("CellUnits", IM_BYTE, 8, "UNKNOWN"); + break; + } + + float_value = (float)pNCSFileInfo->nCompressionRate; + attrib_table->Set("CompressionRatio", IM_FLOAT, 1, (void*)&float_value); + + return IM_ERR_NONE; +} + +static void iCopyDataBuffer(UINT8 **ppOutputLine, imbyte* line_buffer, int nBands, int view_width, int type_size) +{ + if (nBands > 1) + { + for(int i = 0; i < view_width; i++) + { + for(int j = 0; j < nBands; j++) + { + for(int k = 0; k < type_size; k++) + { + *line_buffer++ = (ppOutputLine[j])[i*type_size + k]; + } + } + } + } + else + memcpy(line_buffer, ppOutputLine[0], nBands*type_size*view_width); +} + +int imFormatECW::ReadImageData(void* data) +{ + imAttribTable* attrib_table = AttribTable(); + int i, *attrib_data, view_width, view_height, + nBands = imColorModeDepth(this->file_color_mode); + + // this size is free, can be anything, but we restricted to less than the image size + attrib_data = (int*)attrib_table->Get("ViewWidth"); + view_width = attrib_data? *attrib_data: this->width; + if (view_width > this->width) view_width = this->width; + + attrib_data = (int*)attrib_table->Get("ViewHeight"); + view_height = attrib_data? *attrib_data: this->height; + if (view_height > this->height) view_height = this->height; + + imCounterTotal(this->counter, view_height, "Reading ECW..."); + + { + int xmin, xmax, ymin, ymax, band_start; + + // full image if not defined. + // this size must be inside the image + attrib_data = (int*)attrib_table->Get("ViewXmin"); + xmin = attrib_data? *attrib_data: 0; + if (xmin < 0) xmin = 0; + + attrib_data = (int*)attrib_table->Get("ViewYmin"); + ymin = attrib_data? *attrib_data: 0; + if (ymin < 0) ymin = 0; + + attrib_data = (int*)attrib_table->Get("ViewXmax"); + xmax = attrib_data? *attrib_data: this->width-1; + if (xmax > this->width-1) xmax = this->width-1; + + attrib_data = (int*)attrib_table->Get("ViewYmax"); + ymax = attrib_data? *attrib_data: this->height-1; + if (ymax > this->height-1) ymax = this->height-1; + + band_start = 0; + UINT16* start_plane = (UINT16*)attrib_table->Get("MultiBandSelect"); + if (start_plane) + band_start = *start_plane; + + UINT32 *pBandList = (UINT32*)malloc(sizeof(UINT32)*nBands); + for(i = 0; i < nBands; i++) + pBandList[i] = i+band_start; + + NCSError eError = NCScbmSetFileView(this->pNCSFileView, nBands, pBandList, + xmin, ymin, xmax, ymax, + view_width, view_height); + free(pBandList); + + if( eError != NCS_SUCCESS) + return IM_ERR_DATA; + } + + // this is necessary to fool line buffer management + this->width = view_width; + this->height = view_height; + this->line_buffer_size = imImageLineSize(this->width, this->file_color_mode, this->file_data_type); + + NCSEcwCellType eType = NCSCT_UINT8; + int type_size = 1; + if (this->file_data_type == IM_USHORT) + { + eType = NCSCT_UINT16; + type_size = 2; + } + else if (this->file_data_type == IM_FLOAT) + { + eType = NCSCT_IEEE4; + type_size = 4; + } + UINT8 **ppOutputLine = (UINT8**)malloc(sizeof(UINT8*)*nBands); + UINT8 *ppOutputBuffer = (UINT8*)malloc(type_size*view_width*nBands); + for(i = 0; i < nBands; i++) + ppOutputLine[i] = ppOutputBuffer + i*type_size*view_width; + + for (int row = 0; row < view_height; row++) + { + NCSEcwReadStatus eError = NCScbmReadViewLineBILEx(this->pNCSFileView, eType, (void**)ppOutputLine); + if( eError != NCS_SUCCESS) + { + free(ppOutputLine); + free(ppOutputBuffer); + return IM_ERR_DATA; + } + + iCopyDataBuffer(ppOutputLine, (imbyte*)this->line_buffer, nBands, view_width, type_size); + + imFileLineBufferRead(this, data, row, 0); + + if (!imCounterInc(this->counter)) + { + free(ppOutputLine); + free(ppOutputBuffer); + return IM_ERR_COUNTER; + } + } + + free(ppOutputLine); + free(ppOutputBuffer); + return IM_ERR_NONE; +} + +int imFormatECW::CanWrite(const char* compression, int color_mode, int data_type) const +{ + (void)compression; + (void)color_mode; + (void)data_type; + return IM_ERR_DATA; + + //int color_space = imColorModeSpace(color_mode); + + //if (color_space != IM_GRAY && color_space != IM_RGB)// && color_space != IM_LUV) + // return IM_ERR_DATA; + // + //if (data_type != IM_BYTE && data_type != IM_USHORT && data_type != IM_FLOAT) + // return IM_ERR_DATA; + + //if (!compression || compression[0] == 0) + // return IM_ERR_NONE; + + //if (!imStrEqual(compression, "JPEG-2000")) + // return IM_ERR_COMPRESS; + + //return IM_ERR_NONE; +} |