Skip to content

Commit dbe8aa5

Browse files
committed
FEAT: macOS image codecs cleanup and added support for haif encoding/decoding
1 parent 95bf80c commit dbe8aa5

File tree

8 files changed

+115
-116
lines changed

8 files changed

+115
-116
lines changed

make/rebol3.nest

+1-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ include-image-os-codec: [
339339
host-files: [
340340
%os/osx/host-image.c
341341
%os/osx/sys-codecs.m
342-
%os/osx/sys-utils.c
342+
%os/osx/sys-utils.m
343343
]
344344
frameworks: [CoreGraphics CoreImage ImageIO Foundation]
345345
mezz-lib-files: %mezz/codec-image-osx.reb

src/include/reb-c.h

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
#include <type_traits> // used in CASTING MACROS
5454
#endif
5555

56+
#ifdef __OBJC__
57+
#define HAS_BOOL // don't redefine BOOL in objective-c code
58+
#endif
59+
5660
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
5761
/* C-code types: use C99 */
5862

src/mezz/codec-image-osx.reb

+10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ REBOL [
1010
note: {Add the most common codec at tail (identify is testing the last codec as first)}
1111
]
1212

13+
register-codec [
14+
name: 'heif
15+
title: "High Efficiency Image File Format"
16+
suffixes: [%.heif %.heic]
17+
18+
decode: func [data [binary!]][lib/image/load/as data 'HEIF]
19+
encode: func [data [image! ]][lib/image/save/as none data 'HEIF]
20+
identify: func [data [binary!]][parse data [4 skip #{6674797068656963} to end]]
21+
]
22+
1323
register-codec [
1424
name: 'tiff
1525
title: "Tagged Image File Format"

src/os/osx/sys-codecs.h

+3-20
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,7 @@
11
#pragma once
22

3-
#ifdef __OBJC__
4-
#import <Foundation/Foundation.h>
5-
#include <objc/message.h>
6-
#include <objc/runtime.h>
7-
#include <dlfcn.h>
8-
9-
#define CODECS_API
10-
//#define CODECS_API extern "C"
11-
12-
//extern "C" {
13-
//#include "sys-utils.h"
14-
//#include "reb-types.h"
15-
//}
16-
#else
17-
#define CODECS_API
18-
#endif
3+
#include "sys-utils.h"
194
#include "reb-codec.h"
205

21-
CODECS_API int codecs_init();
22-
CODECS_API void codecs_fini();
23-
CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi);
24-
CODECS_API int EncodeImageToFile(const char *uri, REBCDI *codi);
6+
int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi);
7+
int EncodeImageToFile(const char *uri, REBCDI *codi);

src/os/osx/sys-codecs.m

+48-47
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,23 @@
2525
** Note: So far saves just one frame. For multi-image formats it would be
2626
** better to write a device (image:// port or something like that)
2727
**
28-
************************************************************************
29-
** Useful links:
30-
** https://chromium.googlesource.com/webm/webp-wic-codec
31-
***********************************************************************/
32-
28+
************************************************************************/
3329
#include "sys-codecs.h"
34-
#include "sys-utils.h"
30+
#define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic")
31+
#define kSDUTTypeHEIF ((__bridge CFStringRef)@"public.heif")
3532

3633

34+
#ifdef unused
3735
void listImageCodecs(void){
3836
//puts("Suppported codecs:");
3937
CFArrayRef mySourceTypes = CGImageSourceCopyTypeIdentifiers();
4038
CFShow(mySourceTypes);
4139
CFArrayRef myDestinationTypes = CGImageDestinationCopyTypeIdentifiers();
4240
CFShow(myDestinationTypes);
4341
}
42+
#endif
4443

45-
CFURLRef urlFromCString(const char* cString){
46-
NSString *myNSString = [NSString stringWithUTF8String:cString];
47-
NSString *path = [myNSString stringByExpandingTildeInPath];
48-
return CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, 0, false);
49-
}
50-
51-
CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi)
44+
int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi)
5245
{
5346
int error = 0;
5447
CFURLRef url = NULL;
@@ -62,6 +55,7 @@ CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *
6255
NSUInteger w, h;
6356
NSUInteger bytesPerPixel = 4;
6457
NSUInteger bitsPerComponent = 8;
58+
6559
do {
6660
if(uri) {
6761
// decoding from file
@@ -87,7 +81,6 @@ CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *
8781
CGColorSpaceRelease(space);
8882
CGContextRelease(ctx);
8983

90-
//listImageCodecs();
9184
codi->w = (UInt32)w;
9285
codi->h = (UInt32)h;
9386
codi->len = w * h * 4;
@@ -99,11 +92,17 @@ CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *
9992
return error;
10093
}
10194

102-
CODECS_API int EncodeImageToFile(const char *uri, REBCDI *codi)
95+
int EncodeImageToFile(const char *uri, REBCDI *codi)
10396
{
104-
int result = 0;
97+
int error = 0;
10598
CFStringRef type;
10699
CFMutableDictionaryRef prop;
100+
CGDataProviderRef data;
101+
CGColorSpaceRef colorSpace;
102+
CGImageRef img = NULL;
103+
CGImageDestinationRef imgDst = NULL;
104+
CFURLRef url;
105+
CFDataRef dataDst;
107106

108107
switch (codi->type) {
109108
case CODI_IMG_PNG: type = kUTTypePNG ; break; // Portable Network Graphics
@@ -112,43 +111,45 @@ CODECS_API int EncodeImageToFile(const char *uri, REBCDI *codi)
112111
case CODI_IMG_GIF: type = kUTTypeGIF ; break; // Graphics Interchange Format
113112
case CODI_IMG_BMP: type = kUTTypeBMP ; break; // Device independent bitmap
114113
case CODI_IMG_TIFF: type = kUTTypeTIFF ; break; // Tagged Image File Format
114+
case CODI_IMG_HEIF: type = kSDUTTypeHEIC ; break;
115115
default:
116116
codi->error = 1;
117117
return codi->error;
118118
}
119-
120-
CGDataProviderRef data = CGDataProviderCreateWithData(NULL, codi->bits, codi->w * codi->h * 4, NULL);
121-
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
122-
CGImageRef img = CGImageCreate(codi->w, codi->h, 8, 32, codi->w * 4, colorSpace, (kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), data, NULL, TRUE, 0);
123-
CGDataProviderRelease(data);
124-
CGColorSpaceRelease(colorSpace);
125-
126-
CFURLRef url;
127-
CGImageDestinationRef imgDst;
128-
CFDataRef dataDst;
129-
if(uri == NULL) {
130-
// writing into preallocated buffer (fixed size!)
131-
TRACE_PTR("dataTarget:", &codi->data);
132-
dataDst = CFDataCreateWithBytesNoCopy(NULL, codi->data, codi->len, NULL);
133-
imgDst = CGImageDestinationCreateWithData((CFMutableDataRef)dataDst, type, 1, 0);
134-
} else {
135-
// writing directly into file
136-
url = urlFromCString(uri);
137-
imgDst = CGImageDestinationCreateWithURL(url, type, 1, 0);
138-
}
139-
prop = CFDictionaryCreateMutable(NULL,0,NULL,NULL);
140-
CFDictionaryAddValue(prop, kCGImageDestinationLossyCompressionQuality, "0.2");
141-
CGFloat quality = 0.6;
142-
CGImageDestinationAddImage(imgDst, img, (__bridge CFDictionaryRef)@{(__bridge NSString *)kCGImageDestinationLossyCompressionQuality: @(quality)});
143-
CGImageDestinationFinalize(imgDst);
144-
119+
do {
120+
data = CGDataProviderCreateWithData(NULL, codi->bits, codi->w * codi->h * 4, NULL);
121+
ASSERT_NOT_NULL(data, 1, "prepare input data");
122+
colorSpace = CGColorSpaceCreateDeviceRGB();
123+
img = CGImageCreate(codi->w, codi->h, 8, 32, codi->w * 4, colorSpace, (kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), data, NULL, TRUE, 0);
124+
CGDataProviderRelease(data);
125+
CGColorSpaceRelease(colorSpace);
126+
ASSERT_NOT_NULL(img, 2, "create an image");
127+
128+
129+
if(uri == NULL) {
130+
// writing into preallocated buffer (fixed size!)
131+
dataDst = CFDataCreateWithBytesNoCopy(NULL, codi->data, codi->len, NULL);
132+
ASSERT_NOT_NULL(dataDst, 3, "prepare output data");
133+
imgDst = CGImageDestinationCreateWithData((CFMutableDataRef)dataDst, type, 1, 0);
134+
} else {
135+
// writing directly into file
136+
url = urlFromCString(uri);
137+
imgDst = CGImageDestinationCreateWithURL(url, type, 1, 0);
138+
}
139+
ASSERT_NOT_NULL(imgDst, 4, "create a destination image");
140+
// TODO: handle user defined options
141+
prop = CFDictionaryCreateMutable(NULL,0,NULL,NULL);
142+
CFDictionaryAddValue(prop, kCGImageDestinationLossyCompressionQuality, "0.2");
143+
CGFloat quality = 0.6;
144+
CGImageDestinationAddImage(imgDst, img, (__bridge CFDictionaryRef)@{(__bridge NSString *)kCGImageDestinationLossyCompressionQuality: @(quality)});
145+
CGImageDestinationFinalize(imgDst);
146+
} while(FALSE);
145147
if(uri == NULL) {
146-
TRACE_PTR("dataDst:", &dataDst);
147148
codi->len = CFDataGetLength(dataDst);
148149
//CFRelease(dataDst);
149150
}
150-
CFRelease(img);
151-
CFRelease(imgDst);
152-
codi->error = result;
153-
return result;
151+
SAFE_CF_RELEASE(img);
152+
SAFE_CF_RELEASE(imgDst);
153+
codi->error = error;
154+
return error;
154155
}

src/os/osx/sys-utils.c

-37
This file was deleted.

src/os/osx/sys-utils.h

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
//#define TRACES // to enable trace output
21

2+
#ifdef __OBJC__
3+
#import <Foundation/Foundation.h>
4+
#include <objc/message.h>
5+
#include <objc/runtime.h>
6+
#include <dlfcn.h>
7+
8+
CFURLRef urlFromCString(const char* cString);
39

410
#ifdef TRACES
5-
#define TRACE printf
11+
#define TRACE NSLog
612
#else
7-
static void _no_log(const char* fmt, ...) {}
8-
#define TRACE _no_log
13+
static void _no_log(NSString *format, ...){}
14+
#define TRACE _no_log
915
#endif
1016

11-
//#define TRACE_ERR_(msg, err) TRACE("FAILED: " msg " [%lu]", (err))
12-
//#define TRACE_ERR(msg) TRACE("FAILED: " msg " [%lu]", GetLastError())
13-
#define TRACE_FAILED(msg) TRACE("FAILED: " msg " [%lx]")
14-
//#define TRACE_HR_(msg, hr) TRACE(msg " [%lx]", (hr))
15-
//#define TRACE_HR(msg) TRACE(msg " [%lx]", hr)
16-
#define TRACE_PTR(msg, ptr) TRACE(msg " [%0lX]", ptr)
17+
#define TRACE_MSG(msg) TRACE(@"" msg)
18+
#define TRACE_FAILED(msg, err) TRACE(@"FAILED: " msg " [%i]", (err))
19+
#define TRACE_PTR(msg, ptr) TRACE(@"" msg " [%0lX]", ptr)
1720

18-
#define ASSERT_NOT_NULL(v, e, msg) if(!v) {TRACE_FAILED(msg); error = e; break;}
21+
#define ASSERT_NOT_NULL(v, e, msg) if(!v) {TRACE_FAILED(msg, e); error = e; break;}
1922

2023
#define SAFE_CF_RELEASE(obj) if(obj != NULL) {CFRelease(obj); obj = NULL;}
24+
25+
#endif

src/os/osx/sys-utils.m

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/***********************************************************************
2+
**
3+
** REBOL [R3] Language Interpreter and Run-time Environment
4+
**
5+
** Copyright 2021 Oldes
6+
**
7+
** Licensed under the Apache License, Version 2.0 (the "License");
8+
** you may not use this file except in compliance with the License.
9+
** You may obtain a copy of the License at
10+
**
11+
** http://www.apache.org/licenses/LICENSE-2.0
12+
**
13+
** Unless required by applicable law or agreed to in writing, software
14+
** distributed under the License is distributed on an "AS IS" BASIS,
15+
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
** See the License for the specific language governing permissions and
17+
** limitations under the License.
18+
**
19+
************************************************************************
20+
**
21+
** Title: osx objective-c common code
22+
** Author: Oldes
23+
** Purpose: various common osx functions
24+
**
25+
************************************************************************/
26+
27+
#include "sys-utils.h"
28+
29+
CFURLRef urlFromCString(const char* cString){
30+
NSString *myNSString = [NSString stringWithUTF8String:cString];
31+
NSString *path = [myNSString stringByExpandingTildeInPath];
32+
return CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, 0, false);
33+
}

0 commit comments

Comments
 (0)