unsigned long imCalcCountColors(const imImage* image) { if (imColorModeDepth(image->color_space) > 1) return count_comp(image); else return count_map(image); }
void imProcessMergeComponents(const imImage** src_image, imImage* dst_image) { memcpy(dst_image->data[0], src_image[0]->data[0], dst_image->plane_size); memcpy(dst_image->data[1], src_image[1]->data[0], dst_image->plane_size); memcpy(dst_image->data[2], src_image[2]->data[0], dst_image->plane_size); if (imColorModeDepth(dst_image->color_space) == 4 || dst_image->has_alpha) memcpy(dst_image->data[3], src_image[3]->data[0], dst_image->plane_size); }
int imFileFormatJP2::WriteImageData(void* data) { int count = imFileLineBufferCount(this); imCounterTotal(this->counter, count, "Writing JP2..."); /* first time count */ int depth = imColorModeDepth(this->file_color_mode); if (imColorModeHasAlpha(this->user_color_mode) && imColorModeHasAlpha(this->file_color_mode)) { jas_image_setcmpttype(image, depth-1, JAS_IMAGE_CT_OPACITY); depth--; } for (int d = 0; d < depth; d++) jas_image_setcmpttype(image, d, JAS_IMAGE_CT_COLOR(d)); int row = 0, plane = 0; for (int i = 0; i < count; i++) { imFileLineBufferWrite(this, data, row, plane); int ret = 1; if (this->file_data_type == IM_BYTE) ret = iJP2WriteLine(image, row, plane, (imbyte*)this->line_buffer); else ret = iJP2WriteLine(image, row, plane, (imushort*)this->line_buffer); if (!ret) return IM_ERR_ACCESS; if (!imCounterInc(this->counter)) return IM_ERR_COUNTER; imFileLineBufferInc(this, &row, &plane); } char outopts[512] = ""; imAttribTable* attrib_table = AttribTable(); float* ratio = (float*)attrib_table->Get("CompressionRatio"); if (ratio) sprintf(outopts, "rate=%g", (double)(1.0 / *ratio)); // The counter continuous because in Jasper all image writing is done here. BAD! ijp2_counter = this->counter; ijp2_abort = 0; ijp2_message = NULL; /* other counts */ int err = jas_image_encode(image, stream, 0 /*JP2 format always */, outopts); ijp2_counter = -1; if (err) return IM_ERR_ACCESS; jas_stream_flush(stream); return IM_ERR_NONE; }
int imFileFormatSGI::WriteImageData(void* data) { int count = imFileLineBufferCount(this); imCounterTotal(this->counter, count, "Writing SGI..."); imbyte* compressed_buffer = NULL; if (this->comp_type == SGI_RLE) // point to the extra buffer compressed_buffer = (imbyte*)this->line_buffer + this->line_buffer_size; int row = 0, plane = 0; for (int i = 0; i < count; i++) { imFileLineBufferWrite(this, data, row, plane); if (this->comp_type == SGI_VERBATIM) imBinFileWrite(handle, this->line_buffer, this->line_buffer_size/this->bpc, this->bpc); else { int length; if (this->bpc == 1) length = iSGIEncodeScanLine(compressed_buffer, (imbyte*)this->line_buffer, this->width); else length = iSGIEncodeScanLine((imushort*)compressed_buffer, (imushort*)this->line_buffer, this->width); int row_index = row + plane*this->height; this->starttab[row_index] = imBinFileTell(handle); this->lengthtab[row_index] = length*this->bpc; imBinFileWrite(handle, compressed_buffer, length, this->bpc); } if (imBinFileError(handle)) return IM_ERR_ACCESS; if (!imCounterInc(this->counter)) return IM_ERR_COUNTER; imFileLineBufferInc(this, &row, &plane); } if (this->comp_type == SGI_RLE) { imBinFileSeekTo(this->handle, 512); int tablen = this->height * imColorModeDepth(this->file_color_mode); imBinFileWrite(handle, this->starttab, tablen, 4); imBinFileWrite(handle, this->lengthtab, tablen, 4); } return IM_ERR_NONE; }
int imFileFormatJP2::ReadImageData(void* data) { int count = imFileLineBufferCount(this); imCounterTotal(this->counter, count, NULL); int alpha_plane = -1; if (imColorModeHasAlpha(this->user_color_mode) && imColorModeHasAlpha(this->file_color_mode)) alpha_plane = imColorModeDepth(this->file_color_mode) - 1; int row = 0, plane = 0; for (int i = 0; i < count; i++) { int cmpno; if (plane == alpha_plane) cmpno = jas_image_getcmptbytype(image, JAS_IMAGE_CT_OPACITY); else cmpno = jas_image_getcmptbytype(image, JAS_IMAGE_CT_COLOR(plane)); if (cmpno == -1) return IM_ERR_DATA; int ret = 1; if (this->file_data_type == IM_BYTE) ret = iJP2ReadLine(image, row, cmpno, (imbyte*)this->line_buffer); else ret = iJP2ReadLine(image, row, cmpno, (imushort*)this->line_buffer); if (!ret) return IM_ERR_ACCESS; imFileLineBufferRead(this, data, row, plane); if (!imCounterInc(this->counter)) return IM_ERR_COUNTER; imFileLineBufferInc(this, &row, &plane); } return IM_ERR_NONE; }
/*****************************************************************************\ im.ColorModeDepth(color_mode) \*****************************************************************************/ static int imluaColorModeDepth (lua_State *L) { lua_pushinteger(L, imColorModeDepth(luaL_checkinteger(L, 1))); return 1; }
int imFileFormatSGI::WriteImageInfo() { unsigned int dword_value; unsigned short word_value; unsigned char dummy[404]; memset(dummy, 0, 404); this->comp_type = SGI_VERBATIM; if (imStrEqual(this->compression, "RLE")) this->comp_type = SGI_RLE; unsigned int color_map_id = SGI_NORMAL; this->file_color_mode = imColorModeSpace(this->user_color_mode); int dimension = 2; if (this->file_color_mode == IM_BINARY) this->convert_bpp = -1; // expand 1 to 255 else if (this->file_color_mode == IM_RGB) { dimension = 3; if (imColorModeHasAlpha(this->user_color_mode)) this->file_color_mode |= IM_ALPHA; } this->file_data_type = this->user_data_type; this->bpc = 1; int max = 255; if (this->file_data_type == IM_USHORT) { max = 65535; this->bpc = 2; } this->starttab = NULL; this->lengthtab = NULL; /* writes the SGI file header */ word_value = SGI_ID; imBinFileWrite(handle, &word_value, 1, 2); /* identifier */ imBinFileWrite(handle, &this->comp_type, 1, 1); /* storage */ imBinFileWrite(handle, &this->bpc, 1, 1); /* bpc */ word_value = (imushort)dimension; imBinFileWrite(handle, &word_value, 1, 2); /* dimension */ word_value = (unsigned short)this->width; imBinFileWrite(handle, &word_value, 1, 2); /* image width */ word_value = (unsigned short)this->height; imBinFileWrite(handle, &word_value, 1, 2); /* image height */ word_value = (imushort)imColorModeDepth(this->file_color_mode); imBinFileWrite(handle, &word_value, 1, 2); /* depth */ dword_value = 0; imBinFileWrite(handle, &dword_value, 1, 4); /* min */ dword_value = max; imBinFileWrite(handle, &dword_value, 1, 4); /* max */ imBinFileWrite(handle, dummy, 4, 1); /* dummy */ /* tests if everything was ok */ if (imBinFileError(handle)) return IM_ERR_ACCESS; int size; char* image_name = (char*)AttribTable()->Get("Description", NULL, &size); if (image_name) { if (size < 80) { imBinFileWrite(handle, image_name, size, 1); imBinFileWrite(handle, dummy, 80-size, 1); } else { imBinFileWrite(handle, image_name, 79, 1); imBinFileWrite(handle, (void*)"\0", 1, 1); } } else imBinFileWrite(handle, dummy, 80, 1); /* empty image name */ dword_value = color_map_id; imBinFileWrite(handle, &dword_value, 1, 4); /* color_map_id */ imBinFileWrite(handle, dummy, 404, 1); /* dummy */ /* tests if everything was ok */ if (imBinFileError(handle)) return IM_ERR_ACCESS; if (this->comp_type == SGI_RLE) { int tablen = this->height * imColorModeDepth(this->file_color_mode); this->starttab = (unsigned int *)malloc(tablen*4); this->lengthtab = (unsigned int *)malloc(tablen*4); /* writes the empty compression control information */ /* we will write again at the end */ imBinFileWrite(handle, this->starttab, tablen*4, 1); imBinFileWrite(handle, this->lengthtab, tablen*4, 1); // allocates more than enough since compression algoritm can be ineficient this->line_buffer_extra = 2*imImageLineSize(this->width, this->file_color_mode, this->file_data_type); } /* tests if everything was ok */ if (imBinFileError(handle)) return IM_ERR_ACCESS; return IM_ERR_NONE; }
int imFileFormatJPEG::WriteImageInfo() { this->file_color_mode = imColorModeSpace(this->user_color_mode); this->file_color_mode |= IM_TOPDOWN; if (imColorModeDepth(this->file_color_mode) > 1) this->file_color_mode |= IM_PACKED; this->file_data_type = IM_BYTE; /* Step 3: set parameters for compression */ this->cinfo.image_width = this->width; /* image width and height, in pixels */ this->cinfo.image_height = this->height; this->cinfo.input_components = imColorModeDepth(this->file_color_mode); switch (imColorModeSpace(this->user_color_mode)) { case IM_BINARY: this->convert_bpp = -1; // expand 1 to 255 case IM_GRAY: this->cinfo.in_color_space = JCS_GRAYSCALE; break; case IM_RGB: this->cinfo.in_color_space = JCS_RGB; break; case IM_CMYK: this->cinfo.in_color_space = JCS_CMYK; break; case IM_YCBCR: this->cinfo.in_color_space = JCS_YCbCr; break; default: this->cinfo.in_color_space = JCS_UNKNOWN; break; } if (setjmp(this->jerr.setjmp_buffer)) return IM_ERR_ACCESS; jpeg_set_defaults(&this->cinfo); imAttribTable* attrib_table = AttribTable(); int* auto_ycbcr = (int*)attrib_table->Get("AutoYCbCr"); if (auto_ycbcr && *auto_ycbcr == 0 && this->cinfo.in_color_space == JCS_RGB) { jpeg_set_colorspace(&this->cinfo, JCS_RGB); } int* interlaced = (int*)attrib_table->Get("Interlaced"); if (interlaced && *interlaced) jpeg_simple_progression(&this->cinfo); int* quality = (int*)attrib_table->Get("JPEGQuality"); if (quality) jpeg_set_quality(&this->cinfo, *quality, TRUE); char* res_unit = (char*)attrib_table->Get("ResolutionUnit"); if (res_unit) { float* xres = (float*)attrib_table->Get("XResolution"); float* yres = (float*)attrib_table->Get("YResolution"); if (xres && yres) { if (imStrEqual(res_unit, "DPI")) this->cinfo.density_unit = 1; else this->cinfo.density_unit = 2; this->cinfo.X_density = (UINT16)*xres; this->cinfo.Y_density = (UINT16)*yres; } } /* Step 4: Start compressor */ jpeg_start_compress(&this->cinfo, TRUE); int desc_size; char* desc = (char*)attrib_table->Get("Description", NULL, &desc_size); if (desc) jpeg_write_marker(&this->cinfo, JPEG_COM, (JOCTET*)desc, desc_size-1); #ifdef USE_EXIF iWriteExifAttrib(attrib_table); #endif return IM_ERR_NONE; }
int imFileFormatJPEG::ReadImageInfo(int index) { (void)index; this->fix_adobe_cmyk = 0; if (setjmp(this->jerr.setjmp_buffer)) return IM_ERR_ACCESS; // notify libjpeg to save the COM marker jpeg_save_markers(&this->dinfo, JPEG_COM, 0xFFFF); jpeg_save_markers(&this->dinfo, JPEG_APP0+1, 0xFFFF); /* Step 3: read file parameters with jpeg_read_header() */ if (jpeg_read_header(&this->dinfo, TRUE) != JPEG_HEADER_OK) return IM_ERR_ACCESS; this->width = this->dinfo.image_width; this->height = this->dinfo.image_height; this->file_data_type = IM_BYTE; switch(this->dinfo.jpeg_color_space) { case JCS_GRAYSCALE: this->file_color_mode = IM_GRAY; break; case JCS_RGB: this->file_color_mode = IM_RGB; break; case JCS_YCbCr: this->file_color_mode = IM_RGB; break; case JCS_CMYK: this->file_color_mode = IM_CMYK; if (this->dinfo.saw_Adobe_marker) this->fix_adobe_cmyk = 1; break; case JCS_YCCK: this->file_color_mode = IM_CMYK; this->dinfo.out_color_space = JCS_CMYK; // this is the only supported conversion in libjpeg if (this->dinfo.saw_Adobe_marker) this->fix_adobe_cmyk = 1; break; default: /* JCS_UNKNOWN */ return IM_ERR_DATA; } imAttribTable* attrib_table = AttribTable(); int* auto_ycbcr = (int*)attrib_table->Get("AutoYCbCr"); if (auto_ycbcr && *auto_ycbcr == 0 && this->dinfo.jpeg_color_space == JCS_YCbCr) { this->file_color_mode = IM_YCBCR; this->dinfo.out_color_space = JCS_YCbCr; } this->file_color_mode |= IM_TOPDOWN; if (imColorModeDepth(this->file_color_mode) > 1) this->file_color_mode |= IM_PACKED; if (this->dinfo.progressive_mode != 0) { int progressive = 1; attrib_table->Set("Interlaced", IM_INT, 1, &progressive); } if (this->dinfo.density_unit != 0) { float xres = (float)this->dinfo.X_density, yres = (float)this->dinfo.Y_density; if (this->dinfo.density_unit == 1) attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPI"); else attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPC"); attrib_table->Set("XResolution", IM_FLOAT, 1, (void*)&xres); attrib_table->Set("YResolution", IM_FLOAT, 1, (void*)&yres); } if (this->dinfo.marker_list) { jpeg_saved_marker_ptr cur_marker = this->dinfo.marker_list; // search for COM marker while (cur_marker) { if (cur_marker->marker == JPEG_COM) { char* desc = new char [cur_marker->data_length+1]; memcpy(desc, cur_marker->data, cur_marker->data_length); desc[cur_marker->data_length] = 0; attrib_table->Set("Description", IM_BYTE, cur_marker->data_length+1, desc); delete [] desc; } #ifdef USE_EXIF if (cur_marker->marker == JPEG_APP0+1) iReadExifAttrib(cur_marker->data, cur_marker->data_length, attrib_table); #endif cur_marker = cur_marker->next; } } /* Step 5: Start decompressor */ if (jpeg_start_decompress(&this->dinfo) == FALSE) return IM_ERR_ACCESS; return IM_ERR_NONE; }
int imFileFormatJP2::WriteImageInfo() { this->file_data_type = this->user_data_type; this->file_color_mode = imColorModeSpace(this->user_color_mode); this->file_color_mode |= IM_TOPDOWN; int prec = 8; if (this->file_data_type == IM_USHORT) prec = 16; jas_clrspc_t clrspc; switch (imColorModeSpace(this->user_color_mode)) { case IM_BINARY: prec = 1; case IM_GRAY: clrspc = JAS_CLRSPC_SGRAY; break; case IM_RGB: clrspc = JAS_CLRSPC_SRGB; break; case IM_XYZ: clrspc = JAS_CLRSPC_CIEXYZ; break; case IM_LAB: clrspc = JAS_CLRSPC_CIELAB; break; case IM_YCBCR: clrspc = JAS_CLRSPC_SYCBCR; break; default: return IM_ERR_DATA; } if (imColorModeHasAlpha(this->user_color_mode)) this->file_color_mode |= IM_ALPHA; int numcmpts = imColorModeDepth(this->file_color_mode); jas_image_cmptparm_t cmptparms[4]; for (int i = 0; i < numcmpts; i++) { jas_image_cmptparm_t* cmptparm = &cmptparms[i]; cmptparm->tlx = 0; cmptparm->tly = 0; cmptparm->hstep = 1; cmptparm->vstep = 1; cmptparm->width = this->width; cmptparm->height = this->height; cmptparm->prec = prec; cmptparm->sgnd = 0; } this->image = jas_image_create(numcmpts, cmptparms, clrspc); if (!this->image) return IM_ERR_DATA; if (this->image->metadata.count > 0) { const void* data; int size; imAttribTable* attrib_table = AttribTable(); // GeoTIFF first data = attrib_table->Get("GeoTIFFBox", NULL, &size); if (data) { jas_metadata_box_t *metabox = &image->metadata.boxes[JAS_IMAGE_BOX_GEO]; jas_box_alloc(metabox, size); memcpy(metabox->buf, data, size); memcpy(metabox->id, msi_uuid, sizeof(msi_uuid)); } // Adobe XMP data = attrib_table->Get("XMLPacket", NULL, &size); if (data) { jas_metadata_box_t *metabox = &image->metadata.boxes[JAS_IMAGE_BOX_XMP]; jas_box_alloc(metabox, size); memcpy(metabox->buf, data, size); memcpy(metabox->id, xmp_uuid, sizeof(xmp_uuid)); } } return IM_ERR_NONE; }
int imFileFormatECW::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_SHORT) { eType = NCSCT_INT16; type_size = 2; } else 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 imFileFormatECW::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: this->file_data_type = IM_SHORT; break; case NCSCT_UINT16: this->file_data_type = IM_USHORT; break; case NCSCT_INT64: 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_SHORT; break; case NCSCT_UINT64: case NCSCT_UINT32: // 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; }