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; }
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; }