Skip to content

Instantly share code, notes, and snippets.

@nyteshade
Last active November 6, 2018 06:18
Show Gist options
  • Save nyteshade/5777200 to your computer and use it in GitHub Desktop.
Save nyteshade/5777200 to your computer and use it in GitHub Desktop.
This is a friendly class I use in my iOS applications linked with the Google WebP framework. It adds the ability to create any UIImage from WebP encoded imagery. It also attempts to automatically look for an @2x version for retina resolutions. In order to build the libWebP library for iOS, perform a "git clone http://git.chromium.org/webm/libweb…
//
// UIImage+WebP.m
//
// Created by Brielle Harrison <[email protected]>
// Much inspiration for code comes from Carson McDonald
// his website is http://www.ioncannon.net
//
// Portions copyright by Carson McDonald fall under this license
//
// Copyright (c) 2011 Carson McDonald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// The rest falls under the same license with my name
// Copyright (c) 2013 Gabriel Harrison
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <WebP/decode.h>
@interface UIImage (WebP)
+ (UIImage*) imageFromWebP: (NSString *)filePath;
@end
//
// UIImage+WebP.m
//
// Created by Brielle Harrison <[email protected]>
// Much inspiration for code comes from Carson McDonald
// his website is http://www.ioncannon.net
//
// Portions copyright by Carson McDonald fall under this license
//
// Copyright (c) 2011 Carson McDonald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// The rest falls under the same license with my name
// Copyright (c) 2013 Gabriel Harrison
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "UIImage+WebP.h"
/**
* This gets called when the UIImage gets collected and frees the
* underlying image.
*/
static void free_image_data(void *info, const void *data, size_t size)
{
free((void *)data);
}
@implementation UIImage (WebP)
/**
* The imageFromWebP function loads a file with the specified filePath. It
* makes the assumption that the file exists within the main bundle. If the
* main screen is running at a scale greater than 1.0, it will automatically
* attempt to append @2x to the file name as per the convention that Apple
* follows (as I understand it).
*
* If it does change the name from pic.webp to [email protected] and there is no
* file by that name, it will revert and try to load the lo-res image name
* instead.
*
* If for any reason we end up without a path after asking the main bundle for
* the file name with the supplied extension, nil will be returned.
*
* @param filePath a path, relative to the main bundle, where the file resides
* @return a valid UIImage or nil if there was a problem locating the image.
*/
+ (UIImage*) imageFromWebP: (NSString *)filePath {
NSString *path = NULL;
NSString *name = [filePath stringByDeletingPathExtension];
NSString *ext = [filePath pathExtension];
BOOL isRetina = [[UIScreen mainScreen] respondsToSelector:@selector(scale)]
== YES && [[UIScreen mainScreen] scale] > 1.f;
if (isRetina) {
NSString *at2XName = [NSString stringWithFormat:@"%@@2x", name];
BOOL at2XExists = [[NSFileManager defaultManager]
fileExistsAtPath: [NSString stringWithFormat:@"%@.%@",
at2XName, ext]];
if (at2XExists) {
name = at2XName;
}
}
// Now, finally, get the path relative to the bundle
path = [[NSBundle mainBundle] pathForResource:name ofType:ext];
// Return nil if we don't have a path
if (!path) {
return nil;
}
// Find the path of the selected WebP image in the bundle and read
// it into memory.
NSData *imgData = [NSData dataWithContentsOfFile:path];
// Get width and height of the selected WebP image
int width = 0, height = 0;
WebPGetInfo([imgData bytes], [imgData length], &width, &height);
//NSLog(@"Image Width: %d Height: %d", width, height);
// Decode the WebP image data into a RGBA value array
uint8_t *data = WebPDecodeRGBA([imgData bytes], [imgData length], &width,
&height);
// Construct a UIImage from the decoded RGBA value array
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data,
width * height * 4, free_image_data);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault |
kCGImageAlphaLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4 * width,
colorSpaceRef, bitmapInfo, provider, NULL, YES, renderingIntent);
UIImage *result = [UIImage imageWithCGImage:imageRef];
// Clean up
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
return result;
}
@end
//
// WebPUtils.h
//
// Copyright (c) 2013 Brielle Harrison
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef __WebPUtils_H__
#define __WebPUtils_H__
void WebPImageV(UIImageView *view, NSString *webpPath);
void WebPButton(UIButton *button, NSString *webpPath);
void WebPButtonState(UIButton *button, NSString *webpPath, UIControlState state);
#endif /* defined(__WebPUtils_H__) */
//
// WebPUtils.m
//
// Copyright (c) 2013 Brielle Harrison
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "WebPUtils.h"
#import "UIImage+WebP.h"
void WebPButton(UIButton *button, NSString *webpPath) {
[button setImage:[UIImage imageFromWebP:webpPath]
forState:UIControlStateNormal];
}
void WebPImageV(UIImageView *view, NSString *webpPath) {
[view setImage:[UIImage imageFromWebP:webpPath]];
}
void WebPButtonState(UIButton *button, NSString *webpPath, UIControlState state) {
[button setImage:[UIImage imageFromWebP:webpPath]
forState:state];
}
@nyteshade
Copy link
Author

Examples of usage might look like this

#import "WebPUtils.h"

- (void)awakeFromNib {
  // Where self.background is a UIImage property
  self.background = [UIImage imageFromWebP:@"Images/common/notepad_bg.webp"];

or

#import "WebPUtils.h"

- (void)awakeFromNib {
  // Where self.backBtn and self.nextBtn are IBOutlets that point to UIButton properties
  WebPButton(self.backBtn, @"Images/common/backbutton.webp");
  WebPButton(self.nextBtn, @"Images/common/nextbutton.webp");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment