Skip to content

Commit

Permalink
FEAT: macOS image codecs cleanup and added support for haif encodin…
Browse files Browse the repository at this point in the history
…g/decoding
  • Loading branch information
Oldes committed Aug 25, 2021
1 parent 95bf80c commit dbe8aa5
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 116 deletions.
2 changes: 1 addition & 1 deletion make/rebol3.nest
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ include-image-os-codec: [
host-files: [
%os/osx/host-image.c
%os/osx/sys-codecs.m
%os/osx/sys-utils.c
%os/osx/sys-utils.m
]
frameworks: [CoreGraphics CoreImage ImageIO Foundation]
mezz-lib-files: %mezz/codec-image-osx.reb
Expand Down
4 changes: 4 additions & 0 deletions src/include/reb-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
#include <type_traits> // used in CASTING MACROS
#endif

#ifdef __OBJC__
#define HAS_BOOL // don't redefine BOOL in objective-c code
#endif

#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
/* C-code types: use C99 */

Expand Down
10 changes: 10 additions & 0 deletions src/mezz/codec-image-osx.reb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ REBOL [
note: {Add the most common codec at tail (identify is testing the last codec as first)}
]

register-codec [
name: 'heif
title: "High Efficiency Image File Format"
suffixes: [%.heif %.heic]

decode: func [data [binary!]][lib/image/load/as data 'HEIF]
encode: func [data [image! ]][lib/image/save/as none data 'HEIF]
identify: func [data [binary!]][parse data [4 skip #{6674797068656963} to end]]
]

register-codec [
name: 'tiff
title: "Tagged Image File Format"
Expand Down
23 changes: 3 additions & 20 deletions src/os/osx/sys-codecs.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
#pragma once

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#include <objc/message.h>
#include <objc/runtime.h>
#include <dlfcn.h>

#define CODECS_API
//#define CODECS_API extern "C"

//extern "C" {
//#include "sys-utils.h"
//#include "reb-types.h"
//}
#else
#define CODECS_API
#endif
#include "sys-utils.h"
#include "reb-codec.h"

CODECS_API int codecs_init();
CODECS_API void codecs_fini();
CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi);
CODECS_API int EncodeImageToFile(const char *uri, REBCDI *codi);
int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi);
int EncodeImageToFile(const char *uri, REBCDI *codi);
95 changes: 48 additions & 47 deletions src/os/osx/sys-codecs.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,23 @@
** Note: So far saves just one frame. For multi-image formats it would be
** better to write a device (image:// port or something like that)
**
************************************************************************
** Useful links:
** https://chromium.googlesource.com/webm/webp-wic-codec
***********************************************************************/

************************************************************************/
#include "sys-codecs.h"
#include "sys-utils.h"
#define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic")
#define kSDUTTypeHEIF ((__bridge CFStringRef)@"public.heif")


#ifdef unused
void listImageCodecs(void){
//puts("Suppported codecs:");
CFArrayRef mySourceTypes = CGImageSourceCopyTypeIdentifiers();
CFShow(mySourceTypes);
CFArrayRef myDestinationTypes = CGImageDestinationCopyTypeIdentifiers();
CFShow(myDestinationTypes);
}
#endif

CFURLRef urlFromCString(const char* cString){
NSString *myNSString = [NSString stringWithUTF8String:cString];
NSString *path = [myNSString stringByExpandingTildeInPath];
return CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, 0, false);
}

CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi)
int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *codi)
{
int error = 0;
CFURLRef url = NULL;
Expand All @@ -62,6 +55,7 @@ CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *
NSUInteger w, h;
NSUInteger bytesPerPixel = 4;
NSUInteger bitsPerComponent = 8;

do {
if(uri) {
// decoding from file
Expand All @@ -87,7 +81,6 @@ CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *
CGColorSpaceRelease(space);
CGContextRelease(ctx);

//listImageCodecs();
codi->w = (UInt32)w;
codi->h = (UInt32)h;
codi->len = w * h * 4;
Expand All @@ -99,11 +92,17 @@ CODECS_API int DecodeImageFromFile(const char *uri, unsigned int frame, REBCDI *
return error;
}

CODECS_API int EncodeImageToFile(const char *uri, REBCDI *codi)
int EncodeImageToFile(const char *uri, REBCDI *codi)
{
int result = 0;
int error = 0;
CFStringRef type;
CFMutableDictionaryRef prop;
CGDataProviderRef data;
CGColorSpaceRef colorSpace;
CGImageRef img = NULL;
CGImageDestinationRef imgDst = NULL;
CFURLRef url;
CFDataRef dataDst;

switch (codi->type) {
case CODI_IMG_PNG: type = kUTTypePNG ; break; // Portable Network Graphics
Expand All @@ -112,43 +111,45 @@ CODECS_API int EncodeImageToFile(const char *uri, REBCDI *codi)
case CODI_IMG_GIF: type = kUTTypeGIF ; break; // Graphics Interchange Format
case CODI_IMG_BMP: type = kUTTypeBMP ; break; // Device independent bitmap
case CODI_IMG_TIFF: type = kUTTypeTIFF ; break; // Tagged Image File Format
case CODI_IMG_HEIF: type = kSDUTTypeHEIC ; break;
default:
codi->error = 1;
return codi->error;
}

CGDataProviderRef data = CGDataProviderCreateWithData(NULL, codi->bits, codi->w * codi->h * 4, NULL);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef img = CGImageCreate(codi->w, codi->h, 8, 32, codi->w * 4, colorSpace, (kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), data, NULL, TRUE, 0);
CGDataProviderRelease(data);
CGColorSpaceRelease(colorSpace);

CFURLRef url;
CGImageDestinationRef imgDst;
CFDataRef dataDst;
if(uri == NULL) {
// writing into preallocated buffer (fixed size!)
TRACE_PTR("dataTarget:", &codi->data);
dataDst = CFDataCreateWithBytesNoCopy(NULL, codi->data, codi->len, NULL);
imgDst = CGImageDestinationCreateWithData((CFMutableDataRef)dataDst, type, 1, 0);
} else {
// writing directly into file
url = urlFromCString(uri);
imgDst = CGImageDestinationCreateWithURL(url, type, 1, 0);
}
prop = CFDictionaryCreateMutable(NULL,0,NULL,NULL);
CFDictionaryAddValue(prop, kCGImageDestinationLossyCompressionQuality, "0.2");
CGFloat quality = 0.6;
CGImageDestinationAddImage(imgDst, img, (__bridge CFDictionaryRef)@{(__bridge NSString *)kCGImageDestinationLossyCompressionQuality: @(quality)});
CGImageDestinationFinalize(imgDst);

do {
data = CGDataProviderCreateWithData(NULL, codi->bits, codi->w * codi->h * 4, NULL);
ASSERT_NOT_NULL(data, 1, "prepare input data");
colorSpace = CGColorSpaceCreateDeviceRGB();
img = CGImageCreate(codi->w, codi->h, 8, 32, codi->w * 4, colorSpace, (kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), data, NULL, TRUE, 0);
CGDataProviderRelease(data);
CGColorSpaceRelease(colorSpace);
ASSERT_NOT_NULL(img, 2, "create an image");


if(uri == NULL) {
// writing into preallocated buffer (fixed size!)
dataDst = CFDataCreateWithBytesNoCopy(NULL, codi->data, codi->len, NULL);
ASSERT_NOT_NULL(dataDst, 3, "prepare output data");
imgDst = CGImageDestinationCreateWithData((CFMutableDataRef)dataDst, type, 1, 0);
} else {
// writing directly into file
url = urlFromCString(uri);
imgDst = CGImageDestinationCreateWithURL(url, type, 1, 0);
}
ASSERT_NOT_NULL(imgDst, 4, "create a destination image");
// TODO: handle user defined options
prop = CFDictionaryCreateMutable(NULL,0,NULL,NULL);
CFDictionaryAddValue(prop, kCGImageDestinationLossyCompressionQuality, "0.2");
CGFloat quality = 0.6;
CGImageDestinationAddImage(imgDst, img, (__bridge CFDictionaryRef)@{(__bridge NSString *)kCGImageDestinationLossyCompressionQuality: @(quality)});
CGImageDestinationFinalize(imgDst);
} while(FALSE);
if(uri == NULL) {
TRACE_PTR("dataDst:", &dataDst);
codi->len = CFDataGetLength(dataDst);
//CFRelease(dataDst);
}
CFRelease(img);
CFRelease(imgDst);
codi->error = result;
return result;
SAFE_CF_RELEASE(img);
SAFE_CF_RELEASE(imgDst);
codi->error = error;
return error;
}
37 changes: 0 additions & 37 deletions src/os/osx/sys-utils.c

This file was deleted.

27 changes: 16 additions & 11 deletions src/os/osx/sys-utils.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
//#define TRACES // to enable trace output

#ifdef __OBJC__
#import <Foundation/Foundation.h>
#include <objc/message.h>
#include <objc/runtime.h>
#include <dlfcn.h>

CFURLRef urlFromCString(const char* cString);

#ifdef TRACES
#define TRACE printf
#define TRACE NSLog
#else
static void _no_log(const char* fmt, ...) {}
#define TRACE _no_log
static void _no_log(NSString *format, ...){}
#define TRACE _no_log
#endif

//#define TRACE_ERR_(msg, err) TRACE("FAILED: " msg " [%lu]", (err))
//#define TRACE_ERR(msg) TRACE("FAILED: " msg " [%lu]", GetLastError())
#define TRACE_FAILED(msg) TRACE("FAILED: " msg " [%lx]")
//#define TRACE_HR_(msg, hr) TRACE(msg " [%lx]", (hr))
//#define TRACE_HR(msg) TRACE(msg " [%lx]", hr)
#define TRACE_PTR(msg, ptr) TRACE(msg " [%0lX]", ptr)
#define TRACE_MSG(msg) TRACE(@"" msg)
#define TRACE_FAILED(msg, err) TRACE(@"FAILED: " msg " [%i]", (err))
#define TRACE_PTR(msg, ptr) TRACE(@"" msg " [%0lX]", ptr)

#define ASSERT_NOT_NULL(v, e, msg) if(!v) {TRACE_FAILED(msg); error = e; break;}
#define ASSERT_NOT_NULL(v, e, msg) if(!v) {TRACE_FAILED(msg, e); error = e; break;}

#define SAFE_CF_RELEASE(obj) if(obj != NULL) {CFRelease(obj); obj = NULL;}

#endif
33 changes: 33 additions & 0 deletions src/os/osx/sys-utils.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/***********************************************************************
**
** REBOL [R3] Language Interpreter and Run-time Environment
**
** Copyright 2021 Oldes
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
**
************************************************************************
**
** Title: osx objective-c common code
** Author: Oldes
** Purpose: various common osx functions
**
************************************************************************/

#include "sys-utils.h"

CFURLRef urlFromCString(const char* cString){
NSString *myNSString = [NSString stringWithUTF8String:cString];
NSString *path = [myNSString stringByExpandingTildeInPath];
return CFURLCreateWithFileSystemPath(NULL, (CFStringRef)path, 0, false);
}

0 comments on commit dbe8aa5

Please sign in to comment.