OLD | NEW |
| (Empty) |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/gfx/image/image.h" | |
6 | |
7 #import <UIKit/UIKit.h> | |
8 #include <cmath> | |
9 #include <limits> | |
10 | |
11 #include "base/logging.h" | |
12 #include "base/mac/scoped_cftyperef.h" | |
13 #include "base/mac/scoped_nsobject.h" | |
14 #include "ui/gfx/image/image_png_rep.h" | |
15 #include "ui/gfx/image/image_skia.h" | |
16 #include "ui/gfx/image/image_skia_util_ios.h" | |
17 #include "ui/gfx/size.h" | |
18 | |
19 namespace gfx { | |
20 namespace internal { | |
21 | |
22 namespace { | |
23 | |
24 // Returns a 16x16 red UIImage to visually show when a UIImage cannot be | |
25 // created from PNG data. Logs error as well. | |
26 // Caller takes ownership of returned UIImage. | |
27 UIImage* CreateErrorUIImage(float scale) { | |
28 LOG(ERROR) << "Unable to decode PNG into UIImage."; | |
29 base::ScopedCFTypeRef<CGColorSpaceRef> color_space( | |
30 CGColorSpaceCreateDeviceRGB()); | |
31 base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate( | |
32 NULL, // Allow CG to allocate memory. | |
33 16, // width | |
34 16, // height | |
35 8, // bitsPerComponent | |
36 0, // CG will calculate by default. | |
37 color_space, | |
38 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); | |
39 CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0); | |
40 CGContextFillRect(context, CGRectMake(0.0, 0.0, 16, 16)); | |
41 base::ScopedCFTypeRef<CGImageRef> cg_image( | |
42 CGBitmapContextCreateImage(context)); | |
43 return [[UIImage imageWithCGImage:cg_image.get() | |
44 scale:scale | |
45 orientation:UIImageOrientationUp] retain]; | |
46 } | |
47 | |
48 // Converts from ImagePNGRep to UIImage. | |
49 UIImage* CreateUIImageFromImagePNGRep(const gfx::ImagePNGRep& image_png_rep) { | |
50 float scale = image_png_rep.scale; | |
51 scoped_refptr<base::RefCountedMemory> png = image_png_rep.raw_data; | |
52 CHECK(png.get()); | |
53 NSData* data = [NSData dataWithBytes:png->front() length:png->size()]; | |
54 UIImage* image = [[UIImage alloc] initWithData:data scale:scale]; | |
55 return image ? image : CreateErrorUIImage(scale); | |
56 } | |
57 | |
58 } // namespace | |
59 | |
60 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage( | |
61 UIImage* uiimage) { | |
62 NSData* data = UIImagePNGRepresentation(uiimage); | |
63 | |
64 if ([data length] == 0) | |
65 return NULL; | |
66 | |
67 scoped_refptr<base::RefCountedBytes> png_bytes( | |
68 new base::RefCountedBytes()); | |
69 png_bytes->data().resize([data length]); | |
70 [data getBytes:&png_bytes->data().at(0) length:[data length]]; | |
71 return png_bytes; | |
72 } | |
73 | |
74 UIImage* CreateUIImageFromPNG( | |
75 const std::vector<gfx::ImagePNGRep>& image_png_reps) { | |
76 float ideal_scale = ImageSkia::GetMaxSupportedScale(); | |
77 | |
78 if (image_png_reps.empty()) | |
79 return CreateErrorUIImage(ideal_scale); | |
80 | |
81 // Find best match for |ideal_scale|. | |
82 float smallest_diff = std::numeric_limits<float>::max(); | |
83 size_t closest_index = 0u; | |
84 for (size_t i = 0; i < image_png_reps.size(); ++i) { | |
85 float scale = image_png_reps[i].scale; | |
86 float diff = std::abs(ideal_scale - scale); | |
87 if (diff < smallest_diff) { | |
88 smallest_diff = diff; | |
89 closest_index = i; | |
90 } | |
91 } | |
92 | |
93 return CreateUIImageFromImagePNGRep(image_png_reps[closest_index]); | |
94 } | |
95 | |
96 scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia( | |
97 const ImageSkia* skia) { | |
98 // iOS does not expose libpng, so conversion from ImageSkia to PNG must go | |
99 // through UIImage. | |
100 // TODO(rohitrao): Rewrite the callers of this function to save the UIImage | |
101 // representation in the gfx::Image. If we're generating it, we might as well | |
102 // hold on to it. | |
103 const gfx::ImageSkiaRep& image_skia_rep = skia->GetRepresentation(1.0f); | |
104 if (image_skia_rep.scale() != 1.0f) | |
105 return NULL; | |
106 | |
107 UIImage* image = UIImageFromImageSkiaRep(image_skia_rep); | |
108 return Get1xPNGBytesFromUIImage(image); | |
109 } | |
110 | |
111 ImageSkia* ImageSkiaFromPNG( | |
112 const std::vector<gfx::ImagePNGRep>& image_png_reps) { | |
113 // iOS does not expose libpng, so conversion from PNG to ImageSkia must go | |
114 // through UIImage. | |
115 gfx::ImageSkia* image_skia = new gfx::ImageSkia(); | |
116 for (size_t i = 0; i < image_png_reps.size(); ++i) { | |
117 base::scoped_nsobject<UIImage> uiimage( | |
118 CreateUIImageFromImagePNGRep(image_png_reps[i])); | |
119 gfx::ImageSkiaRep image_skia_rep = ImageSkiaRepOfScaleFromUIImage( | |
120 uiimage, image_png_reps[i].scale); | |
121 if (!image_skia_rep.is_null()) | |
122 image_skia->AddRepresentation(image_skia_rep); | |
123 } | |
124 return image_skia; | |
125 } | |
126 | |
127 gfx::Size UIImageSize(UIImage* image) { | |
128 int width = static_cast<int>(image.size.width); | |
129 int height = static_cast<int>(image.size.height); | |
130 return gfx::Size(width, height); | |
131 } | |
132 | |
133 } // namespace internal | |
134 } // namespace gfx | |
OLD | NEW |