1 // Copyright 2015 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "ios_image_load.h" 16 17 #include <assert.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 #import <CoreImage/CoreImage.h> 23 #import <ImageIO/ImageIO.h> 24 25 std::vector<uint8_t> LoadImageFromFile(const char* file_name, int* out_width, int* out_height, 26 int* out_channels) { 27 FILE* file_handle = fopen(file_name, "rb"); 28 fseek(file_handle, 0, SEEK_END); 29 const size_t bytes_in_file = ftell(file_handle); 30 fseek(file_handle, 0, SEEK_SET); 31 std::vector<uint8_t> file_data(bytes_in_file); 32 fread(file_data.data(), 1, bytes_in_file, file_handle); 33 fclose(file_handle); 34 35 CFDataRef file_data_ref = 36 CFDataCreateWithBytesNoCopy(NULL, file_data.data(), bytes_in_file, kCFAllocatorNull); 37 CGDataProviderRef image_provider = CGDataProviderCreateWithCFData(file_data_ref); 38 39 const char* suffix = strrchr(file_name, '.'); 40 if (!suffix || suffix == file_name) { 41 suffix = ""; 42 } 43 CGImageRef image; 44 if (strcasecmp(suffix, ".png") == 0) { 45 image = CGImageCreateWithPNGDataProvider(image_provider, NULL, true, kCGRenderingIntentDefault); 46 } else if ((strcasecmp(suffix, ".jpg") == 0) || (strcasecmp(suffix, ".jpeg") == 0)) { 47 image = 48 CGImageCreateWithJPEGDataProvider(image_provider, NULL, true, kCGRenderingIntentDefault); 49 } else { 50 CFRelease(image_provider); 51 CFRelease(file_data_ref); 52 fprintf(stderr, "Unknown suffix for file '%s'\n", file_name); 53 *out_width = 0; 54 *out_height = 0; 55 *out_channels = 0; 56 return std::vector<uint8_t>(); 57 } 58 59 const int width = (int)CGImageGetWidth(image); 60 const int height = (int)CGImageGetHeight(image); 61 const int channels = 4; 62 CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); 63 const int bytes_per_row = (width * channels); 64 const int bytes_in_image = (bytes_per_row * height); 65 std::vector<uint8_t> result(bytes_in_image); 66 const int bits_per_component = 8; 67 68 CGContextRef context = 69 CGBitmapContextCreate(result.data(), width, height, bits_per_component, bytes_per_row, 70 color_space, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 71 CGColorSpaceRelease(color_space); 72 CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); 73 CGContextRelease(context); 74 CFRelease(image); 75 CFRelease(image_provider); 76 CFRelease(file_data_ref); 77 78 *out_width = width; 79 *out_height = height; 80 *out_channels = channels; 81 return result; 82 } 83