1 #ifndef WIC_IMAGE_H
2 #define WIC_IMAGE_H
3
4 // image decoder and encoder with WIC
5 #include <wincodec.h>
6
wic_decode_image(const wchar_t * filepath,int * w,int * h,int * c)7 unsigned char* wic_decode_image(const wchar_t* filepath, int* w, int* h, int* c)
8 {
9 IWICImagingFactory* factory = 0;
10 IWICBitmapDecoder* decoder = 0;
11 IWICBitmapFrameDecode* frame = 0;
12 WICPixelFormatGUID pixel_format;
13 IWICFormatConverter* converter = 0;
14 IWICBitmap* bitmap = 0;
15 IWICBitmapLock* lock = 0;
16 int width = 0;
17 int height = 0;
18 int channels = 0;
19 WICRect rect = { 0, 0, 0, 0 };
20 unsigned int datasize = 0;
21 unsigned char* data = 0;
22 int stride = 0;
23 unsigned char* bgrdata = 0;
24
25 if (CoCreateInstance(CLSID_WICImagingFactory1, 0, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)))
26 goto RETURN;
27
28 if (factory->CreateDecoderFromFilename(filepath, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder))
29 goto RETURN;
30
31 if (decoder->GetFrame(0, &frame))
32 goto RETURN;
33
34 if (factory->CreateFormatConverter(&converter))
35 goto RETURN;
36
37 if (frame->GetPixelFormat(&pixel_format))
38 goto RETURN;
39
40 if (!IsEqualGUID(pixel_format, GUID_WICPixelFormat32bppBGRA))
41 pixel_format = GUID_WICPixelFormat24bppBGR;
42
43 channels = IsEqualGUID(pixel_format, GUID_WICPixelFormat32bppBGRA) ? 4 : 3;
44
45 if (converter->Initialize(frame, pixel_format, WICBitmapDitherTypeNone, 0, 0.0, WICBitmapPaletteTypeCustom))
46 goto RETURN;
47
48 if (factory->CreateBitmapFromSource(converter, WICBitmapCacheOnDemand, &bitmap))
49 goto RETURN;
50
51 if (bitmap->GetSize((UINT*)&width, (UINT*)&height))
52 goto RETURN;
53
54 rect.Width = width;
55 rect.Height = height;
56 if (bitmap->Lock(&rect, WICBitmapLockRead, &lock))
57 goto RETURN;
58
59 if (lock->GetDataPointer(&datasize, &data))
60 goto RETURN;
61
62 if (lock->GetStride((UINT*)&stride))
63 goto RETURN;
64
65 bgrdata = (unsigned char*)malloc(width * height * channels);
66 if (!bgrdata)
67 goto RETURN;
68
69 for (int y = 0; y < height; y++)
70 {
71 const unsigned char* ptr = data + y * stride;
72 unsigned char* bgrptr = bgrdata + y * width * channels;
73 memcpy(bgrptr, ptr, width * channels);
74 }
75
76 *w = width;
77 *h = height;
78 *c = channels;
79
80 RETURN:
81 if (lock) lock->Release();
82 if (bitmap) bitmap->Release();
83 if (decoder) decoder->Release();
84 if (frame) frame->Release();
85 if (converter) converter->Release();
86 if (factory) factory->Release();
87
88 return bgrdata;
89 }
90
wic_encode_image(const wchar_t * filepath,int w,int h,int c,void * bgrdata)91 int wic_encode_image(const wchar_t* filepath, int w, int h, int c, void* bgrdata)
92 {
93 IWICImagingFactory* factory = 0;
94 IWICStream* stream = 0;
95 IWICBitmapEncoder* encoder = 0;
96 IWICBitmapFrameEncode* frame = 0;
97 WICPixelFormatGUID format = c == 4 ? GUID_WICPixelFormat32bppBGRA : GUID_WICPixelFormat24bppBGR;
98 int stride = (w * c * 8 + 7) / 8;
99 unsigned char* data = 0;
100 int ret = 0;
101
102 if (CoCreateInstance(CLSID_WICImagingFactory1, 0, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)))
103 goto RETURN;
104
105 if (factory->CreateStream(&stream))
106 goto RETURN;
107
108 if (stream->InitializeFromFilename(filepath, GENERIC_WRITE))
109 goto RETURN;
110
111 if (factory->CreateEncoder(GUID_ContainerFormatPng, 0, &encoder))
112 goto RETURN;
113
114 if (encoder->Initialize(stream, WICBitmapEncoderNoCache))
115 goto RETURN;
116
117 if (encoder->CreateNewFrame(&frame, 0))
118 goto RETURN;
119
120 if (frame->Initialize(0))
121 goto RETURN;
122
123 if (frame->SetSize((UINT)w, (UINT)h))
124 goto RETURN;
125
126 if (frame->SetPixelFormat(&format))
127 goto RETURN;
128
129 if (!IsEqualGUID(format, c == 4 ? GUID_WICPixelFormat32bppBGRA : GUID_WICPixelFormat24bppBGR))
130 goto RETURN;
131
132 data = (unsigned char*)malloc(h * stride);
133 if (!data)
134 goto RETURN;
135
136 for (int y = 0; y < h; y++)
137 {
138 const unsigned char* bgrptr = (const unsigned char*)bgrdata + y * w * c;
139 unsigned char* ptr = data + y * stride;
140 memcpy(ptr, bgrptr, w * c);
141 }
142
143 if (frame->WritePixels(h, stride, h * stride, data))
144 goto RETURN;
145
146 if (frame->Commit())
147 goto RETURN;
148
149 if (encoder->Commit())
150 goto RETURN;
151
152 ret = 1;
153
154 RETURN:
155 if (data) free(data);
156 if (encoder) encoder->Release();
157 if (frame) frame->Release();
158 if (stream) stream->Release();
159 if (factory) factory->Release();
160
161 return ret;
162 }
163
wic_encode_jpeg_image(const wchar_t * filepath,int w,int h,int c,void * bgrdata)164 int wic_encode_jpeg_image(const wchar_t* filepath, int w, int h, int c, void* bgrdata)
165 {
166 // assert c == 3
167
168 IWICImagingFactory* factory = 0;
169 IWICStream* stream = 0;
170 IWICBitmapEncoder* encoder = 0;
171 IWICBitmapFrameEncode* frame = 0;
172 IPropertyBag2* propertybag = 0;
173 WICPixelFormatGUID format = GUID_WICPixelFormat24bppBGR;
174 int stride = (w * c * 8 + 7) / 8;
175 unsigned char* data = 0;
176 int ret = 0;
177
178 PROPBAG2 option = { 0 };
179 option.pstrName = L"ImageQuality";
180 VARIANT varValue;
181 VariantInit(&varValue);
182 varValue.vt = VT_R4;
183 varValue.fltVal = 1.0f;
184
185 if (CoCreateInstance(CLSID_WICImagingFactory1, 0, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)))
186 goto RETURN;
187
188 if (factory->CreateStream(&stream))
189 goto RETURN;
190
191 if (stream->InitializeFromFilename(filepath, GENERIC_WRITE))
192 goto RETURN;
193
194 if (factory->CreateEncoder(GUID_ContainerFormatJpeg, 0, &encoder))
195 goto RETURN;
196
197 if (encoder->Initialize(stream, WICBitmapEncoderNoCache))
198 goto RETURN;
199
200 if (encoder->CreateNewFrame(&frame, &propertybag))
201 goto RETURN;
202
203 if (propertybag->Write(1, &option, &varValue))
204 goto RETURN;
205
206 if (frame->Initialize(propertybag))
207 goto RETURN;
208
209 if (frame->SetSize((UINT)w, (UINT)h))
210 goto RETURN;
211
212 if (frame->SetPixelFormat(&format))
213 goto RETURN;
214
215 if (!IsEqualGUID(format, GUID_WICPixelFormat24bppBGR))
216 goto RETURN;
217
218 data = (unsigned char*)malloc(h * stride);
219 if (!data)
220 goto RETURN;
221
222 for (int y = 0; y < h; y++)
223 {
224 const unsigned char* bgrptr = (const unsigned char*)bgrdata + y * w * c;
225 unsigned char* ptr = data + y * stride;
226 memcpy(ptr, bgrptr, w * c);
227 }
228
229 if (frame->WritePixels(h, stride, h * stride, data))
230 goto RETURN;
231
232 if (frame->Commit())
233 goto RETURN;
234
235 if (encoder->Commit())
236 goto RETURN;
237
238 ret = 1;
239
240 RETURN:
241 if (data) free(data);
242 if (encoder) encoder->Release();
243 if (frame) frame->Release();
244 if (propertybag) propertybag->Release();
245 if (stream) stream->Release();
246 if (factory) factory->Release();
247
248 return ret;
249 }
250
251 #endif // WIC_IMAGE_H
252