Пример #1
0
// ------------------------------------------------------------
//   Keep original size info when using scale option on loading
// ------------------------------------------------------------
static void 
store_size_info(FIBITMAP *dib, JDIMENSION width, JDIMENSION height) {
	char buffer[256];
	// create a tag
	FITAG *tag = FreeImage_CreateTag();
	if(tag) {
		size_t length = 0;
		// set the original width
		sprintf(buffer, "%d", (int)width);
		length = strlen(buffer) + 1;	// include the NULL/0 value
		FreeImage_SetTagKey(tag, "OriginalJPEGWidth");
		FreeImage_SetTagLength(tag, (DWORD)length);
		FreeImage_SetTagCount(tag, (DWORD)length);
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagValue(tag, buffer);
		FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
		// set the original height
		sprintf(buffer, "%d", (int)height);
		length = strlen(buffer) + 1;	// include the NULL/0 value
		FreeImage_SetTagKey(tag, "OriginalJPEGHeight");
		FreeImage_SetTagLength(tag, (DWORD)length);
		FreeImage_SetTagCount(tag, (DWORD)length);
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagValue(tag, buffer);
		FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
		// destroy the tag
		FreeImage_DeleteTag(tag);
	}
}
Пример #2
0
BOOL DLL_CALLCONV 
FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) {
	if(!dib) 
		return FALSE;

	TAGMAP *tagmap = NULL;

	// get the metadata model
	METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
	tagmap = (*metadata)[model];

	if(key != NULL) {

		if(!tagmap) {
			// this model, doesn't exist: create it 
			tagmap = new TAGMAP();
			(*metadata)[model] = tagmap;
		}

		// first check the tag
		if(tag) {
			if(FreeImage_GetTagKey(tag) == NULL) {
				FreeImage_SetTagKey(tag, key);
			} else if(strcmp(key, FreeImage_GetTagKey(tag)) != 0) {
				// set the tag key
				FreeImage_SetTagKey(tag, key);
			}
			if(FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth(FreeImage_GetTagType(tag)) != FreeImage_GetTagLength(tag)) {
				// invalid data count ?
				return FALSE;
			}
		}

		// delete existing tag
		FITAG *old_tag = (*tagmap)[key];
		if(old_tag) {
			FreeImage_DeleteTag(old_tag);
		}

		// create a new tag
		(*tagmap)[key] = FreeImage_CloneTag(tag);
	}
	else {
		// destroy the metadata model
		if(tagmap) {
			for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
				FITAG *tag = (*i).second;
				FreeImage_DeleteTag(tag);
			}

			delete tagmap;
			(*metadata)[model] = NULL;
		}
	}

	return TRUE;
}
Пример #3
0
/**
	Read JPEG_COM marker (comment)
*/
static BOOL 
jpeg_read_comment(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
	size_t length = datalen;
	BYTE *profile = (BYTE*)dataptr;

	// read the comment
	char *value = (char*)malloc((length + 1) * sizeof(char));
	if(value == NULL) return FALSE;
	memcpy(value, profile, length);
	value[length] = '\0';

	// create a tag
	FITAG *tag = FreeImage_CreateTag();
	if(tag) {
		unsigned int count = (unsigned int)length + 1;	// includes the null value

		FreeImage_SetTagID(tag, JPEG_COM);
		FreeImage_SetTagKey(tag, "Comment");
		FreeImage_SetTagLength(tag, count);
		FreeImage_SetTagCount(tag, count);
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagValue(tag, value);
		
		// store the tag
		FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);

		// destroy the tag
		FreeImage_DeleteTag(tag);
	}

	free(value);

	return TRUE;
}
void FreeImageGifData::add24bitBGRDataPage(int width, int height, BYTE* pData)
{
    FIBITMAP* newBitmap = FreeImage_Allocate(width, height, 24, 0x0000FF, 0x00FF00, 0xFF0000);
    BYTE* bitmapData = FreeImage_GetBits(newBitmap);
    memcpy(bitmapData, pData, width * height * 3);
    
    //Set metadata
    FIBITMAP* convBitmap = FreeImage_ColorQuantizeEx(newBitmap, FIQ_WUQUANT, 256);

    FITAG* delayTag = FreeImage_CreateTag();
    
    FreeImage_SetMetadata(FIMD_ANIMATION, convBitmap, NULL, NULL);

    LONG delayVal = 20;
    if (delayTag) {
        FreeImage_SetTagKey(delayTag, "FrameTime");
        FreeImage_SetTagType(delayTag, FIDT_LONG);
        FreeImage_SetTagCount(delayTag, 1);
        FreeImage_SetTagLength(delayTag, 4);
        FreeImage_SetTagValue(delayTag, &delayVal);
        FreeImage_SetMetadata(FIMD_ANIMATION, convBitmap, FreeImage_GetTagKey(delayTag), delayTag);
        FreeImage_DeleteTag(delayTag);
    }

    FreeImage_AppendPage(m_gifHandle, convBitmap);
    
    int pCount = FreeImage_GetPageCount(m_gifHandle);
    FreeImage_Unload(newBitmap);
    FreeImage_Unload(convBitmap);
}
Пример #5
0
/**
   Build and set a FITAG whose type is FIDT_ASCII.
   The tag must be destroyed by the caller using FreeImage_DeleteTag.
   @param model Metadata model to be filled
   @param dib Image to be filled
   @param key Tag key
   @param value Tag value
   @return Returns TRUE if successful, returns FALSE otherwise
*/
static BOOL
mng_SetKeyValue(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, const char *value) {
    if(!dib || !key || !value) {
        return FALSE;
    }
    // create a tag
    FITAG *tag = FreeImage_CreateTag();
    if(tag) {
        BOOL bSuccess = TRUE;
        // fill the tag
        DWORD tag_length = (DWORD)(strlen(value) + 1);
        bSuccess &= FreeImage_SetTagKey(tag, key);
        bSuccess &= FreeImage_SetTagLength(tag, tag_length);
        bSuccess &= FreeImage_SetTagCount(tag, tag_length);
        bSuccess &= FreeImage_SetTagType(tag, FIDT_ASCII);
        bSuccess &= FreeImage_SetTagValue(tag, value);
        if(bSuccess) {
            // set the tag
            FreeImage_SetMetadata(model, dib, FreeImage_GetTagKey(tag), tag);
        }
        FreeImage_DeleteTag(tag);
        return bSuccess;
    }

    return FALSE;
}
Пример #6
0
/**
Read JPEG_APP1 marker (Exif profile)
@param dib Input FIBITMAP
@param dataptr Pointer to the APP1 marker
@param datalen APP1 marker length
@return Returns TRUE if successful, FALSE otherwise
*/
BOOL  
jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned length) {
    // marker identifying string for Exif = "Exif\0\0"
    BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };

	// verify the identifying string
	if(memcmp(exif_signature, profile, sizeof(exif_signature)) != 0) {
		// not an Exif profile
		return FALSE;
	}

	// create a tag
	FITAG *tag = FreeImage_CreateTag();
	if(tag) {
		FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName);
		FreeImage_SetTagLength(tag, (DWORD)length);
		FreeImage_SetTagCount(tag, (DWORD)length);
		FreeImage_SetTagType(tag, FIDT_BYTE);
		FreeImage_SetTagValue(tag, profile);

		// store the tag
		FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag);

		// destroy the tag
		FreeImage_DeleteTag(tag);

		return TRUE;
	}

	return FALSE;
}
Пример #7
0
static BOOL 
ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
	// XMP keyword
	const char *g_png_xmp_keyword = "XML:com.adobe.xmp";

	FITAG *tag = NULL;
	png_textp text_ptr = NULL;
	int num_text = 0;

	// iTXt/tEXt/zTXt chuncks
	if(png_get_text(png_ptr, info_ptr, &text_ptr, &num_text) > 0) {
		for(int i = 0; i < num_text; i++) {
			// create a tag
			tag = FreeImage_CreateTag();
			if(!tag) return FALSE;

			DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length);

			FreeImage_SetTagLength(tag, tag_length);
			FreeImage_SetTagCount(tag, tag_length);
			FreeImage_SetTagType(tag, FIDT_ASCII);
			FreeImage_SetTagValue(tag, text_ptr[i].text);

			if(strcmp(text_ptr[i].key, g_png_xmp_keyword) == 0) {
				// store the tag as XMP
				FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
				FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
			} else {
				// store the tag as a comment
				FreeImage_SetTagKey(tag, text_ptr[i].key);
				FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
			}
			
			// destroy the tag
			FreeImage_DeleteTag(tag);
		}
	}

	return TRUE;
}
Пример #8
0
void ofxGifEncoder::doSave() {
	// create a multipage bitmap
	FIMULTIBITMAP *multi = FreeImage_OpenMultiBitmap(FIF_GIF, ofToDataPath(fileName).c_str(), TRUE, FALSE); 
	FIBITMAP * bmp = NULL;
	
	for(int i = 0; i < frames.size(); i++ ) { 
		// we need to swap the channels if we're on little endian (see ofImage::swapRgb);
#ifdef TARGET_LITTLE_ENDIAN
        swapRgb(frames[i]);
#endif
		// get the pixel data
		bmp	= FreeImage_ConvertFromRawBits(
            frames[i]->pixels, 
            frames[i]->width,
            frames[i]->height, 
            frames[i]->width*(frames[i]->bitsPerPixel/8), 
            frames[i]->bitsPerPixel, 
            0, 0, 0, true // in of006 this (topdown) had to be false.
        );	 
        
#ifdef TARGET_LITTLE_ENDIAN
        swapRgb(frames[i]);
#endif
        
        DWORD frameDuration = (DWORD) (frames[i]->duration * 1000.f);

        bmp = FreeImage_ColorQuantizeEx(bmp, FIQ_NNQUANT, nColors);
		
		// dithering :)
        if(ditherMode > OFX_GIF_DITHER_NONE) bmp = FreeImage_Dither(bmp, (FREE_IMAGE_DITHER)ditherMode);
        
		// clear any animation metadata used by this dib as we’ll adding our own ones 
		FreeImage_SetMetadata(FIMD_ANIMATION, bmp, NULL, NULL); 
		// add animation tags to dib[i] 
		FITAG *tag = FreeImage_CreateTag(); 
		
		if(tag) { 
			FreeImage_SetTagKey(tag, "FrameTime"); 
			FreeImage_SetTagType(tag, FIDT_LONG); 
			FreeImage_SetTagCount(tag, 1); 
			FreeImage_SetTagLength(tag, 4); 
			FreeImage_SetTagValue(tag, &frameDuration); 
			FreeImage_SetMetadata(FIMD_ANIMATION, bmp, FreeImage_GetTagKey(tag), tag); 
			FreeImage_DeleteTag(tag); 
		} 
		FreeImage_AppendPage(multi, bmp); 
	} 
	
	FreeImage_Unload(bmp);
	FreeImage_CloseMultiBitmap(multi); 
}
Пример #9
0
/**
	Read JPEG_APP1 marker (XMP profile)
	@param dib Input FIBITMAP
	@param dataptr Pointer to the APP1 marker
	@param datalen APP1 marker length
	@return Returns TRUE if successful, FALSE otherwise
*/
static BOOL  
jpeg_read_xmp_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
	// marker identifying string for XMP (null terminated)
	char *xmp_signature = "http://ns.adobe.com/xap/1.0/";

	size_t length = datalen;
	BYTE *profile = (BYTE*)dataptr;

	// verify the identifying string

	if(memcmp(xmp_signature, profile, strlen(xmp_signature)) == 0) {
		// XMP profile

		size_t offset = strlen(xmp_signature) + 1;
		profile += offset;
		length  -= offset;

		// create a tag
		FITAG *tag = FreeImage_CreateTag();
		if(tag) {
			FreeImage_SetTagID(tag, JPEG_APP0+1);	// 0xFFE1
			FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
			FreeImage_SetTagLength(tag, (DWORD)length);
			FreeImage_SetTagCount(tag, (DWORD)length);
			FreeImage_SetTagType(tag, FIDT_ASCII);
			FreeImage_SetTagValue(tag, profile);
			
			// store the tag
			FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);

			// destroy the tag
			FreeImage_DeleteTag(tag);
		}

		return TRUE;
	}

	return FALSE;
}
Пример #10
0
static BOOL 
FreeImage_SetMetadataEx(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, WORD id, FREE_IMAGE_MDTYPE type, DWORD count, DWORD length, const void *value)
{
	BOOL bResult = FALSE;
	FITAG *tag = FreeImage_CreateTag();
	if(tag) {
		FreeImage_SetTagKey(tag, key);
		FreeImage_SetTagID(tag, id);
		FreeImage_SetTagType(tag, type);
		FreeImage_SetTagCount(tag, count);
		FreeImage_SetTagLength(tag, length);
		FreeImage_SetTagValue(tag, value);
		if(model == FIMD_ANIMATION) {
			TagLib& s = TagLib::instance();
			// get the tag description
			const char *description = s.getTagDescription(TagLib::ANIMATION, id);
			FreeImage_SetTagDescription(tag, description);
		}
		// store the tag
		bResult = FreeImage_SetMetadata(model, dib, key, tag);
		FreeImage_DeleteTag(tag);
	}
	return bResult;
}
Пример #11
0
BOOL DLL_CALLCONV 
FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) {
	if(!dib) 
		return FALSE;

	TAGMAP *tagmap = NULL;

	// get the metadata model
	METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
	METADATAMAP::iterator model_iterator = metadata->find(model);
	if (model_iterator != metadata->end()) {
		tagmap = model_iterator->second;
	}

	if(key != NULL) {

		if(!tagmap) {
			// this model, doesn't exist: create it 
			tagmap = new(std::nothrow) TAGMAP();
			(*metadata)[model] = tagmap;
		}
		
		if(tag) {
			// first check the tag
			if(FreeImage_GetTagKey(tag) == NULL) {
				FreeImage_SetTagKey(tag, key);
			} else if(strcmp(key, FreeImage_GetTagKey(tag)) != 0) {
				// set the tag key
				FreeImage_SetTagKey(tag, key);
			}
			if(FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth(FreeImage_GetTagType(tag)) != FreeImage_GetTagLength(tag)) {
				FreeImage_OutputMessageProc(FIF_UNKNOWN, "Invalid data count for tag '%s'", key);
				return FALSE;
			}

			// fill the tag ID if possible and if it's needed
			TagLib& tag_lib = TagLib::instance();
			switch(model) {
				case FIMD_IPTC:
				{
					int id = tag_lib.getTagID(TagLib::IPTC, key);
					/*
					if(id == -1) {
						FreeImage_OutputMessageProc(FIF_UNKNOWN, "IPTC: Invalid key '%s'", key);
					}
					*/
					FreeImage_SetTagID(tag, (WORD)id);
				}
				break;

				default:
					break;
			}

			// delete existing tag
			FITAG *old_tag = (*tagmap)[key];
			if(old_tag) {
				FreeImage_DeleteTag(old_tag);
			}

			// create a new tag
			(*tagmap)[key] = FreeImage_CloneTag(tag);
		}
		else {
			// delete existing tag
			TAGMAP::iterator i = tagmap->find(key);
			if(i != tagmap->end()) {
				FITAG *old_tag = (*i).second;
				FreeImage_DeleteTag(old_tag);
				tagmap->erase(key);
			}
		}
	}
	else {
		// destroy the metadata model
		if(tagmap) {
			for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
				FITAG *tag = (*i).second;
				FreeImage_DeleteTag(tag);
			}

			delete tagmap;
			metadata->erase(model_iterator);
		}
	}

	return TRUE;
}
Пример #12
0
/**
Read a single exif tag
*/
static BOOL 
tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& tagLib, TIFFDirectory *td, uint32 tag) {
	const TIFFField *fip;
	uint32 value_count;
	int mem_alloc = 0;
	void *raw_data = NULL;

	if(tag == TIFFTAG_EXIFIFD) {
		return TRUE;
	}

	// get the tag key - use NULL to avoid reading GeoTIFF tags
	const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL);
	if(key == NULL) {
		return TRUE;
	}

	fip = TIFFFieldWithTag(tif, tag);
	if(fip == NULL) {
		return TRUE;
	}

	if(fip->field_passcount) { //<- "passcount" means "returns count"
		if (fip->field_readcount != TIFF_VARIABLE2) { //<- TIFF_VARIABLE2 means "uses LONG count"

			// assume TIFF_VARIABLE (uses SHORT count)
			uint16 value_count16;
			if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) {
				return TRUE;
			}
			value_count = value_count16;
		} else {
			if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) {
				return TRUE;
			}
		}
	} else {

		// determine count

		if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) {
			value_count = 1;
		} else if (fip->field_readcount == TIFF_SPP) {
			value_count = td->td_samplesperpixel;
		} else {
			value_count = fip->field_readcount;
		}

		// access fields as pointers to data
		// (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code)

		if(fip->field_tag == TIFFTAG_TRANSFERFUNCTION) {
			// reading this tag cause a bug probably located somewhere inside libtiff
			return TRUE;
		}

		if ((fip->field_type == TIFF_ASCII
		     || fip->field_readcount == TIFF_VARIABLE
		     || fip->field_readcount == TIFF_VARIABLE2
		     || fip->field_readcount == TIFF_SPP
			 || value_count > 1)
			 
			 && fip->field_tag != TIFFTAG_PAGENUMBER
			 && fip->field_tag != TIFFTAG_HALFTONEHINTS
			 && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
			 && fip->field_tag != TIFFTAG_DOTRANGE

			 && fip->field_tag != TIFFTAG_BITSPERSAMPLE	//<- these two are tricky - 
			 && fip->field_tag != TIFFTAG_COMPRESSION	//<- they are defined as TIFF_VARIABLE but in reality return a single value
			 ) {
				 if(TIFFGetField(tif, tag, &raw_data) != 1) {
					 return TRUE;
				 }
		} else {

			// access fields as values

			const int value_size = _TIFFDataSize(fip->field_type);
			raw_data = _TIFFmalloc(value_size * value_count);
			mem_alloc = 1;
			int ok = FALSE;
			
			// ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, 
			// all off which are value_count == 2 (see tif_dirinfo.c)
			switch(value_count)
			{
				case 1:
					ok = TIFFGetField(tif, tag, raw_data);
					break;
				case 2:
					ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1);
					break;
/* # we might need more in the future:
				case 3:
					ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2);
					break;
*/
				default:
					FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", fip->field_name);
					break;
			}
			if(ok != 1) {
				_TIFFfree(raw_data);
				return TRUE;
			}
		}
	}

	// build FreeImage tag from Tiff Tag data we collected

	FITAG *fitag = FreeImage_CreateTag();
	if(!fitag) {
		if(mem_alloc) {
			_TIFFfree(raw_data);
		}
		return FALSE;
	}

	FreeImage_SetTagID(fitag, (WORD)tag);
	FreeImage_SetTagKey(fitag, key);

	switch(fip->field_type) {
		case TIFF_BYTE:
			FreeImage_SetTagType(fitag, FIDT_BYTE);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_UNDEFINED:
			FreeImage_SetTagType(fitag, FIDT_UNDEFINED);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SBYTE:
			FreeImage_SetTagType(fitag, FIDT_SBYTE);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SHORT:
			FreeImage_SetTagType(fitag, FIDT_SHORT);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SSHORT:
			FreeImage_SetTagType(fitag, FIDT_SSHORT);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_LONG:
			FreeImage_SetTagType(fitag, FIDT_LONG);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_IFD:
			FreeImage_SetTagType(fitag, FIDT_IFD);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SLONG:
			FreeImage_SetTagType(fitag, FIDT_SLONG);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_RATIONAL: {
			// LibTIFF converts rational to floats : reconvert floats to rationals
			DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD));
			for(uint32 i = 0; i < value_count; i++) {
				float *fv = (float*)raw_data;
				FIRational rational(fv[i]);
				rvalue[2*i] = rational.getNumerator();
				rvalue[2*i+1] = rational.getDenominator();
			}
			FreeImage_SetTagType(fitag, FIDT_RATIONAL);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, rvalue);
			free(rvalue);
		}
		break;

		case TIFF_SRATIONAL: {
			// LibTIFF converts rational to floats : reconvert floats to rationals
			LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG));
			for(uint32 i = 0; i < value_count; i++) {
				float *fv = (float*)raw_data;
				FIRational rational(fv[i]);
				rvalue[2*i] = rational.getNumerator();
				rvalue[2*i+1] = rational.getDenominator();
			}
			FreeImage_SetTagType(fitag, FIDT_RATIONAL);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, rvalue);
			free(rvalue);
		}
		break;

		case TIFF_FLOAT:
			FreeImage_SetTagType(fitag, FIDT_FLOAT);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_DOUBLE:
			FreeImage_SetTagType(fitag, FIDT_DOUBLE);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_LONG8:	// BigTIFF 64-bit unsigned integer 
			FreeImage_SetTagType(fitag, FIDT_LONG8);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_IFD8:		// BigTIFF 64-bit unsigned integer (offset) 
			FreeImage_SetTagType(fitag, FIDT_IFD8);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SLONG8:		// BigTIFF 64-bit signed integer 
			FreeImage_SetTagType(fitag, FIDT_SLONG8);
			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		default: {
			size_t length = strlen((char*)raw_data) + 1;
			FreeImage_SetTagType(fitag, FIDT_ASCII);
			FreeImage_SetTagLength(fitag, (DWORD)length);
			FreeImage_SetTagCount(fitag, (DWORD)length);
			FreeImage_SetTagValue(fitag, raw_data);
		}
		break;
	}

	const char *description = tagLib.getTagDescription(md_model, (WORD)tag);
	if(description) {
		FreeImage_SetTagDescription(fitag, description);
	}
	// store the tag
	FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag);

	// destroy the tag
	FreeImage_DeleteTag(fitag);

	if(mem_alloc) {
		_TIFFfree(raw_data);
	}
	return TRUE;
}
Пример #13
0
//--------------------------------------------------------------
void ofxGifEncoder::save (vector <ofxGifFrame *> frames, string fileName, int nColors) {
    
    if (nColors < 2 || nColors > 256) {
        ofLog(OF_LOG_WARNING, "nColors must be between 2 and 256. your gif won't be saved");
        return;
    }
    
	// create a multipage bitmap
	FIMULTIBITMAP *multi = FreeImage_OpenMultiBitmap(FIF_GIF, ofToDataPath(fileName).c_str(), TRUE, FALSE); 
	
	FIBITMAP * bmp = NULL;
	
	for(int i = 0; i < frames.size(); i++ ) { 
		// we need to swap the channels if we're on little endian (see ofImage::swapRgb);
#ifdef TARGET_LITTLE_ENDIAN
        swapRgb(frames[i]);
#endif
		
		// get the pixel data
		bmp	= FreeImage_ConvertFromRawBits(
            frames[i]->pixels, 
            frames[i]->width,
            frames[i]->height, 
            frames[i]->width*(frames[i]->bitsPerPixel/8), 
            frames[i]->bitsPerPixel, 
            0,
            0,
            0, 
            true // in of006 this (topdown) had to be false.
        );	 
		
		
#ifdef TARGET_LITTLE_ENDIAN
        swapRgb(frames[i]);
#endif
    		
        DWORD frameDuration = (DWORD) frames[i]->duration * 1000.f;
		
        // bmp =  FreeImage_ColorQuantize(bmp, FIQ_NNQUANT);
		
		// if we want to set a reduced color palette (2 to 256);
        bmp = FreeImage_ColorQuantizeEx(bmp, FIQ_NNQUANT, nColors);
		
		// dithering :)
		// you can set a different dither pattern for each frame
        // bmp = FreeImage_Dither(bmp, (FREE_IMAGE_DITHER)((i+1)%6));
        //bmp = FreeImage_Dither(bmp, FID_BAYER8x8);
        
		// clear any animation metadata used by this dib as we’ll adding our own ones 
		FreeImage_SetMetadata(FIMD_ANIMATION, bmp, NULL, NULL); 
		// add animation tags to dib[i] 
		FITAG *tag = FreeImage_CreateTag(); 
		
		if(tag) { 
			FreeImage_SetTagKey(tag, "FrameTime"); 
			FreeImage_SetTagType(tag, FIDT_LONG); 
			FreeImage_SetTagCount(tag, 1); 
			FreeImage_SetTagLength(tag, 4); 
			FreeImage_SetTagValue(tag, &frameDuration); 
			FreeImage_SetMetadata(FIMD_ANIMATION, bmp, FreeImage_GetTagKey(tag), tag); 
			FreeImage_DeleteTag(tag); 
		} 
		FreeImage_AppendPage(multi, bmp); 
	} 
	
	FreeImage_Unload(bmp);
	FreeImage_CloseMultiBitmap(multi); 
}
Пример #14
0
static BOOL 
ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
	// XMP keyword
	const char *g_png_xmp_keyword = "XML:com.adobe.xmp";

	FITAG *tag = NULL;
	png_textp text_ptr = NULL;
	png_timep mod_time = NULL;
	int num_text = 0;

	// iTXt/tEXt/zTXt chuncks
	if(png_get_text(png_ptr, info_ptr, &text_ptr, &num_text) > 0) {
		for(int i = 0; i < num_text; i++) {
			// create a tag
			tag = FreeImage_CreateTag();
			if(!tag) return FALSE;

			DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length);

			FreeImage_SetTagLength(tag, tag_length);
			FreeImage_SetTagCount(tag, tag_length);
			FreeImage_SetTagType(tag, FIDT_ASCII);
			FreeImage_SetTagValue(tag, text_ptr[i].text);

			if(strcmp(text_ptr[i].key, g_png_xmp_keyword) == 0) {
				// store the tag as XMP
				FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
				FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
			} else {
				// store the tag as a comment
				FreeImage_SetTagKey(tag, text_ptr[i].key);
				FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
			}
			
			// destroy the tag
			FreeImage_DeleteTag(tag);
		}
	}

	// timestamp chunk
	if(png_get_tIME(png_ptr, info_ptr, &mod_time)) {
		char timestamp[32];
		// create a tag
		tag = FreeImage_CreateTag();
		if(!tag) return FALSE;

		// convert as 'yyyy:MM:dd hh:mm:ss'
		sprintf(timestamp, "%4d:%02d:%02d %2d:%02d:%02d", mod_time->year, mod_time->month, mod_time->day, mod_time->hour, mod_time->minute, mod_time->second);

		DWORD tag_length = (DWORD)strlen(timestamp) + 1;
		FreeImage_SetTagLength(tag, tag_length);
		FreeImage_SetTagCount(tag, tag_length);
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagID(tag, TAG_DATETIME);
		FreeImage_SetTagValue(tag, timestamp);

		// store the tag as Exif-TIFF
		FreeImage_SetTagKey(tag, "DateTime");
		FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, FreeImage_GetTagKey(tag), tag);

		// destroy the tag
		FreeImage_DeleteTag(tag);
	}

	return TRUE;
}
Пример #15
0
void
tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
	char defaultKey[16];

	size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);

	TagLib& tag_lib = TagLib::instance();

	for(unsigned i = 0; i < tag_size; i++) {

		const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];

		if(fieldInfo->field_type == TIFF_ASCII) {
			char *params = NULL;

			if(TIFFGetField(tif, fieldInfo->field_tag, &params)) {
				// create a tag
				FITAG *tag = FreeImage_CreateTag();
				if(!tag)
					return;

				WORD tag_id = (WORD)fieldInfo->field_tag;

				FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)fieldInfo->field_type);
				FreeImage_SetTagID(tag, tag_id);
				FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
				FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
				FreeImage_SetTagLength(tag, (DWORD)strlen(params) + 1);
				FreeImage_SetTagCount(tag, FreeImage_GetTagLength(tag));
				FreeImage_SetTagValue(tag, params);
				FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);

				// delete the tag
				FreeImage_DeleteTag(tag);
			}
		} else {
			short tag_count = 0;
			void* data = NULL;

			if(TIFFGetField(tif, fieldInfo->field_tag, &tag_count, &data)) {
				// create a tag
				FITAG *tag = FreeImage_CreateTag();
				if(!tag)
					return;

				WORD tag_id = (WORD)fieldInfo->field_tag;
				FREE_IMAGE_MDTYPE tag_type = (FREE_IMAGE_MDTYPE)fieldInfo->field_type;

				FreeImage_SetTagType(tag, tag_type);
				FreeImage_SetTagID(tag, tag_id);
				FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
				FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
				FreeImage_SetTagLength(tag, FreeImage_TagDataWidth(tag_type) * tag_count);
				FreeImage_SetTagCount(tag, tag_count);
				FreeImage_SetTagValue(tag, data);
				FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);

				// delete the tag
				FreeImage_DeleteTag(tag);
			}
		}
	} // for(tag_size)
}
Пример #16
0
/**
Process a Canon maker note tag. 
A single Canon tag may contain many other tags within.
*/
static BOOL 
processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) {
	char defaultKey[16];
	DWORD startIndex = 0;
	TagLib& s = TagLib::instance();

	WORD tag_id = FreeImage_GetTagID(tag);

	int subTagTypeBase = 0;

	switch(tag_id) {
		case TAG_CANON_CAMERA_STATE_0x01:
			subTagTypeBase = 0xC100;
			startIndex = 1;
			break;
		case TAG_CANON_CAMERA_STATE_0x02:
			subTagTypeBase = 0xC200;
			startIndex = 0;
			break;
		case TAG_CANON_CAMERA_STATE_0x04:
			subTagTypeBase = 0xC400;
			startIndex = 1;
			break;
		case TAG_CANON_CAMERA_STATE_0x12:
			subTagTypeBase = 0xC120;
			startIndex = 0;
			break;
		case TAG_CANON_CAMERA_STATE_0xA0:
			subTagTypeBase = 0xCA00;
			startIndex = 1;
			break;
		case TAG_CANON_CAMERA_STATE_0xE0:
			subTagTypeBase = 0xCE00;
			startIndex = 1;
			break;

		default:
		{
			// process as a normal tag

			// get the tag key and description
			const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
			FreeImage_SetTagKey(tag, key);
			const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
			FreeImage_SetTagDescription(tag, description);

			// store the tag
			if(key) {
				FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, tag);
			}

			return TRUE;
		}
		break;

	}

	WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag);

	// create a tag
	FITAG *canonTag = FreeImage_CreateTag();
	if(!canonTag) return FALSE;

	// we intentionally skip the first array member (if needed)
    for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) {

		tag_id = (WORD)(subTagTypeBase + i);

		FreeImage_SetTagID(canonTag, tag_id);
		FreeImage_SetTagType(canonTag, FIDT_SHORT);
		FreeImage_SetTagCount(canonTag, 1);
		FreeImage_SetTagLength(canonTag, 2);
		FreeImage_SetTagValue(canonTag, &pvalue[i]);

		// get the tag key and description
		const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
		FreeImage_SetTagKey(canonTag, key);
		const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
		FreeImage_SetTagDescription(canonTag, description);

		// store the tag
		if(key) {
			FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, canonTag);
		}
	}

	// delete the tag
	FreeImage_DeleteTag(canonTag);

	return TRUE;
}
Пример #17
0
/**
Process a standard Exif tag
*/
static void 
processExifTag(FIBITMAP *dib, FITAG *tag, char *pval, BOOL msb_order, TagLib::MDMODEL md_model) {
	char defaultKey[16];
	int n;
	DWORD i;

	// allocate a buffer to store the tag value
	BYTE *exif_value = (BYTE*)malloc(FreeImage_GetTagLength(tag) * sizeof(BYTE));
	memset(exif_value, 0, FreeImage_GetTagLength(tag) * sizeof(BYTE));

	// get the tag value
	switch(FreeImage_GetTagType(tag)) {

		case FIDT_SHORT:
		{
			WORD *value = (WORD*)&exif_value[0];
			for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
				value[i] = ReadUint16(msb_order, pval + i * sizeof(WORD));
			}
			FreeImage_SetTagValue(tag, value);
			break;
		}
		case FIDT_SSHORT:
		{
			short *value = (short*)&exif_value[0];
			for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
				value[i] = ReadInt16(msb_order, pval + i * sizeof(short));
			}
			FreeImage_SetTagValue(tag, value);
			break;
		}
		case FIDT_LONG:
		{
			DWORD *value = (DWORD*)&exif_value[0];
			for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
				value[i] = ReadUint32(msb_order, pval + i * sizeof(DWORD));
			}
			FreeImage_SetTagValue(tag, value);
			break;
		}
		case FIDT_SLONG:
		{
			LONG *value = (LONG*)&exif_value[0];
			for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
				value[i] = ReadInt32(msb_order, pval + i * sizeof(LONG));
			}
			FreeImage_SetTagValue(tag, value);
			break;
		}
		case FIDT_RATIONAL:
		{
			n = sizeof(DWORD);

			DWORD *value = (DWORD*)&exif_value[0];						
			for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
				// read a sequence of (numerator, denominator)
				value[i] = ReadUint32(msb_order, n*i + (char*)pval);
			}
			FreeImage_SetTagValue(tag, value);
			break;
		}
		case FIDT_SRATIONAL:
		{
			n = sizeof(LONG);

			LONG *value = (LONG*)&exif_value[0];
			for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
				// read a sequence of (numerator, denominator)
				value[i] = ReadInt32(msb_order, n*i + (char*)pval);
			}
			FreeImage_SetTagValue(tag, value);
			break;
		}
		case FIDT_BYTE:
		case FIDT_ASCII:
		case FIDT_SBYTE:
		case FIDT_UNDEFINED:
		case FIDT_FLOAT:
		case FIDT_DOUBLE:
		default:
			FreeImage_SetTagValue(tag, pval);
			break;
	}

	if(md_model == TagLib::EXIF_MAKERNOTE_CANON) {
		// A single Canon tag can have multiple values within
		processCanonMakerNoteTag(dib, tag);
	}
	else {
		TagLib& s = TagLib::instance();

		WORD tag_id = FreeImage_GetTagID(tag);

		// get the tag key and description
		const char *key = s.getTagFieldName(md_model, tag_id, defaultKey);
		FreeImage_SetTagKey(tag, key);
		const char *description = s.getTagDescription(md_model, tag_id);
		FreeImage_SetTagDescription(tag, description);

		// store the tag
		if(key) {
			FreeImage_SetMetadata(s.getFreeImageModel(md_model), dib, key, tag);
		}
	}
	

	// free the temporary buffer
	free(exif_value);

}
Пример #18
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	WebPMux *mux = NULL;
	WebPMuxFrameInfo webp_frame = { 0 };	// raw image
	WebPData color_profile;	// ICC raw data
	WebPData xmp_metadata;	// XMP raw data
	WebPData exif_metadata;	// EXIF raw data
	FIBITMAP *dib = NULL;
	WebPMuxError error_status;

	if(!handle) {
		return NULL;
	}

	try {
		// get the MUX object
		mux = (WebPMux*)data;
		if(!mux) {
			throw (1);
		}
		
		// gets the feature flags from the mux object
		uint32_t webp_flags = 0;
		error_status = WebPMuxGetFeatures(mux, &webp_flags);
		if(error_status != WEBP_MUX_OK) {
			throw (1);
		}

		// get image data
		error_status = WebPMuxGetFrame(mux, 1, &webp_frame);

		if(error_status == WEBP_MUX_OK) {
			// decode the data (can be limited to the header if flags uses FIF_LOAD_NOPIXELS)
			dib = DecodeImage(&webp_frame.bitstream, flags);
			if(!dib) {
				throw (1);
			}
			
			// get ICC profile
			if(webp_flags & ICCP_FLAG) {
				error_status = WebPMuxGetChunk(mux, "ICCP", &color_profile);
				if(error_status == WEBP_MUX_OK) {
					FreeImage_CreateICCProfile(dib, (void*)color_profile.bytes, (long)color_profile.size);
				}
			}

			// get XMP metadata
			if(webp_flags & XMP_FLAG) {
				error_status = WebPMuxGetChunk(mux, "XMP ", &xmp_metadata);
				if(error_status == WEBP_MUX_OK) {
					// create a tag
					FITAG *tag = FreeImage_CreateTag();
					if(tag) {
						FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
						FreeImage_SetTagLength(tag, (DWORD)xmp_metadata.size);
						FreeImage_SetTagCount(tag, (DWORD)xmp_metadata.size);
						FreeImage_SetTagType(tag, FIDT_ASCII);
						FreeImage_SetTagValue(tag, xmp_metadata.bytes);
						
						// store the tag
						FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);

						// destroy the tag
						FreeImage_DeleteTag(tag);
					}
				}
			}

			// get Exif metadata
			if(webp_flags & EXIF_FLAG) {
				error_status = WebPMuxGetChunk(mux, "EXIF", &exif_metadata);
				if(error_status == WEBP_MUX_OK) {
					// read the Exif raw data as a blob
					jpeg_read_exif_profile_raw(dib, exif_metadata.bytes, (unsigned)exif_metadata.size);
					// read and decode the Exif data
					jpeg_read_exif_profile(dib, exif_metadata.bytes, (unsigned)exif_metadata.size);
				}
			}
		}

		WebPDataClear(&webp_frame.bitstream);

		return dib;

	} catch(int) {
		WebPDataClear(&webp_frame.bitstream);
		return NULL;
	}
}
Пример #19
0
/**
Read a single Exif tag

@param tif TIFF handle
@param tag_id TIFF Tag ID
@param dib Image being read
@param md_model Metadata model where to store the tag
@return Returns TRUE if successful, returns FALSE otherwise
*/
static BOOL 
tiff_read_exif_tag(TIFF *tif, uint32 tag_id, FIBITMAP *dib, TagLib::MDMODEL md_model) {
	uint32 value_count = 0;
	int mem_alloc = 0;
	void *raw_data = NULL;

	if(tag_id == TIFFTAG_EXIFIFD) {
		// Exif IFD offset - skip this tag
		// md_model should be EXIF_MAIN, the Exif IFD is processed later using the EXIF_EXIF metadata model
		return TRUE;
	}
	if((tag_id == TIFFTAG_GPSIFD) && (md_model == TagLib::EXIF_MAIN)) {
		// Exif GPS IFD offset - skip this tag
		// should be processed in another way ...
		return TRUE;
	}
	
	TagLib& tagLib = TagLib::instance();

	// get the tag key - use NULL to avoid reading GeoTIFF tags
	const char *key = tagLib.getTagFieldName(md_model, (WORD)tag_id, NULL);
	if(key == NULL) {
		return TRUE;
	}

	const TIFFField *fip = TIFFFieldWithTag(tif, tag_id);
	if(fip == NULL) {
		return TRUE;
	}

	if(TIFFFieldPassCount(fip)) { 
		// a count value is required for 'TIFFGetField'

		if (TIFFFieldReadCount(fip) != TIFF_VARIABLE2) {
			// a count is required, it will be of type uint16
			uint16 value_count16 = 0;
			if(TIFFGetField(tif, tag_id, &value_count16, &raw_data) != 1) {
				// stop, ignore error
				return TRUE;
			}
			value_count = value_count16;
		} else {
			// a count is required, it will be of type uint32
			uint32 value_count32 = 0;
			if(TIFFGetField(tif, tag_id, &value_count32, &raw_data) != 1) {
				// stop, ignore error
				return TRUE;
			}
			value_count = value_count32;
		}

	} else {
		// determine count

		if (TIFFFieldReadCount(fip) == TIFF_VARIABLE || TIFFFieldReadCount(fip) == TIFF_VARIABLE2) {
			value_count = 1;
		} else if (TIFFFieldReadCount(fip) == TIFF_SPP) {
			uint16 spp;
			TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
			value_count = spp;
		} else {
			value_count = TIFFFieldReadCount(fip);
		}

		// access fields as pointers to data
		// (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code)

		if(TIFFFieldTag(fip) == TIFFTAG_TRANSFERFUNCTION) {
			// reading this tag cause a bug probably located somewhere inside libtiff
			return TRUE;
		}

		if ((TIFFFieldDataType(fip) == TIFF_ASCII
		     || TIFFFieldReadCount(fip) == TIFF_VARIABLE
		     || TIFFFieldReadCount(fip) == TIFF_VARIABLE2
		     || TIFFFieldReadCount(fip) == TIFF_SPP
			 || value_count > 1)
			 
			 && TIFFFieldTag(fip) != TIFFTAG_PAGENUMBER
			 && TIFFFieldTag(fip) != TIFFTAG_HALFTONEHINTS
			 && TIFFFieldTag(fip) != TIFFTAG_YCBCRSUBSAMPLING
			 && TIFFFieldTag(fip) != TIFFTAG_DOTRANGE

			 && TIFFFieldTag(fip) != TIFFTAG_BITSPERSAMPLE	//<- these two are tricky - 
			 && TIFFFieldTag(fip) != TIFFTAG_COMPRESSION	//<- they are defined as TIFF_VARIABLE but in reality return a single value
			 ) {
				 if(TIFFGetField(tif, tag_id, &raw_data) != 1) {
					 // stop, ignore error
					 return TRUE;
				 }
		} else {
			int value_size = 0;

			// access fields as values

			// Note: 
			// For TIFF_RATIONAL values, TIFFDataWidth() returns 8, but LibTIFF use internaly 4-byte float to represent rationals.
			{
				TIFFDataType tag_type = TIFFFieldDataType(fip);
				switch(tag_type) {
					case TIFF_RATIONAL:
					case TIFF_SRATIONAL:
						value_size = 4;
						break;
					default:
						value_size = TIFFDataWidth(tag_type);
						break;
				}
			}

			raw_data = _TIFFmalloc(value_size * value_count);
			mem_alloc = 1;
			int ok = FALSE;
			
			// ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, 
			// all off which are value_count == 2 (see tif_dirinfo.c)
			switch(value_count)
			{
				case 1:
					ok = TIFFGetField(tif, tag_id, raw_data);
					break;
				case 2:
					ok = TIFFGetField(tif, tag_id, raw_data, (BYTE*)(raw_data) + value_size*1);
					break;
/* # we might need more in the future:
				case 3:
					ok = TIFFGetField(tif, tag_id, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2);
					break;
*/
				default:
					FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", TIFFFieldName(fip));
					break;
			}
			if(ok != 1) {
				_TIFFfree(raw_data);
				return TRUE;
			}
		}
	}

	// build FreeImage tag from Tiff Tag data we collected

	FITAG *fitag = FreeImage_CreateTag();
	if(!fitag) {
		if(mem_alloc) {
			_TIFFfree(raw_data);
		}
		return FALSE;
	}

	FreeImage_SetTagID(fitag, (WORD)tag_id);
	FreeImage_SetTagKey(fitag, key);

	switch(TIFFFieldDataType(fip)) {
		case TIFF_BYTE:
			FreeImage_SetTagType(fitag, FIDT_BYTE);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_UNDEFINED:
			FreeImage_SetTagType(fitag, FIDT_UNDEFINED);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SBYTE:
			FreeImage_SetTagType(fitag, FIDT_SBYTE);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SHORT:
			FreeImage_SetTagType(fitag, FIDT_SHORT);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SSHORT:
			FreeImage_SetTagType(fitag, FIDT_SSHORT);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_LONG:
			FreeImage_SetTagType(fitag, FIDT_LONG);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_IFD:
			FreeImage_SetTagType(fitag, FIDT_IFD);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SLONG:
			FreeImage_SetTagType(fitag, FIDT_SLONG);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_RATIONAL: {
			// LibTIFF converts rational to floats : reconvert floats to rationals
			DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD));
			for(uint32 i = 0; i < value_count; i++) {
				float *fv = (float*)raw_data;
				FIRational rational(fv[i]);
				rvalue[2*i] = rational.getNumerator();
				rvalue[2*i+1] = rational.getDenominator();
			}
			FreeImage_SetTagType(fitag, FIDT_RATIONAL);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, rvalue);
			free(rvalue);
		}
		break;

		case TIFF_SRATIONAL: {
			// LibTIFF converts rational to floats : reconvert floats to rationals
			LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG));
			for(uint32 i = 0; i < value_count; i++) {
				float *fv = (float*)raw_data;
				FIRational rational(fv[i]);
				rvalue[2*i] = rational.getNumerator();
				rvalue[2*i+1] = rational.getDenominator();
			}
			FreeImage_SetTagType(fitag, FIDT_RATIONAL);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, rvalue);
			free(rvalue);
		}
		break;

		case TIFF_FLOAT:
			FreeImage_SetTagType(fitag, FIDT_FLOAT);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_DOUBLE:
			FreeImage_SetTagType(fitag, FIDT_DOUBLE);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_LONG8:	// BigTIFF 64-bit unsigned integer 
			FreeImage_SetTagType(fitag, FIDT_LONG8);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_IFD8:		// BigTIFF 64-bit unsigned integer (offset) 
			FreeImage_SetTagType(fitag, FIDT_IFD8);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_SLONG8:		// BigTIFF 64-bit signed integer 
			FreeImage_SetTagType(fitag, FIDT_SLONG8);
			FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
			FreeImage_SetTagCount(fitag, value_count);
			FreeImage_SetTagValue(fitag, raw_data);
			break;

		case TIFF_ASCII:
		default: {
			size_t length = 0;
			if(!mem_alloc && (TIFFFieldDataType(fip) == TIFF_ASCII) && (TIFFFieldReadCount(fip) == TIFF_VARIABLE)) {
				// when metadata tag is of type ASCII and it's value is of variable size (TIFF_VARIABLE),
				// tiff_read_exif_tag function gives length of 1 so all strings are truncated ...
				// ... try to avoid this by using an explicit calculation for 'length'
				length = strlen((char*)raw_data) + 1;
			}
			else {
				// remember that raw_data = _TIFFmalloc(value_size * value_count);
				const int value_size = TIFFDataWidth( TIFFFieldDataType(fip) );
				length = value_size * value_count;
			}
			FreeImage_SetTagType(fitag, FIDT_ASCII);
			FreeImage_SetTagLength(fitag, (DWORD)length);
			FreeImage_SetTagCount(fitag, (DWORD)length);
			FreeImage_SetTagValue(fitag, raw_data);
		}
		break;
	}

	const char *description = tagLib.getTagDescription(md_model, (WORD)tag_id);
	if(description) {
		FreeImage_SetTagDescription(fitag, description);
	}
	// store the tag
	FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag);

	// destroy the tag
	FreeImage_DeleteTag(fitag);

	if(mem_alloc) {
		_TIFFfree(raw_data);
	}
	return TRUE;
}
Пример #20
0
void ofxGifEncoder::processFrame(ofxGifFrame * frame, FIMULTIBITMAP *multi){
    FIBITMAP * bmp = NULL;
    // we need to swap the channels if we're on little endian (see ofImage::swapRgb);

    
    if (frame->bitsPerPixel ==32){
        ofLog() << "image is transaprent!";
        frame = convertTo24BitsWithGreenScreen(frame);
    }
    
#ifdef TARGET_LITTLE_ENDIAN
    swapRgb(frame);
#endif
    
    
    // from here on, we can only deal with 24 bits
    
    // get the pixel data
    bmp	= FreeImage_ConvertFromRawBits(
                                       frame->pixels,
                                       frame->width,
                                       frame->height,
                                       frame->width*(frame->bitsPerPixel/8),
                                       frame->bitsPerPixel,
                                       0, 0, 0, true // in of006 this (topdown) had to be false.
                                       );
    
    FIBITMAP * bmpConverted;
    
#ifdef TARGET_LITTLE_ENDIAN
    swapRgb(frame);
#endif
    
    FIBITMAP * quantizedBmp = NULL;
    FIBITMAP * ditheredBmp  = NULL;
    FIBITMAP * processedBmp = NULL;
    
    
    quantizedBmp = FreeImage_ColorQuantizeEx(bmp, FIQ_WUQUANT, nColors);
    processedBmp = quantizedBmp;
    
    if (nChannels == 4){
        calculatePalette(processedBmp);
        FreeImage_SetTransparentIndex(processedBmp,getClosestToGreenScreenPaletteColorIndex());
    }


    
    // dithering :)
    if(ditherMode > OFX_GIF_DITHER_NONE) {
        ditheredBmp = FreeImage_Dither(processedBmp, (FREE_IMAGE_DITHER)ditherMode);
        processedBmp = ditheredBmp;
    }
    
    DWORD frameDuration = (DWORD) (frame->duration * 1000.f);
    
    // clear any animation metadata used by this dib as we’ll adding our own ones
    FreeImage_SetMetadata(FIMD_ANIMATION, processedBmp, NULL, NULL);
    // add animation tags to dib[frameNum]
    FITAG *tag = FreeImage_CreateTag();
    if(tag) {
        FreeImage_SetTagKey(tag, "FrameTime");
        FreeImage_SetTagType(tag, FIDT_LONG);
        FreeImage_SetTagCount(tag, 1);
        FreeImage_SetTagLength(tag, 4);
        FreeImage_SetTagValue(tag, &frameDuration);
        FreeImage_SetMetadata(FIMD_ANIMATION, processedBmp, FreeImage_GetTagKey(tag), tag);
        FreeImage_DeleteTag(tag);
    }
    
    FreeImage_AppendPage(multi, processedBmp);
    
    // clear freeimage stuff
    if(bmp          != NULL) FreeImage_Unload(bmp);
    if(quantizedBmp != NULL) FreeImage_Unload(quantizedBmp);
    if(ditheredBmp  != NULL) FreeImage_Unload(ditheredBmp);
    
    // no need to unload processedBmp, as it points to either of the above

}
Пример #21
0
/**
Process a Canon maker note tag. 
A single Canon tag may contain many other tags within.
*/
static void 
processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) {
	char defaultKey[16];
	DWORD startIndex = 0;
	TagLib& s = TagLib::instance();

	WORD tag_id = FreeImage_GetTagID(tag);

	if((tag_id == TAG_CANON_CAMERA_STATE_1) || (tag_id == TAG_CANON_CAMERA_STATE_2) || (tag_id == TAG_CANON_CAMERA_STATE_4)) {
		// this single tag has multiple values within

		int subTagTypeBase = 0;

		switch(tag_id) {
			case TAG_CANON_CAMERA_STATE_1:
				subTagTypeBase = 0xC100;
				startIndex = 1;
				break;
			case TAG_CANON_CAMERA_STATE_2:
				subTagTypeBase = 0xC200;
				startIndex = 0;
				break;
			case TAG_CANON_CAMERA_STATE_4:
				subTagTypeBase = 0xC400;
				startIndex = 2;
				break;
		}

		WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag);

        // we intentionally skip the first array member
        for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) {
			// create a tag
			FITAG *canonTag = FreeImage_CreateTag();
			if(!canonTag) return;

			tag_id = (WORD)(subTagTypeBase + i);

			FreeImage_SetTagID(canonTag, tag_id);
			FreeImage_SetTagType(canonTag, FIDT_SHORT);
			FreeImage_SetTagCount(canonTag, 1);
			FreeImage_SetTagLength(canonTag, 2);
			FreeImage_SetTagValue(canonTag, &pvalue[i]);

			// get the tag key and description
			const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
			FreeImage_SetTagKey(canonTag, key);
			const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
			FreeImage_SetTagDescription(canonTag, description);

			// store the tag
			if(key) {
				FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, canonTag);
			}

			// delete the tag
			FreeImage_DeleteTag(canonTag);
        }
	}
	else {
		// process as a normal tag

		// get the tag key and description
		const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
		FreeImage_SetTagKey(tag, key);
		const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
		FreeImage_SetTagDescription(tag, description);

		// store the tag
		if(key) {
			FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, tag);
		}
	}
}
Пример #22
0
BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
    int  i;
    short count;

	TagLib& tagLib = TagLib::instance();

	TIFFDirectory *td = &tif->tif_dir;
    
	count = (short) TIFFGetTagListCount(tif);
    for(i = 0; i < count; i++) {
        ttag_t tag = TIFFGetTagListEntry(tif, i);
        const TIFFFieldInfo *fip;
        uint32 value_count;
        int mem_alloc = 0;
        void *raw_data;

		if(tag == TIFFTAG_EXIFIFD) continue;

		// get the tag key - use NULL to avoid reading GeoTIFF tags
		const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL);
		if(key == NULL) continue;
        
		fip = TIFFFieldWithTag(tif, tag);
        if(fip == NULL) continue;
		
		if(fip->field_passcount) {
			if (fip->field_readcount != TIFF_VARIABLE2) {
				// assume TIFF_VARIABLE
				uint16 value_count16;
				if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) continue;
				value_count = value_count16;
			} else {
				if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) continue;
			}
		} else {
			if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) {
				value_count = 1;
			} else if (fip->field_readcount == TIFF_SPP) {
				value_count = td->td_samplesperpixel;
			} else {
				value_count = fip->field_readcount;
			}
			if (fip->field_type == TIFF_ASCII 
				|| fip->field_readcount == TIFF_VARIABLE
				|| fip->field_readcount == TIFF_VARIABLE2
				|| fip->field_readcount == TIFF_SPP
				|| value_count > 1) {
				if(TIFFGetField(tif, tag, &raw_data) != 1) continue;
			} else {
				raw_data = _TIFFmalloc(_TIFFDataSize(fip->field_type) * value_count);
				mem_alloc = 1;
				if(TIFFGetField(tif, tag, raw_data) != 1) {
					_TIFFfree(raw_data);
					continue;
				}
			}
		}
		
		// create a tag
		FITAG *fitag = FreeImage_CreateTag();
		if(!fitag) {
			if(mem_alloc)
				_TIFFfree(raw_data);
			return FALSE;
		}

		FreeImage_SetTagID(fitag, (WORD)tag);
		FreeImage_SetTagKey(fitag, key);

		switch(fip->field_type) {
			case TIFF_BYTE:
				FreeImage_SetTagType(fitag, FIDT_BYTE);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_UNDEFINED:
				FreeImage_SetTagType(fitag, FIDT_UNDEFINED);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_SBYTE:
				FreeImage_SetTagType(fitag, FIDT_SBYTE);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_SHORT:
				FreeImage_SetTagType(fitag, FIDT_SHORT);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_SSHORT:
				FreeImage_SetTagType(fitag, FIDT_SSHORT);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_LONG:
				FreeImage_SetTagType(fitag, FIDT_LONG);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_IFD:
				FreeImage_SetTagType(fitag, FIDT_IFD);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_SLONG:
				FreeImage_SetTagType(fitag, FIDT_SLONG);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_RATIONAL:
			{
				// LibTIFF converts rational to floats : reconvert floats to rationals
				DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD));
				for(uint32 i = 0; i < value_count; i++) {
					float *fv = (float*)raw_data;
					FIRational rational(fv[i]);
					rvalue[2*i] = rational.getNumerator();
					rvalue[2*i+1] = rational.getDenominator();
				}
				FreeImage_SetTagType(fitag, FIDT_RATIONAL);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, rvalue);
				free(rvalue);
			}
			break;

			case TIFF_SRATIONAL:
			{
				// LibTIFF converts rational to floats : reconvert floats to rationals
				LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG));
				for(uint32 i = 0; i < value_count; i++) {
					float *fv = (float*)raw_data;
					FIRational rational(fv[i]);
					rvalue[2*i] = rational.getNumerator();
					rvalue[2*i+1] = rational.getDenominator();
				}
				FreeImage_SetTagType(fitag, FIDT_RATIONAL);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, rvalue);
				free(rvalue);
			}
			break;

			case TIFF_FLOAT:
				FreeImage_SetTagType(fitag, FIDT_FLOAT);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			case TIFF_DOUBLE:
				FreeImage_SetTagType(fitag, FIDT_DOUBLE);
				FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
				FreeImage_SetTagCount(fitag, value_count);
				FreeImage_SetTagValue(fitag, raw_data);
				break;

			default:
			{
				size_t length = strlen((char*)raw_data) + 1;
				FreeImage_SetTagType(fitag, FIDT_ASCII);
				FreeImage_SetTagLength(fitag, (DWORD)length);
				FreeImage_SetTagCount(fitag, (DWORD)length);
				FreeImage_SetTagValue(fitag, raw_data);
			}
			break;
		}

		const char *description = tagLib.getTagDescription(md_model, (WORD)tag);
		if(description) {
			FreeImage_SetTagDescription(fitag, description);
		}
		// store the tag
		FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag);

		// destroy the tag
		FreeImage_DeleteTag(fitag);
	
		if(mem_alloc)
			_TIFFfree(raw_data);
    }

	return TRUE;

}
Пример #23
0
/**
	Read and decode IPTC binary data
*/
BOOL 
read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
	char defaultKey[16];
	size_t length = datalen;
	BYTE *profile = (BYTE*)dataptr;

	std::string Keywords;
	std::string SupplementalCategory;

	WORD tag_id;

	// create a tag

	FITAG *tag = FreeImage_CreateTag();

	TagLib& tag_lib = TagLib::instance();

    // find start of the BIM portion of the binary data
    size_t offset = 0;
	while(offset < length - 1) {
		if((profile[offset] == 0x1C) && (profile[offset+1] == 0x02))
			break;
		offset++;
	}

    // for each tag
    while (offset < length) {

        // identifies start of a tag
        if (profile[offset] != 0x1c) {
            break;
        }
        // we need at least five bytes left to read a tag
        if ((offset + 5) >= length) {
            break;
        }

        offset++;

		int directoryType	= profile[offset++];
        int tagType			= profile[offset++];;
        int tagByteCount	= ((profile[offset] & 0xFF) << 8) | (profile[offset + 1] & 0xFF);
        offset += 2;

        if ((offset + tagByteCount) > length) {
            // data for tag extends beyond end of iptc segment
            break;
        }

		// process the tag

		tag_id = (WORD)(tagType | (directoryType << 8));

		FreeImage_SetTagID(tag, tag_id);
		FreeImage_SetTagLength(tag, tagByteCount);

		// allocate a buffer to store the tag value
		BYTE *iptc_value = (BYTE*)malloc((tagByteCount + 1) * sizeof(BYTE));
		memset(iptc_value, 0, (tagByteCount + 1) * sizeof(BYTE));

		// get the tag value

		switch (tag_id) {
			case TAG_RECORD_VERSION:
			{
				// short
				FreeImage_SetTagType(tag, FIDT_SSHORT);
				FreeImage_SetTagCount(tag, 1);
				short *pvalue = (short*)&iptc_value[0];
				*pvalue = (short)((profile[offset] << 8) | profile[offset + 1]);
				FreeImage_SetTagValue(tag, pvalue);
				break;
			}

			case TAG_RELEASE_DATE:
			case TAG_DATE_CREATED:
				// Date object
			case TAG_RELEASE_TIME:
			case TAG_TIME_CREATED:
				// time
			default:
			{
				// string
				FreeImage_SetTagType(tag, FIDT_ASCII);
				FreeImage_SetTagCount(tag, tagByteCount);
				for(int i = 0; i < tagByteCount; i++) {
					iptc_value[i] = profile[offset + i];
				}
				iptc_value[tagByteCount] = '\0';
				FreeImage_SetTagValue(tag, (char*)&iptc_value[0]);
				break;
			}
		}

		if(tag_id == TAG_SUPPLEMENTAL_CATEGORIES) {
			// concatenate the categories
			if(SupplementalCategory.length() == 0) {
				SupplementalCategory.append((char*)iptc_value);
			} else {
				SupplementalCategory.append(IPTC_DELIMITER);
				SupplementalCategory.append((char*)iptc_value);
			}
		}
		else if(tag_id == TAG_KEYWORDS) {
			// concatenate the keywords
			if(Keywords.length() == 0) {
				Keywords.append((char*)iptc_value);
			} else {
				Keywords.append(IPTC_DELIMITER);
				Keywords.append((char*)iptc_value);
			}
		}
		else {
			// get the tag key and description
			const char *key = tag_lib.getTagFieldName(TagLib::IPTC, tag_id, defaultKey);
			FreeImage_SetTagKey(tag, key);
			const char *description = tag_lib.getTagDescription(TagLib::IPTC, tag_id);
			FreeImage_SetTagDescription(tag, description);

			// store the tag
			if(key) {
				FreeImage_SetMetadata(FIMD_IPTC, dib, key, tag);
			}
		}

		free(iptc_value);

        // next tag
		offset += tagByteCount;

    }

	// store the 'keywords' tag
	if(Keywords.length()) {
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagID(tag, TAG_KEYWORDS);
		FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_KEYWORDS, defaultKey));
		FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_KEYWORDS));
		FreeImage_SetTagLength(tag, (DWORD)Keywords.length());
		FreeImage_SetTagCount(tag, (DWORD)Keywords.length());
		FreeImage_SetTagValue(tag, (char*)Keywords.c_str());
		FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
	}

	// store the 'supplemental category' tag
	if(SupplementalCategory.length()) {
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagID(tag, TAG_SUPPLEMENTAL_CATEGORIES);
		FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES, defaultKey));
		FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES));
		FreeImage_SetTagLength(tag, (DWORD)SupplementalCategory.length());
		FreeImage_SetTagCount(tag, (DWORD)SupplementalCategory.length());
		FreeImage_SetTagValue(tag, (char*)SupplementalCategory.c_str());
		FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
	}

	// delete the tag

	FreeImage_DeleteTag(tag);

	return TRUE;
}
Пример #24
0
/**
Read ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata
@see ReadProfile, ReadDescriptiveMetadata
*/
static ERR
ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) {
	ERR error_code = 0;		// error code as returned by the interface
	size_t currentPos = 0;	// current stream position
	
	WMPStream *pStream = pID->pStream;
	WmpDEMisc *wmiDEMisc = &pID->WMP.wmiDEMisc;
	BYTE *pbProfile = NULL;

	try {
		// save current position
		error_code = pStream->GetPos(pStream, &currentPos);
		JXR_CHECK(error_code);

		// ICC profile
		if(0 != wmiDEMisc->uColorProfileByteCount) {
			unsigned cbByteCount = wmiDEMisc->uColorProfileByteCount;
			unsigned uOffset = wmiDEMisc->uColorProfileOffset;
			error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
			JXR_CHECK(error_code);
			FreeImage_CreateICCProfile(dib, pbProfile, cbByteCount);
		}

		// XMP metadata
		if(0 != wmiDEMisc->uXMPMetadataByteCount) {
			unsigned cbByteCount = wmiDEMisc->uXMPMetadataByteCount;
			unsigned uOffset = wmiDEMisc->uXMPMetadataOffset;
			error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
			JXR_CHECK(error_code);
			// store the tag as XMP
			FITAG *tag = FreeImage_CreateTag();
			if(tag) {
				FreeImage_SetTagLength(tag, cbByteCount);
				FreeImage_SetTagCount(tag, cbByteCount);
				FreeImage_SetTagType(tag, FIDT_ASCII);
				FreeImage_SetTagValue(tag, pbProfile);
				FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
				FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
				FreeImage_DeleteTag(tag);
			}
		}

		// IPTC metadata
		if(0 != wmiDEMisc->uIPTCNAAMetadataByteCount) {
			unsigned cbByteCount = wmiDEMisc->uIPTCNAAMetadataByteCount;
			unsigned uOffset = wmiDEMisc->uIPTCNAAMetadataOffset;
			error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
			JXR_CHECK(error_code);
			// decode the IPTC profile
			read_iptc_profile(dib, pbProfile, cbByteCount);
		}

		// Exif metadata
		if(0 != wmiDEMisc->uEXIFMetadataByteCount) {
			unsigned cbByteCount = wmiDEMisc->uEXIFMetadataByteCount;
			unsigned uOffset = wmiDEMisc->uEXIFMetadataOffset;
			error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
			JXR_CHECK(error_code);
			// decode the Exif profile
			jpegxr_read_exif_profile(dib, pbProfile, cbByteCount, uOffset);
		}

		// Exif-GPS metadata
		if(0 != wmiDEMisc->uGPSInfoMetadataByteCount) {
			unsigned cbByteCount = wmiDEMisc->uGPSInfoMetadataByteCount;
			unsigned uOffset = wmiDEMisc->uGPSInfoMetadataOffset;
			error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile);
			JXR_CHECK(error_code);
			// decode the Exif-GPS profile
			jpegxr_read_exif_gps_profile(dib, pbProfile, cbByteCount, uOffset);
		}

		// free profile buffer
		free(pbProfile);
		// restore initial position
		error_code = pID->pStream->SetPos(pID->pStream, currentPos);
		JXR_CHECK(error_code);

		// as a LAST STEP, read descriptive metadata
		// these metadata overwrite possible identical Exif-TIFF metadata 
		// that could have been read inside the Exif IFD
		
		return ReadDescriptiveMetadata(pID, dib);

	} catch(...) {
		// free profile buffer
		free(pbProfile);
		if(currentPos) {
			// restore initial position
			pStream->SetPos(pStream, currentPos);
		}
		return error_code;
	}
}