Esempio n. 1
0
void crop_and_flip_image(Buffer* destBuffer, Buffer* sourceBuffer, int offsetX, int offsetY, bool doFlipHorizontal) {

  const Dimensions destDims = destBuffer->_dims;
  const Dimensions sourceDims = sourceBuffer->_dims;
  assert((destDims._length == 3) && (sourceDims._length == 3));

  const int destWidth = destDims[1];
  const int destHeight = destDims[0];
  const int destChannels = destDims[2];

  const int sourceWidth = sourceDims[1];
  const int sourceHeight = sourceDims[0];
  const int sourceChannels = sourceDims[2];
  assert(destChannels == sourceChannels);

  const int sourceEndX = (offsetX + destWidth);
  assert(sourceEndX <= sourceWidth);
  const int sourceEndY = (offsetY + destHeight);
  assert(sourceEndY <= sourceHeight);

  const Dimensions destRowDims = destDims.removeDimensions(1);
  const int destRowElementCount = destRowDims.elementCount();
  const size_t destRowByteCount = (destRowElementCount * sizeof(jpfloat_t));

  jpfloat_t* const destDataStart = destBuffer->_data;
  jpfloat_t* const sourceDataStart = sourceBuffer->_data;

  if (!doFlipHorizontal) {
    for (int destY = 0; destY < destHeight; destY += 1) {
      const int sourceX = offsetX;
      const int sourceY = (destY + offsetY);
      const int sourceOffset = sourceDims.offset(sourceY, sourceX, 0);
      jpfloat_t* const sourceData = (sourceDataStart + sourceOffset);
      const int destOffset = destDims.offset(destY, 0, 0);
      jpfloat_t* const destData = (destDataStart + destOffset);
      memcpy(destData, sourceData, destRowByteCount);
    }
  } else {
    for (int destY = 0; destY < destHeight; destY += 1) {
      const int sourceX = offsetX;
      const int sourceY = (destY + offsetY);
      const int sourceOffset = sourceDims.offset(sourceY, sourceX, 0);
      jpfloat_t* const sourceLeft = (sourceDataStart + sourceOffset);
      const int destOffset = destDims.offset(destY, 0, 0);
      jpfloat_t* const destLeft = (destDataStart + destOffset);
      jpfloat_t* const destRight = (destLeft + destRowElementCount);
      jpfloat_t* destCurrent = destRight;
      jpfloat_t* sourceCurrent = sourceLeft;
      while (destCurrent != destLeft) {
        jpfloat_t* destChannelEnd = (destCurrent + destChannels);
        while (destCurrent < destChannelEnd) {
          *destCurrent = *sourceCurrent;
          destCurrent += 1;
          sourceCurrent += 1;
        }
        destCurrent -= (destChannels * 2);
      }
    }
  }

}
Esempio n. 2
0
void rescale_image_to_fit(Buffer* input, Buffer* output, bool doFlip) {

  const Dimensions inputDims = input->_dims;
  const int inputWidth = inputDims[1];
  const int inputHeight = inputDims[0];
  const int inputChannels = inputDims[2];

  const Dimensions outputDims = output->_dims;
  const int outputWidth = outputDims[1];
  const int outputHeight = outputDims[0];
  const int outputChannels = outputDims[2];

  if ((inputDims == outputDims) && !doFlip) {
    const int elementCount = inputDims.elementCount();
    const size_t bytesInBuffer = (elementCount * sizeof(jpfloat_t));
    memcpy(output->_data, input->_data, bytesInBuffer);
    return;
  }

  const float flipBias = (doFlip) ? inputHeight : 0.0f;
  const float flipScale = (doFlip) ? -1.0f : 1.0f;

  const float scaleX = (inputWidth / (jpfloat_t)(outputWidth));
  const float scaleY = (flipScale * (inputHeight / (jpfloat_t)(outputHeight)));
  const int channelsToWrite = MIN(outputChannels, inputChannels);

  const Dimensions inputRowDims = inputDims.removeDimensions(1);
  const Dimensions outputRowDims = outputDims.removeDimensions(1);

  const jpfloat_t* inputDataStart = input->_data;
  jpfloat_t* const outputDataStart = output->_data;

  for (int outputY = 0; outputY < outputHeight; outputY += 1) {
    const jpfloat_t inputY = (flipBias + (outputY * scaleY));
    const int indexY0 = fmaxf(0.0f, fminf((inputHeight - 1.0f), floorf(inputY)));
    const int indexY1 = fmaxf(0.0f, fminf((inputHeight - 1.0f), ceilf(inputY)));
    const jpfloat_t lerpY = (indexY1 - inputY);
    const jpfloat_t oneMinusLerpY = (1.0f - lerpY);

    const int inputRowY0Offset = inputDims.offset(indexY0, 0, 0);
    const jpfloat_t* const inputRowY0 = (inputDataStart + inputRowY0Offset);
    const int inputRowY1Offset = inputDims.offset(indexY1, 0, 0);
    const jpfloat_t* const inputRowY1 = (inputDataStart + inputRowY1Offset);
    const int outputRowOffset = outputDims.offset(outputY, 0, 0);
    jpfloat_t* const outputRow = (outputDataStart + outputRowOffset);

    for (int outputX = 0; outputX < outputWidth; outputX += 1) {
      const jpfloat_t inputX = (outputX * scaleX);
      const int indexX0 = fmaxf(0.0f, floorf(inputX));
      const int indexX1 = fminf((inputWidth - 1.0f), ceilf(inputX));
      const jpfloat_t lerpX = (indexX1 - inputX);
      const jpfloat_t oneMinusLerpX = (1.0f - lerpX);

      const int indexX0Offset = inputRowDims.offset(indexX0, 0);
      const int indexX1Offset = inputRowDims.offset(indexX1, 0);

      const jpfloat_t* const input00Base = (inputRowY0 + indexX0Offset);
      const jpfloat_t* const input01Base = (inputRowY0 + indexX1Offset);
      const jpfloat_t* const input10Base = (inputRowY1 + indexX0Offset);
      const jpfloat_t* const input11Base = (inputRowY1 + indexX1Offset);

      const int outputOffset = outputRowDims.offset(outputX, 0);
      jpfloat_t* const outputBase = (outputRow + outputOffset);

      for (int channel = 0; channel < outputChannels; channel += 1) {
        jpfloat_t* const outputLocation = (outputBase + channel);
        if (channel >= channelsToWrite) {
          *outputLocation = 0.0f;
        } else {
          const jpfloat_t* input00Location = (input00Base + channel);
          const jpfloat_t* input01Location = (input01Base + channel);
          const jpfloat_t* input10Location = (input10Base + channel);
          const jpfloat_t* input11Location = (input11Base + channel);

          const jpfloat_t input00 = (*input00Location);
          const jpfloat_t input01 = (*input01Location);
          const jpfloat_t input10 = (*input10Location);
          const jpfloat_t input11 = (*input11Location);

          const jpfloat_t yInterp0 = ((input00 * lerpY) + (input10 * oneMinusLerpY));
          const jpfloat_t yInterp1 = ((input01 * lerpY) + (input11 * oneMinusLerpY));
          const jpfloat_t interp = ((yInterp0 * lerpX) + (yInterp1 * oneMinusLerpX));
          *outputLocation = interp;
        }
      }

    }
  }
}