int stackBlurComponent(float* radius, unsigned char* srcComponent, int* width, int* height, unsigned char* dstComponent) { int size = (*width) * (*height); unsigned char* srcComponentCopy; int returnCode = newUnsignedCharArray(size, &srcComponentCopy); if (returnCode != MEMORY_OK) { return returnCode; } int i; memcpy(srcComponentCopy, srcComponent, size); for (i = 3; i--; ) { //horizontal pass returnCode = fastBlurComponent((int)(*radius), srcComponentCopy, *width, *height, dstComponent); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&srcComponentCopy); return returnCode; } //vertical pass returnCode = fastBlurComponent((int)(*radius), dstComponent, *height, *width, srcComponentCopy); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&srcComponentCopy); return returnCode; } } memcpy(dstComponent, srcComponentCopy, size); freeUnsignedCharArray(&srcComponentCopy); return MEMORY_OK; }
void deleteBitmap(Bitmap* bitmap) { freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); freeUnsignedCharArray(&(*bitmap).transformList.transforms); (*bitmap).transformList.size = 0; (*bitmap).width = 0; (*bitmap).height = 0; }
int stackBlur(float* radius, unsigned char* srcRed, unsigned char* srcGreen, unsigned char* srcBlue, int* width, int* height, unsigned char* dstRed, unsigned char* dstGreen, unsigned char* dstBlue) { unsigned int size = (*width) * (*height); unsigned char* srcComponentCopy; int returnCode = newUnsignedCharArray(size, &srcComponentCopy); if (returnCode != MEMORY_OK) { return returnCode; } unsigned int i, c; unsigned char* srcComponent; unsigned char* dstComponent; for (c = 3; c--; ) { if (c == 0) { srcComponent = srcRed; dstComponent = dstRed; } else if (c == 1) { srcComponent = srcGreen; dstComponent = dstGreen; } else { srcComponent = srcBlue; dstComponent = dstBlue; } memcpy(srcComponentCopy, srcComponent, size); for (i = 3; i--; ) { //horizontal pass returnCode = fastBlurComponent((int)(*radius), srcComponentCopy, *width, *height, dstComponent); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&srcComponentCopy); return returnCode; } //vertical pass returnCode = fastBlurComponent((int)(*radius), dstComponent, *height, *width, srcComponentCopy); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&srcComponentCopy); return returnCode; } } memcpy(dstComponent, srcComponentCopy, size); } freeUnsignedCharArray(&srcComponentCopy); return MEMORY_OK; }
int resizeChannel(unsigned char** channelPixels, int srcWidth, int srcHeight, int maxWidth, int maxHeight) { // Resize channel if (srcWidth > maxWidth && srcHeight > maxHeight) { unsigned char* scaledPixels; int returnCode = newUnsignedCharArray(maxWidth * maxHeight, &scaledPixels); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&scaledPixels); return returnCode; } returnCode = resizeChannelBicubic(*channelPixels, srcWidth, srcHeight, scaledPixels, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&scaledPixels); return returnCode; } //No need for hi-res channel so free the memory freeUnsignedCharArray(channelPixels); //channelPixels is already a pointer to a pointer *channelPixels = scaledPixels; } return MEMORY_OK; }
int Java_editimage_fliter_PhotoProcessing_nativeResizeBitmap(JNIEnv *env, jobject thiz, jint newWidth, jint newHeight) { unsigned char* newRed; int resultCode = newUnsignedCharArray(newWidth*newHeight, &newRed); if (resultCode != MEMORY_OK) { return resultCode; } resizeChannelBicubic(bitmap.red, bitmap.width, bitmap.height, newRed, (int)newWidth, (int)newHeight); freeUnsignedCharArray(&bitmap.red); bitmap.red = newRed; bitmap.redWidth = newWidth; bitmap.redHeight = newHeight; unsigned char* newGreen; resultCode = newUnsignedCharArray(newWidth*newHeight, &newGreen); if (resultCode != MEMORY_OK) { return resultCode; } resizeChannelBicubic(bitmap.green, bitmap.width, bitmap.height, newGreen, (int)newWidth, (int)newHeight); freeUnsignedCharArray(&bitmap.green); bitmap.green = newGreen; bitmap.greenWidth = newWidth; bitmap.greenHeight = newHeight; unsigned char* newBlue; resultCode = newUnsignedCharArray(newWidth*newHeight, &newBlue); if (resultCode != MEMORY_OK) { return resultCode; } resizeChannelBicubic(bitmap.blue, bitmap.width, bitmap.height, newBlue, (int)newWidth, (int)newHeight); freeUnsignedCharArray(&bitmap.blue); bitmap.blue = newBlue; bitmap.blueWidth = newWidth; bitmap.blueHeight = newHeight; bitmap.width = newWidth; bitmap.height = newHeight; }
//TODO memory usage may be reduced by using component based blur int applyHDR(Bitmap* bitmap) { //Cache to local variables unsigned char* red = (*bitmap).red; unsigned char* green = (*bitmap).green; unsigned char* blue = (*bitmap).blue; unsigned char* blurRed; unsigned char* blurGreen; unsigned char* blurBlue; int length = (*bitmap).width * (*bitmap).height; int resultCode = newUnsignedCharArray(length, &blurRed); if (resultCode != MEMORY_OK) { return resultCode; } resultCode = newUnsignedCharArray(length, &blurGreen); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); return resultCode; } resultCode = newUnsignedCharArray(length, &blurBlue); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); return resultCode; } float blurRadius = 9.0f; resultCode = stackBlur(&blurRadius, red, green, blue, &((*bitmap).width), &((*bitmap).height), blurRed, blurGreen, blurBlue); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); freeUnsignedCharArray(&blurBlue); return resultCode; } unsigned int i, j; unsigned char r1, g1, b1, r2, g2, b2; float matrix[4][4]; identMatrix(matrix); float saturation = 1.3f; saturateMatrix(matrix, &saturation); for (i = length; i--;) { // invert the blurred pixel r1 = 255 - blurRed[i]; g1 = 255 - blurGreen[i]; b1 = 255 - blurBlue[i]; // Grain merge the inverted blurred pixel with the original r1 = grainMergePixelsComponent(r1, red[i]); g1 = grainMergePixelsComponent(g1, green[i]); b1 = grainMergePixelsComponent(b1, blue[i]); // boost the saturation of the original pixel //HSBColour hsb; //rgbToHsb(red[i], green[i], blue[i], &hsb); //hsb.s = min(1.0f, hsb.s * 1.3f); r2 = red[i]; g2 = green[i]; b2 = blue[i]; applyMatrixToPixel(&r2, &g2, &b2, matrix); //hsbToRgb(&hsb, &r2, &g2, &b2); // grain merge the saturated pixel with the inverted grain merged pixel red[i] = grainMergePixelsComponent(r2, r1); green[i] = grainMergePixelsComponent(g2, g1); blue[i] = grainMergePixelsComponent(b2, g1); } applyMatrix(bitmap, matrix); freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); freeUnsignedCharArray(&blurBlue); return MEMORY_OK; }
int applySahara(Bitmap* bitmap) { int length = (*bitmap).width * (*bitmap).height; int i; unsigned char r, g, b; //HSBColour hsb; unsigned char* red = (*bitmap).red; unsigned char* green = (*bitmap).green; unsigned char* blue = (*bitmap).blue; unsigned char brightnessLut[256]; unsigned char contrastLut[256]; for (i = 0; i < 256; i++) { float pixelf = i/255.0f; //brightnessLut[i] = 255*applyBrightnessToPixelComponent(pixelf, 0.35433f); //contrastLut[i] = 255*applyContrastToPixelComponent(pixelf, 0.1496f); brightnessLut[i] = 255*applyBrightnessToPixelComponent(pixelf, 0.45f); contrastLut[i] = 255*applyContrastToPixelComponent(pixelf, 0.1f); } for (i = length; i--; ) { r = brightnessLut[red[i]]; g = brightnessLut[green[i]]; b = brightnessLut[blue[i]]; r = contrastLut[r]; green[i] = contrastLut[g]; b = contrastLut[b]; red[i] = (r*0.8431f/*215*/)+40; //compress the red channel between 18 - 237 blue[i] = (b*0.8823f/*225*/)+30; //compress the blue channel between 50 - 205 //rgbToHsb(red[i], green[i], blue[i], &hsb); //hsb.s = hsb.s * 0.55f; //hsbToRgb(&hsb, &red[i], &green[i], &blue[i]); } float matrix[4][4]; identMatrix(matrix); float saturation = 0.65f; saturateMatrix(matrix, &saturation); applyMatrix(bitmap, matrix); unsigned char* blurRed; unsigned char* blurGreen; unsigned char* blurBlue; int resultCode = newUnsignedCharArray(length, &blurRed); if (resultCode != MEMORY_OK) { return resultCode; } resultCode = newUnsignedCharArray(length, &blurGreen); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); return resultCode; } resultCode = newUnsignedCharArray(length, &blurBlue); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); return resultCode; } float blurRadius = 1.0f; resultCode = stackBlur(&blurRadius, (*bitmap).red, (*bitmap).green, (*bitmap).blue, &((*bitmap).width), &((*bitmap).height), blurRed, blurGreen, blurBlue); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); freeUnsignedCharArray(&blurBlue); return resultCode; } short int overlayLut[256][256]; unsigned char multiplyLut255[256]; unsigned char multiplyLut227[256]; unsigned char multiplyLut187[256]; unsigned int j; for (i = 0; i < 256; i++) { for (j = 0; j < 256; j++) { overlayLut[i][j] = -1;//overlayPixelComponents(i, j, 1.0f); } multiplyLut255[i] = multiplyPixelComponents(255, i); multiplyLut227[i] = multiplyPixelComponents(227, i); multiplyLut187[i] = multiplyPixelComponents(187, i); } for (i = length; i--; ) { if (overlayLut[blurRed[i]][red[i]] == -1) { overlayLut[blurRed[i]][red[i]] = overlayPixelComponents(blurRed[i], red[i], 1.0f); } red[i] = overlayLut[blurRed[i]][red[i]];//overlayPixelComponents(blurRed[i], red[i], 1.0f); if (overlayLut[blurGreen[i]][green[i]] == -1) { overlayLut[blurGreen[i]][green[i]] = overlayPixelComponents(blurGreen[i], green[i], 1.0f); } green[i] = overlayLut[blurGreen[i]][green[i]];//overlayPixelComponents(blurGreen[i], green[i], 1.0f); if (overlayLut[blurBlue[i]][blue[i]] == -1) { overlayLut[blurBlue[i]][blue[i]] = overlayPixelComponents(blurBlue[i], blue[i], 1.0f); } blue[i] = overlayLut[blurBlue[i]][blue[i]];//overlayPixelComponents(blurBlue[i], blue[i], 1.0f); // Multiply by a wheat colour rgb(255, 227, 187) red[i] = multiplyLut255[red[i]];//multiplyPixelComponents(255, red[i]); green[i] = multiplyLut227[green[i]];//multiplyPixelComponents(227, green[i]); blue[i] = multiplyLut187[blue[i]];//multiplyPixelComponents(187, blue[i]); } freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); freeUnsignedCharArray(&blurBlue); return MEMORY_OK; }
// amount is 0.0 to 1.0 // threshold is 0 to 255 int unsharpMask(Bitmap* bitmap, int radius, float amount, int threshold) { unsigned char* red = (*bitmap).red; unsigned char* green = (*bitmap).green; unsigned char* blue = (*bitmap).blue; unsigned int length = (*bitmap).width * (*bitmap).height; // Create blur unsigned char* blurRed; unsigned char* blurGreen; unsigned char* blurBlue; int resultCode = newUnsignedCharArray(length, &blurRed); if (resultCode != MEMORY_OK) { return resultCode; } resultCode = newUnsignedCharArray(length, &blurGreen); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); return resultCode; } resultCode = newUnsignedCharArray(length, &blurBlue); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); return resultCode; } float blurRadius = radius/3.0f; resultCode = stackBlur(&blurRadius, (*bitmap).red, (*bitmap).green, (*bitmap).blue, &((*bitmap).width), &((*bitmap).height), blurRed, blurGreen, blurBlue); if (resultCode != MEMORY_OK) { freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); freeUnsignedCharArray(&blurBlue); return resultCode; } int i, j; short int lut[256][256]; float a = (4 * amount) + 1; for (i = 0; i < 256; i++) { for (j = 0; j < 256; j++) { lut[i][j] = -1;//clampComponent((int) (a * (i - j) + j)); } } for (i = length; i--;) { int r1 = red[i]; int g1 = green[i]; int b1 = blue[i]; int r2 = blurRed[i]; int g2 = blurGreen[i]; int b2 = blurBlue[i]; if (fabs(r1 - r2) >= threshold) { if (lut[r1][r2] == -1) { lut[r1][r2] = clampComponent((int) ((a + 1) * (r1 - r2) + r2)); } r1 = lut[r1][r2]; //clampComponent((int) ((a + 1) * (r1 - r2) + r2)); } if (fabs(g1 - g2) >= threshold) { if (lut[g1][g2] == -1) { lut[g1][g2] = clampComponent((int) ((a + 1) * (g1 - g2) + g2)); } g1 = lut[g1][g2]; //clampComponent((int) ((a + 1) * (g1 - g2) + g2)); } if (fabs(b1 - b2) >= threshold) { if (lut[b1][b2] == -1) { lut[b1][b2] = clampComponent((int) ((a + 1) * (b1 - b2) + b2)); } b1 = lut[b1][b2]; //clampComponent((int) ((a + 1) * (b1 - b2) + b2)); } red[i] = r1; green[i] = g1; blue[i] = b1; } freeUnsignedCharArray(&blurRed); freeUnsignedCharArray(&blurGreen); freeUnsignedCharArray(&blurBlue); }
int decodeJpegData(char* jpegData, int jpegSize, int maxPixels, Bitmap* bitmap) { int returnCode; int maxWidth; int maxHeight; // Decode red channel returnCode = decodeJpegChannel(jpegData, jpegSize, 0, &(*bitmap).red, &(*bitmap).redWidth, &(*bitmap).redHeight); if (returnCode != MEMORY_OK) { LOGE("Failed to decode red channel"); njDone(); freeUnsignedCharArray(&(*bitmap).red); return returnCode; } doTransforms(bitmap, 1, 0, 0); // Resize red channel getScaledSize((*bitmap).redWidth, (*bitmap).redHeight, maxPixels, &maxWidth, &maxHeight); //We only need to do this once as r, g, b should be the same sizes returnCode = resizeChannel(&(*bitmap).red, (*bitmap).redWidth, (*bitmap).redHeight, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { njDone(); freeUnsignedCharArray(&(*bitmap).red); return returnCode; } // Set red channel dimensions if ((*bitmap).redWidth >= maxWidth && (*bitmap).redHeight >= maxHeight) { (*bitmap).redWidth = maxWidth; (*bitmap).redHeight = maxHeight; } // Decode green channel returnCode = decodeJpegChannel(jpegData, jpegSize, 1, &(*bitmap).green, &(*bitmap).greenWidth, &(*bitmap).greenHeight); if (returnCode != MEMORY_OK) { LOGE("Failed to decode green channel"); njDone(); freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); return returnCode; } doTransforms(bitmap, 0, 1, 0); // Resize green channel returnCode = resizeChannel(&(*bitmap).green, (*bitmap).greenWidth, (*bitmap).greenHeight, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { njDone(); freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); return returnCode; } // Set green channel dimensions if ((*bitmap).greenWidth >= maxWidth && (*bitmap).greenHeight >= maxHeight) { (*bitmap).greenWidth = maxWidth; (*bitmap).greenHeight = maxHeight; } // Decode blue channel returnCode = decodeJpegChannel(jpegData, jpegSize, 2, &(*bitmap).blue, &(*bitmap).blueWidth, &(*bitmap).blueHeight); if (returnCode != MEMORY_OK) { LOGE("Failed to decode blue channel"); njDone(); freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); return returnCode; } doTransforms(bitmap, 0, 0, 1); // Resize blue channel returnCode = resizeChannel(&(*bitmap).blue, (*bitmap).blueWidth, (*bitmap).blueHeight, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { njDone(); freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); return returnCode; } // Set blue channel dimensions if ((*bitmap).blueWidth >= maxWidth && (*bitmap).blueHeight >= maxHeight) { (*bitmap).blueWidth = maxWidth; (*bitmap).blueHeight = maxHeight; } // Set the final bitmap dimensions if ((*bitmap).redWidth == (*bitmap).greenWidth && (*bitmap).redWidth == (*bitmap).blueWidth && (*bitmap).redHeight == (*bitmap).greenHeight && (*bitmap).redHeight == (*bitmap).blueHeight) { (*bitmap).width = (*bitmap).redWidth; (*bitmap).height = (*bitmap).redHeight; } else { njDone(); freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); return INCONSISTENT_BITMAP_ERROR; } njDoneLeaveRGBData(); return MEMORY_OK; }
int resizeChannelBicubic(const unsigned char *src, int srcWidth, int srcHeight, unsigned char *dst, int dstWidth, int dstHeight) { unsigned char *xVector; int i, nextCol, nextRow, numRows, ty, x, y; double factor, *s, *scanline, *scaleScanline, *t, xScale, xSpan, yScale, ySpan, *yVector; factor = (double) dstWidth / (double) srcWidth; if (dst == NULL) { return -1; } /* No scaling needed. */ if (srcWidth == dstWidth) { memcpy(dst, src, srcWidth * srcHeight); return 0; } int returnCode = newUnsignedCharArray(srcWidth, &xVector); if (returnCode != MEMORY_OK) { return returnCode; } returnCode = newDoubleArray(srcWidth, &yVector); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&xVector); return returnCode; } returnCode = newDoubleArray(srcWidth, &scanline); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&xVector); freeDoubleArray(&yVector); return returnCode; } returnCode = newDoubleArray((dstWidth + 1), &scaleScanline); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&xVector); freeDoubleArray(&yVector); freeDoubleArray(&scanline); return returnCode; } numRows = 0; nextRow = 1; ySpan = 1.0; yScale = factor; i = 0; for (y = 0; y < dstHeight; y++) { ty = y * dstWidth; memset(yVector, 0, srcWidth * sizeof(double)); memset(scaleScanline, 0, dstWidth * sizeof(double)); /* Scale Y-dimension. */ while (yScale < ySpan) { if (nextRow && numRows < srcHeight) { /* Read a new scanline. */ memcpy(xVector, src, srcWidth); src += srcWidth; numRows++; } for (x = 0; x < srcWidth; x++) { yVector[x] += yScale * (double) xVector[x]; } ySpan -= yScale; yScale = factor; nextRow = 1; } if (nextRow && numRows < srcHeight) { /* Read a new scanline. */ memcpy(xVector, src, srcWidth); src += srcWidth; numRows++; nextRow = 0; } s = scanline; for (x = 0; x < srcWidth; x++) { yVector[x] += ySpan * (double) xVector[x]; *s = yVector[x]; s++; } yScale -= ySpan; if (yScale <= 0) { yScale = factor; nextRow = 1; } ySpan = 1.0; nextCol = 0; xSpan = 1.0; s = scanline; t = scaleScanline; /* Scale X dimension. */ for (x = 0; x < srcWidth; x++) { xScale = factor; while (xScale >= xSpan) { if (nextCol) { t++; } t[0] += xSpan * s[0]; xScale -= xSpan; xSpan = 1.0; nextCol = 1; } if (xScale > 0) { if (nextCol) { nextCol = 0; t++; } t[0] += xScale * s[0]; xSpan -= xScale; } s++; } /* Copy scanline to target. */ t = scaleScanline; for (x = 0; x < dstWidth; x++) { dst[ty + x] = (unsigned char) t[x]; } } freeUnsignedCharArray(&xVector); freeDoubleArray(&yVector); freeDoubleArray(&scanline); freeDoubleArray(&scaleScanline); return MEMORY_OK; }
int decodeResizeImage(char const *filename, int maxPixels, Bitmap* bitmap) { LOGI("decodeResizeImage. START"); int returnCode; int maxWidth; int maxHeight; // Decode Image returnCode = decodeImage(filename, bitmap); if (returnCode != MEMORY_OK) { LOGE("Failed to decode image"); freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); return returnCode; } LOGI("decodeResizeImage. IMAGE DECODED"); doTransforms(bitmap, 1, 0, 0); // Resize red channel getScaledSize((*bitmap).redWidth, (*bitmap).redHeight, maxPixels, &maxWidth, &maxHeight); //We only need to do this once as r, g, b should be the same sizes returnCode = resizeChannel(&(*bitmap).red, (*bitmap).redWidth, (*bitmap).redHeight, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&(*bitmap).red); return returnCode; } // Set red channel dimensions if ((*bitmap).redWidth >= maxWidth && (*bitmap).redHeight >= maxHeight) { (*bitmap).redWidth = maxWidth; (*bitmap).redHeight = maxHeight; } LOGI("decodeResizeImage. RED COMPLETE"); /** * GREEN CHANNEL */ doTransforms(bitmap, 0, 1, 0); // Resize green channel returnCode = resizeChannel(&(*bitmap).green, (*bitmap).greenWidth, (*bitmap).greenHeight, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); return returnCode; } // Set green channel dimensions if ((*bitmap).greenWidth >= maxWidth && (*bitmap).greenHeight >= maxHeight) { (*bitmap).greenWidth = maxWidth; (*bitmap).greenHeight = maxHeight; } LOGI("decodeResizeImage. GREEN COMPLETE"); /** * BLUE CHANNEL */ doTransforms(bitmap, 0, 0, 1); // Resize blue channel returnCode = resizeChannel(&(*bitmap).blue, (*bitmap).blueWidth, (*bitmap).blueHeight, maxWidth, maxHeight); if (returnCode != MEMORY_OK) { freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); return returnCode; } // Set blue channel dimensions if ((*bitmap).blueWidth >= maxWidth && (*bitmap).blueHeight >= maxHeight) { (*bitmap).blueWidth = maxWidth; (*bitmap).blueHeight = maxHeight; } LOGI("decodeResizeImage. BLUE COMPLETE"); // Set the final bitmap dimensions if ((*bitmap).redWidth == (*bitmap).greenWidth && (*bitmap).redWidth == (*bitmap).blueWidth && (*bitmap).redHeight == (*bitmap).greenHeight && (*bitmap).redHeight == (*bitmap).blueHeight) { (*bitmap).width = (*bitmap).redWidth; (*bitmap).height = (*bitmap).redHeight; } else { freeUnsignedCharArray(&(*bitmap).red); freeUnsignedCharArray(&(*bitmap).green); freeUnsignedCharArray(&(*bitmap).blue); return INCONSISTENT_BITMAP_ERROR; } LOGI("decodeResizeImage. FINISHED"); return MEMORY_OK; }