To convert JPEG file, C function, bgraToGrayscale is called from Swift.
Is there a better way to
1.allocate memory and
2.access pointers
than the ways they have been done in code below?
And maybe things that have been completely missed, like freeing memory?
converter.swift
func BGRAToGrayscale(srcImg: CGImage) -> CGImage {
let BytesPerPixel = 4
guard let srcProv = srcImg.dataProvider else { fatalError("dataProvider is nil") }
guard let srcProvData = srcProv.data else { fatalError("dataProvider.data is nil") }
let srcPtr = CFDataGetBytePtr(srcProvData)
let srcSize = srcImg.width * srcImg.height * BytesPerPixel
var destPtr = [CUnsignedChar](repeating: 0, count: srcSize)
bgraToGrayscale(&destPtr, srcPtr, Int32(srcImg.width), Int32(srcImg.height))
let destCgContext = CGContext(data: &destPtr,
width: srcImg.width, height: srcImg.height,
bitsPerComponent: srcImg.bitsPerComponent,
bytesPerRow: srcImg.bytesPerRow,
space: srcImg.colorSpace!,
bitmapInfo: srcImg.bitmapInfo.rawValue)
guard let destImg = destCgContext?.makeImage() else {
fatalError("Destination Image is nil")
}
return destImg
}
converter.c (slow way of converting to grayscale, will write assembly code for this, just for the sake of learning :-) )
void bgraToGrayscale( unsigned char * __restrict dest, const unsigned char* src, int width, int height ) {
int BYTES_PER_PIXEL = 4;
int numPixels = width * height;
for( int idx=0; idx < numPixels; idx++ ) {
float weight = ((float)src[0]) * 0.11 +
((float)src[1]) * 0.59 +
((float)src[2]) * 0.3;
dest[0] = (int)weight;
dest[1] = (int)weight;
dest[2] = (int)weight;
dest[3] = src[3];
dest += BYTES_PER_PIXEL;
src += BYTES_PER_PIXEL;
}
}
1 Answer 1
// Not following Swift naming conventions, should be bytesPerPixel
let BytesPerPixel = 4
// Better to make function throwable and throw specific error.
guard let srcProv = srcImg.dataProvider else { fatalError("dataProvider is nil") }
guard let srcProvData = srcProv.data else { fatalError("dataProvider.data is nil") }
For unwrap of srcImg.colorSpace!
is not good solution, I would recommend to use guard ... else
and throw an exception if value is nil.
Overall: why you are using abbreviations and shortcuts for every variable/constant name? It is much harder to read such code
-
\$\begingroup\$ trying to write relatively concise code, which why there are some abbreviations like src and dest, and prov. It is harder to read for the first time, i agree. \$\endgroup\$Lydon Ch– Lydon Ch2020年01月09日 09:24:49 +00:00Commented Jan 9, 2020 at 9:24
bgraToGrayScale()
, so there's nothing to worry about. Unless you want this function to allocate memory for the converted image and return a pointer to that new image? \$\endgroup\$assert(int(255f*.11+255f*.59+255f*.3) < 256)
. (hm,==255
?)) \$\endgroup\$