Пример #1
0
static int add_png_to_family(icns_family_t **iconFamily, char *pngname)
{
	FILE *pngfile;

	int icnsErr = ICNS_STATUS_OK;
	icns_image_t icnsImage;
	icns_image_t icnsMask;
	icns_type_t iconType;
	icns_type_t maskType;
	icns_icon_info_t iconInfo;

	icns_element_t *iconElement = NULL;
	icns_element_t *maskElement = NULL;
	char iconStr[5] = {0,0,0,0,0};
	char maskStr[5] = {0,0,0,0,0};
	int iconDataOffset = 0;
	int maskDataOffset = 0;
    
    char isHiDPI = 0;
    
    int pngnamelen = strlen(pngname);
    int namea2xpng = pngnamelen - 7;

	png_bytep buffer;
	int width, height, bpp;
    
	if(namea2xpng > 0) {
			if(memcmp(&pngname[namea2xpng],"@2x.png",7) == 0) {
					isHiDPI = 1;
			}
			if(memcmp(&pngname[namea2xpng],"@2X.PNG",7) == 0) {
					isHiDPI = 1;
			}
	}
    
	pngfile = fopen(pngname, "rb");
	if (pngfile == NULL)
	{
		fprintf(stderr, "Could not open '%s' for reading: %s\n", pngname, strerror(errno));
		return FALSE;
	}

	if (!read_png(pngfile, &buffer, &bpp, &width, &height))
	{
		fprintf(stderr, "Failed to read PNG file\n");
		fclose(pngfile);

		return FALSE;
	}

	fclose(pngfile);

	icnsImage.imageWidth = width;
	icnsImage.imageHeight = height;
	icnsImage.imageChannels = 4;
	icnsImage.imagePixelDepth = 8;
	icnsImage.imageDataSize = width * height * 4;
	icnsImage.imageData = buffer;

	iconInfo.isImage = 1;
	iconInfo.iconWidth = icnsImage.imageWidth;
	iconInfo.iconHeight = icnsImage.imageHeight;
	iconInfo.iconBitDepth = bpp;
	iconInfo.iconChannels = (bpp == 32 ? 4 : 1);
	iconInfo.iconPixelDepth = bpp / iconInfo.iconChannels;

	iconType = icns_get_type_from_image_info_advanced(iconInfo,isHiDPI);
	maskType = icns_get_mask_type_for_icon_type(iconType);

	icns_type_str(iconType,iconStr);
	icns_type_str(maskType,maskStr);

	/* Only convert the icons that match sizes icns supports */
	if (iconType == ICNS_NULL_TYPE)
	{
		fprintf(stderr, "Unable to determine icon type: PNG file '%s' is %dx%d\n", pngname, width, height);
		free(buffer);

		return FALSE;
	}

	if (bpp != 32)
	{
		fprintf(stderr, "Bit depth %d unsupported in '%s'\n", bpp, pngname);
		free(buffer);

		return FALSE;
	}

	icns_set_print_errors(0);
	if (icns_get_element_from_family(*iconFamily, iconType, &iconElement) == ICNS_STATUS_OK)
	{
		icns_set_print_errors(1);

		fprintf(stderr, "Duplicate icon element of type '%s' detected (%s)\n", iconStr, pngname);
		free(buffer);

		return FALSE;
	}
	
	icns_set_print_errors(1);
	
	#if DEBUG_ICNSUTIL
	if(maskType != ICNS_NULL_TYPE)
	{
		printf("Using icns type '%s', mask '%s' for '%s'\n", iconStr, maskStr, pngname);
	}
	else
	{
		printf("Using icns type '%s' (ARGB) for '%s'\n", iconStr, pngname);
	}
	#endif
	
	icnsErr = icns_new_element_from_image(&icnsImage, iconType, &iconElement);
	
	if (iconElement != NULL)
	{
		if (icnsErr == ICNS_STATUS_OK)
		{
			icns_set_element_in_family(iconFamily, iconElement);
		}
		free(iconElement);
	}

	if(maskType != ICNS_NULL_TYPE)
	{
		icns_init_image_for_type(maskType, &icnsMask);

		iconDataOffset = 0;
		maskDataOffset = 0;
	
		while ((iconDataOffset < icnsImage.imageDataSize) && (maskDataOffset < icnsMask.imageDataSize))
		{
			icnsMask.imageData[maskDataOffset] = icnsImage.imageData[iconDataOffset+3];
			iconDataOffset += 4; /* move to the next alpha byte */
			maskDataOffset += 1; /* move to the next byte */
		}

		icnsErr = icns_new_element_from_mask(&icnsMask, maskType, &maskElement);

		if (maskElement != NULL)
		{
			if (icnsErr == ICNS_STATUS_OK)
			{
				icns_set_element_in_family(iconFamily, maskElement);
			}
			free(maskElement);
		}
		
		icns_free_image(&icnsMask);
	}

	free(buffer);

	return TRUE;
}
Пример #2
0
int icns_get_image32_with_mask_from_family(icns_family_t *iconFamily,icns_type_t iconType,icns_image_t *imageOut)
{
	int		error = ICNS_STATUS_OK;
	icns_type_t	maskType = ICNS_NULL_TYPE;
	icns_element_t	*iconElement = NULL;
	icns_element_t	*maskElement = NULL;
	icns_image_t	iconImage;
	icns_image_t	maskImage;
	unsigned long	dataCount = 0;
	icns_byte_t	dataValue = 0;
	unsigned long	pixelCount = 0;
	unsigned long	pixelID = 0;
	icns_byte_t	colorIndex = 0;	
	
	memset ( &iconImage, 0, sizeof(icns_image_t) );
	memset ( &maskImage, 0, sizeof(icns_image_t) );
	
	if(iconFamily == NULL)
	{
		icns_print_err("icns_get_image32_with_mask_from_family: Icon family is NULL!\n");
		return ICNS_STATUS_NULL_PARAM;
	}
	
	if(imageOut == NULL)
	{
		icns_print_err("icns_get_image32_with_mask_from_family: Icon image is NULL!\n");
		return ICNS_STATUS_NULL_PARAM;
	}
	else
	{
		icns_free_image(imageOut);
	}
	
	#ifdef ICNS_DEBUG
	{
		char typeStr[5];
		printf("Making 32-bit image...\n");
		printf("  using icon type '%s'\n",icns_type_str(iconType,typeStr));
	}
	#endif
	
	
	if((iconType == ICNS_128X128_8BIT_MASK) || \
	(iconType == ICNS_48x48_8BIT_MASK) || \
	(iconType == ICNS_32x32_8BIT_MASK) || \
	(iconType == ICNS_16x16_8BIT_MASK) )
	{
		icns_print_err("icns_get_image32_with_mask_from_family: Can't make an image with mask from a mask\n");
		return ICNS_STATUS_INVALID_DATA;
	}
	
	// Preliminaries checked - carry on with the icon/mask merge
	
	// Load icon element then image
	error = icns_get_element_from_family(iconFamily,iconType,&iconElement);
	
	if(error) {
		icns_print_err("icns_get_image32_with_mask_from_family: Unable to load icon element from icon family!\n");
		goto cleanup;
	}
	
	error = icns_get_image_from_element(iconElement,&iconImage);
	
	if(error) {
		icns_print_err("icns_get_image32_with_mask_from_family: Unable to load icon image data from icon element!\n");
		goto cleanup;
	}
	
	// We used the jp2/png processor for these two, so we're done!
	if(
    (iconType == ICNS_128x128_32BIT_ARGB_DATA) ||
    (iconType == ICNS_256x256_32BIT_ARGB_DATA) ||
    (iconType == ICNS_512x512_32BIT_ARGB_DATA) ||
    (iconType == ICNS_1024x1024_32BIT_ARGB_DATA) ||
    (iconType == ICNS_16x16_2X_32BIT_ARGB_DATA) ||
    (iconType == ICNS_32x32_2X_32BIT_ARGB_DATA) ||
    (iconType == ICNS_128x128_2X_32BIT_ARGB_DATA) ||
    (iconType == ICNS_256x256_2X_32BIT_ARGB_DATA) ||
    (iconType == ICNS_512x512_2X_32BIT_ARGB_DATA)
	) {
		memcpy(imageOut,&iconImage,sizeof(icns_image_t));
		if(iconElement != NULL) {
		free(iconElement);
		iconElement = NULL;
		}
		return error;
	}
	
	maskType = icns_get_mask_type_for_icon_type(iconType);
	
	#ifdef ICNS_DEBUG
	{
		char typeStr[5];
		printf("  using mask type '%s'\n",icns_type_str(maskType,typeStr));
	}
	#endif
	
	if( (maskType == ICNS_NULL_DATA) )
	{
		char typeStr[5];
		icns_print_err("icns_get_image32_with_mask_from_family: Can't find mask for type '%s'\n",icns_type_str(iconType,typeStr));
		return ICNS_STATUS_DATA_NOT_FOUND;
	}
	
	// Load mask element then image...
	error = icns_get_element_from_family(iconFamily,maskType,&maskElement);
	
	// Note that we could arguably recover from not having a mask
	// by creating a dummy blank mask. However, the icns data type
	// should always have the corresponding mask present. This
	// function was designed to retreive a VALID image... There are
	// other API functions better used if the goal is editing, data
	// recovery, etc.
	if(error) {
		icns_print_err("icns_get_image32_with_mask_from_family: Unable to load mask element from icon family!\n");
		goto cleanup;
	}
	
	error = icns_get_mask_from_element(maskElement,&maskImage);
	
	if(error) {
		icns_print_err("icns_get_image32_with_mask_from_family: Unable to load mask image data from icon element!\n");
		goto cleanup;
	}
	
	if(iconImage.imageWidth != maskImage.imageWidth) {
		icns_print_err("icns_get_image32_with_mask_from_family: icon and mask widths do not match! (%d != %d)\n",iconImage.imageWidth,maskImage.imageHeight);
		goto cleanup;
	}
	
	if(iconImage.imageHeight != maskImage.imageHeight) {
		icns_print_err("icns_get_image32_with_mask_from_family: icon and mask heights do not match! (%d != %d)\n",iconImage.imageHeight,maskImage.imageHeight);
		goto cleanup;
	}
	
	// Unpack image pixels if depth is < 32
	if((iconImage.imagePixelDepth * iconImage.imageChannels) < 32)
	{
		icns_byte_t	*oldData = NULL;
		icns_byte_t	*newData = NULL;
		icns_uint32_t	oldBitDepth = 0;
		unsigned long	newBlockSize = 0;
		unsigned long	newDataSize = 0;
		icns_colormap_rgb_t	colorRGB;
		
		oldBitDepth = (iconImage.imagePixelDepth * iconImage.imageChannels);
		
		pixelCount = iconImage.imageWidth * iconImage.imageHeight;
		
		newBlockSize = iconImage.imageWidth * 32;
		newDataSize = newBlockSize * iconImage.imageHeight;
		
		oldData = iconImage.imageData;
		newData = (icns_byte_t *)malloc(newDataSize);
		
		if(newData == NULL)
		{
			icns_print_err("icns_get_image32_with_mask_from_family: Unable to allocate memory block of size: %d!\n",(int)newDataSize);
			return ICNS_STATUS_NO_MEMORY;
		}
		
		dataCount = 0;
		
		// 8-Bit Icon Image Data Types
		if((iconType == ICNS_48x48_8BIT_DATA) || \
		(iconType == ICNS_32x32_8BIT_DATA) || \
		(iconType == ICNS_16x16_8BIT_DATA) || \
		(iconType == ICNS_16x12_8BIT_DATA) )
		{
			if(oldBitDepth != 8)
			{
				icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - type mismatch!\n");
				free(newData);
				error = ICNS_STATUS_INVALID_DATA;
				goto cleanup;
			}
			for(pixelID = 0; pixelID < pixelCount; pixelID++)
			{
				colorIndex = oldData[dataCount++];
				colorRGB = icns_colormap_8[colorIndex];
				newData[pixelID * 4 + 0] = colorRGB.r;
				newData[pixelID * 4 + 1] = colorRGB.g;
				newData[pixelID * 4 + 2] = colorRGB.b;
				newData[pixelID * 4 + 3] = 0xff;
			}
		}
		// 4-Bit Icon Image Data Types
		else if((iconType == ICNS_48x48_4BIT_DATA) || \
		(iconType == ICNS_32x32_4BIT_DATA) || \
		(iconType == ICNS_16x16_4BIT_DATA) || \
		(iconType == ICNS_16x12_4BIT_DATA) )
		{
			if(oldBitDepth != 4)
			{
				icns_print_err("icns_get_image32_with_mask_from_family: Invalid bit depth - type mismatch!\n");
				free(newData);
				error = ICNS_STATUS_INVALID_DATA;
				goto cleanup;
			}
			for(pixelID = 0; pixelID < pixelCount; pixelID++)
			{
				if(pixelID % 2 == 0)
					dataValue = oldData[dataCount++];
				colorIndex = (dataValue & 0xF0) >> 4;
				dataValue = dataValue << 4;
				colorRGB = icns_colormap_4[colorIndex];
				newData[pixelID * 4 + 0] = colorRGB.r;
				newData[pixelID * 4 + 1] = colorRGB.g;
				newData[pixelID * 4 + 2] = colorRGB.b;
				newData[pixelID * 4 + 3] = 0xFF;
			}
		}
		// 1-Bit Icon Image Data Types
		else if((iconType == ICNS_48x48_1BIT_DATA) || \
Пример #3
0
ICNSSaver::ICNSSaver(BPositionIO *stream, uint32 rowBytes, icns_type_t type)
{
	fCreated = false;	

	icns_icon_info_t imageTypeInfo = icns_get_image_info_for_type(type);	
	int iconWidth = imageTypeInfo.iconWidth;
	int iconHeight = imageTypeInfo.iconWidth;
	int bpp = 32;

	uint8 *bits = new uint8[iconWidth * iconHeight * sizeof(uint32)];
	
	uint8 *rowPtr = bits;
	for (int i = 0; i < iconHeight; i++) {
		stream->Read(rowPtr, rowBytes);
		uint8 *bytePtr = rowPtr;
		for (int j=0; j < iconWidth; j++) {
			uint8 temp = bytePtr[0];
			bytePtr[0] = bytePtr[2];
			bytePtr[2] = temp;
			bytePtr += sizeof(uint32);
		}
		rowPtr += iconWidth * sizeof(uint32);
	}
	
	icns_create_family(&fIconFamily);
	
	icns_image_t icnsImage;	
	icnsImage.imageWidth = iconWidth;
	icnsImage.imageHeight = iconHeight;
	icnsImage.imageChannels = 4;
	icnsImage.imagePixelDepth = 8;
	icnsImage.imageDataSize = iconWidth * iconHeight * 4;
	icnsImage.imageData = bits;		

	icns_icon_info_t iconInfo;
	iconInfo.isImage = 1;
	iconInfo.iconWidth = icnsImage.imageWidth;
	iconInfo.iconHeight = icnsImage.imageHeight;
	iconInfo.iconBitDepth = bpp;
	iconInfo.iconChannels = (bpp == 32 ? 4 : 1);
	iconInfo.iconPixelDepth = bpp / iconInfo.iconChannels;

	icns_type_t iconType = icns_get_type_from_image_info(iconInfo);
	
	if (iconType == ICNS_NULL_TYPE) {
		delete bits;
		free(fIconFamily);
		fIconFamily = NULL;
		return;
	}

	icns_element_t *iconElement = NULL;
	int icnsErr = icns_new_element_from_image(&icnsImage, iconType,
		&iconElement);
		
	if (iconElement != NULL) {
		if (icnsErr == ICNS_STATUS_OK) {
			icns_set_element_in_family(&fIconFamily, iconElement);
			fCreated = true;
		}
		free(iconElement);
	}
	
	if (iconType != ICNS_1024x1024_32BIT_ARGB_DATA
		&& iconType != ICNS_512x512_32BIT_ARGB_DATA
		&& iconType != ICNS_256x256_32BIT_ARGB_DATA)
	{
		icns_type_t maskType = icns_get_mask_type_for_icon_type(iconType);
		
		icns_image_t icnsMask;
		icns_init_image_for_type(maskType, &icnsMask);

		uint32 iconDataOffset = 0;
		uint32 maskDataOffset = 0;
	
		while (iconDataOffset < icnsImage.imageDataSize 
			&& maskDataOffset < icnsMask.imageDataSize)	{
			icnsMask.imageData[maskDataOffset] =
				icnsImage.imageData[iconDataOffset + 3];
			iconDataOffset += 4;
			maskDataOffset += 1;
		}
		
		icns_element_t *maskElement = NULL;
		icnsErr = icns_new_element_from_mask(&icnsMask, maskType,
			&maskElement);

		if (maskElement != NULL) {
			if (icnsErr == ICNS_STATUS_OK)
				icns_set_element_in_family(&fIconFamily, maskElement);
			else
				fCreated = false;
			free(maskElement);
		}		
		icns_free_image(&icnsMask);
	}	
		
	if (!fCreated) {
		free(fIconFamily);
		fIconFamily = NULL;
	}
	
	delete bits;
}