⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 format_canon.c

📁 Gqview,Linux下基于GTK+库写成的轻量级而能丰富的图像浏览程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  GQView *  (C) 2005 John Ellis * * This software is released under the GNU General Public License (GNU GPL). * Please read the included file COPYING for more information. * This software comes with no warranty of any kind, use at your own risk! * * * Code to add support for Canon CR2 and CRW files, version 0.2 * * Developed by Daniel M. German, dmgerman at uvic.ca  * * you can find the sources for this patch at http://turingmachine.org/~dmg/libdcraw/gqview/ * */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include <stdio.h>#include <string.h>#include <unistd.h>#include <glib.h>#include "intl.h"#include "format_canon.h"#include "format_raw.h"#include "exif.h"/* *----------------------------------------------------------------------------- * Raw (CR2, CRW) embedded jpeg extraction for Canon *----------------------------------------------------------------------------- */static gint canon_cr2_tiff_entry(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,				 guint *image_offset, gint *jpeg_encoding){	guint tag;	guint type;	guint count;	guint jpeg_start;	/* the two (tiff compliant) tags we want are:	 *  0x0103 image compression type (must be type 6 for jpeg)	 *  0x0111 jpeg start offset	 * only use the first segment that contains an actual jpeg - as there	 * is a another that contains the raw data.	 */	tag = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_TAG, bo);	type = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_FORMAT, bo);	count = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_COUNT, bo);	/* tag 0x0103 contains the compression type for this segment's image data */	if (tag == 0x0103)		{		if (ExifFormatList[type].size * count == 2 &&		    exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_DATA, bo) == 6)			{			*jpeg_encoding = TRUE;			}		return FALSE;		}	/* find and verify jpeg offset */	if (tag != 0x0111 ||	    !jpeg_encoding) return FALSE;	/* make sure data segment contains 4 bytes */	if (ExifFormatList[type].size * count != 4) return FALSE;	jpeg_start = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_DATA, bo);	/* verify this is jpeg data */	if (len < jpeg_start + 4 ||	    memcmp(data + jpeg_start, "\xff\xd8", 2) != 0)		{		return FALSE;		}	*image_offset = jpeg_start;	return TRUE;}static gint canon_cr2_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,				 guint *image_offset){	gint jpeg_encoding = FALSE;	guint count;	guint i;	if (len < offset + 2) return 0;	count = exif_byte_get_int16(data + offset, bo);	offset += 2;	if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0;	for (i = 0; i < count; i++)		{		if (canon_cr2_tiff_entry(data, len, offset + i * EXIF_TIFD_SIZE, bo,					 image_offset, &jpeg_encoding))			{			return 0;			}		}	return exif_byte_get_int32(data + offset + count * EXIF_TIFD_SIZE, bo);}gint format_canon_raw_cr2(unsigned char *data, const guint len,			  guint *image_offset, guint *exif_offset){	guint jpeg_offset = 0;	ExifByteOrder bo;	guint offset;	gint level;	/* cr2 files are tiff files with a few canon specific directory tags	 * they are (always ?) in little endian format	 */	if (!exif_tiff_directory_offset(data, len, &offset, &bo)) return FALSE;	level = 0;	while (offset && level < EXIF_TIFF_MAX_LEVELS)		{		offset = canon_cr2_tiff_table(data, len, offset, bo, &jpeg_offset);		level++;		if (jpeg_offset != 0)			{			if (image_offset) *image_offset = jpeg_offset;			return TRUE;			}		}	return FALSE;}#define CRW_BYTE_ORDER		EXIF_BYTE_ORDER_INTEL#define CRW_HEADER_SIZE		26#define CRW_DIR_ENTRY_SIZE	10gint format_canon_raw_crw(unsigned char *data, const guint len,			  guint *image_offset, guint *exif_offset){	guint block_offset;	guint data_length;	guint offset;	guint count;	guint i;	/* CRW header starts with 2 bytes for byte order (always "II", little endian),	 * 4 bytes for start of root block,	 * and 8 bytes of magic for file type and format "HEAPCCDR"	 * (also 4 bytes for file version, and 8 bytes reserved)	 *	 * CIFF specification in pdf format is available on some websites,	 * search for "CIFFspecV1R03.pdf" or "CIFFspecV1R04.pdf"	 */	if (len < CRW_HEADER_SIZE ||	    memcmp(data, "II", 2) != 0 ||	    memcmp(data + 6, "HEAPCCDR", 8) != 0)		{		return FALSE;		}	block_offset = exif_byte_get_int32(data + 2, CRW_BYTE_ORDER);	/* the end of the root block equals end of file,	 * the last 4 bytes of the root block contain the block's data size	 */	offset = len - 4;	data_length = exif_byte_get_int32(data + offset, CRW_BYTE_ORDER);	offset = block_offset + data_length;	if (len < offset + 2) return FALSE;	/* number of directory entries for this block is in	 * the next two bytes after the data for this block.	 */	count = exif_byte_get_int16(data + offset, CRW_BYTE_ORDER);	offset += 2;	if (len < offset + count * CRW_DIR_ENTRY_SIZE + 4) return FALSE;	/* walk the directory entries looking for type jpeg (tag 0x2007),	 * for reference, other tags are 0x2005 for raw and 0x300a for photo info:	 */	for (i = 0; i < count ; i++)		{		guint entry_offset;		guint record_type;		guint record_offset;		guint record_length;		entry_offset = offset + i * CRW_DIR_ENTRY_SIZE;		/* entry is 10 bytes (in order):		 *  2 for type		 *  4 for length of data		 *  4 for offset into data segment of this block		 */		record_type = exif_byte_get_int16(data + entry_offset, CRW_BYTE_ORDER);		record_length = exif_byte_get_int32(data + entry_offset + 2, CRW_BYTE_ORDER);		record_offset = exif_byte_get_int32(data + entry_offset + 6, CRW_BYTE_ORDER);		/* tag we want for jpeg data */		if (record_type == 0x2007)			{			guint jpeg_offset;			jpeg_offset = block_offset + record_offset;		 	if (len < jpeg_offset + record_length ||			    record_length < 4 ||			    memcmp(data + jpeg_offset, "\xff\xd8\xff\xdb", 4) != 0)				{				return FALSE;				}			/* we now know offset and verified jpeg */			*image_offset = jpeg_offset;			return TRUE;			}		}	return FALSE;}/* *----------------------------------------------------------------------------- * EXIF Makernote for Canon *----------------------------------------------------------------------------- */static ExifTextList CanonSet1MacroMode[] = {	{ 1,	"macro" },	{ 2,	"normal" },	EXIF_TEXT_LIST_END};static ExifTextList CanonSet1Quality[] = {	{ 2,	"normal" },	{ 3,	"fine" },	{ 4,	"raw" },	{ 5,	"superfine" },	EXIF_TEXT_LIST_END};static ExifTextList CanonSet1FlashMode[] = {	{ 0,	"flash not fired" },	{ 1,	"auto" },	{ 2,	"on" },	{ 3,	"red-eye reduction" },	{ 4,	"slow sync" },	{ 5,	"auto + red-eye reduction" },	{ 6,	"on + red-eye reduction" },	{ 16,	"external flash" },	EXIF_TEXT_LIST_END};static ExifTextList CanonSet1DriveMode[] = {	{ 0,	"single or timer" },	{ 1,	"continuous" },	EXIF_TEXT_LIST_END};static ExifTextList CanonSet1FocusMode[] = {	{ 0,	"one-shot AF" },	{ 1,	"AI servo AF" },	{ 2,	"AI focus AF" },	{ 3,	"manual" },	{ 4,	"single" },	{ 5,	"continuous" },	{ 6,	"manual" },	EXIF_TEXT_LIST_END};static ExifTextList CanonSet1ImageSize[] = {	{ 0,	"large" },	{ 1,	"medium" },	{ 2,	"small" },	/* where (or) does Medium 1/2 fit in here ? */	EXIF_TEXT_LIST_END};static ExifTextList CanonSet1ShootingMode[] = {	{ 0,	"auto" },	{ 1,	"manual" },	{ 2,	"landscape" },	{ 3,	"fast shutter" },	{ 4,	"slow shutter" },	{ 5,	"night" },	{ 6,	"black and white" },	{ 7,	"sepia" },	{ 8,	"portrait" },	{ 9,	"sports" },	{ 10,	"macro" },	{ 11,	"pan focus" },	EXIF_TEXT_LIST_END};/* Don't think this is interpreted correctly/completely, A60 at 2.5x Digital sets value of 3 */static ExifTextList CanonSet1DigitalZoom[] = {	{ 0,	"none" },	{ 1,	"2x" },	{ 2,	"4x" },	{ 3,	"other" },	EXIF_TEXT_LIST_END};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -