I lost a couple of hours struggling to find what might be causing my program to not pass the check, but to reveals all the 50 images from the test set. I even compiled else's passing code just to get the correct test images and compared their hexdumps to mine and they were the same. I'm out of ideas and kindly ask if someone could help me.
My code:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
const char FIRST_BYTE = 0xff;
const char SECOND_BYTE = 0xd8;
const char THIRD_BYTE = 0xff;
const char FORTH_BYTE_PARTIAL = 0b11100000;
const int FORTH_BYTE_BITS_TO_COMPARE_NO = 4;
typedef struct MemoryBlock {
char bytes[512];
} MemoryBlock;
bool AreBytesBeginningSame(char first, char second, int numberOfBitsToCompare);
MemoryBlock GetStartingImageMemoryBlock(FILE* pFile);
int main(int argc, char* argv[]) {
FILE* pRaw = fopen(argv[1], "r");
bool isOpened = pRaw != NULL;
if (!isOpened) {
fprintf(stderr, "Can't open raw file\n");
return 1;
}
FILE* pImage = fopen("000.jpg", "w");
bool isCreated = pImage != NULL;
if (!isCreated) {
fprintf(stderr, "Can't create image file\n");
return 1;
}
MemoryBlock startingBlock = GetStartingImageMemoryBlock(pRaw);
fwrite(&startingBlock, sizeof(MemoryBlock), 1, pImage);
int currentImageNo = 0;
while (true) {
MemoryBlock currentBlock;
bool isReadSuccessful = fread(¤tBlock, sizeof(MemoryBlock), 1, pRaw) > 0;
if (isReadSuccessful) {
if ((currentBlock.bytes[0] == FIRST_BYTE) &&
(currentBlock.bytes[1] == SECOND_BYTE) &&
(currentBlock.bytes[2] == THIRD_BYTE) &&
(AreBytesBeginningSame(currentBlock.bytes[3], FORTH_BYTE_PARTIAL, FORTH_BYTE_BITS_TO_COMPARE_NO))) {
//printf("found new image at %li\n", ftell(pRaw) - 512);
fclose(pImage);
++currentImageNo;
char newImageName[10];
sprintf(newImageName, "%03i.jpg", currentImageNo);
pImage = fopen(newImageName, "w");
bool isCreated = pImage != NULL;
if (!isCreated) {
fprintf(stderr, "Can't create image %s\n", newImageName);
return 1;
}
}
fwrite(¤tBlock, sizeof(MemoryBlock), 1, pImage);
continue;
}
else {
fprintf(stderr, feof(pRaw) ? "File end reached!\n" : "File end not reached!\n");
break;
}
}
fclose(pRaw);
fclose(pImage);
return 0;
}
// used to compare bits in a byte (8 bits MAX)
// starts comparing from left side
bool AreBytesBeginningSame(char first, char second, int numberOfBitsToCompare) {
const unsigned int BYTE_SIZE = 7; // because we start from 0
bool isOutOfRange = numberOfBitsToCompare < 1 || numberOfBitsToCompare > 8;
if (isOutOfRange) {
printf("Bit comparisong error: out of range");
exit(1);
}
char cropByte = 0;
for (unsigned int i = 0; i < numberOfBitsToCompare; ++i) {
cropByte |= 1UL << (BYTE_SIZE - i);
}
first &= cropByte;
// printf("First: "BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(first));
second &= cropByte;
// printf("Second: "BYTE_TO_BINARY_PATTERN"\n", BYTE_TO_BINARY(second));
return first == second;
}
MemoryBlock GetStartingImageMemoryBlock(FILE* pFile) {
MemoryBlock block;
do {
fread(&block, sizeof(MemoryBlock), 1, pFile);
} while (block.bytes[0] != FIRST_BYTE);
return block;
}