Taking screenshot using bmp file in c? - c

I'm trying to create a 3D Game using c.
when adding the flag '--save'
The game takes a screenshot and saves it.
so to do this (taking a screenshot from the game).
I have to use BMP file, so I have to make it using c.
The code:
#include "../includes/cub3d.h"
t_screenshot *ft_init_shot(t_mlx *mlx)
{
t_screenshot *takeshot;
takeshot = malloc(1 * sizeof(t_screenshot));
takeshot->width = w;
takeshot->height = h;
takeshot->bitcount = 24;
takeshot->width_in_bytes = ((takeshot->width * takeshot->bitcount + 31) / 32) * 4;
takeshot->imagesize = takeshot->width_in_bytes * takeshot->height;
takeshot->filesize = 54 + takeshot->imagesize;
return (takeshot);
}
unsigned char *ft_bitheader(t_mlx *mlx)
{
unsigned char *header;
uint32_t bisize;
uint32_t bfoffbits;
uint16_t biplanes;
header =(unsigned char *)malloc(54 * sizeof(char));
bisize = 40;
bfoffbits = 54;
biplanes = 1;
memcpy(header, "BM", 2);
memcpy(header + 2 , &mlx->shot->filesize, 4);
memcpy(header + 10, &bfoffbits, 4);
memcpy(header + 14, &bisize, 4);
memcpy(header + 18, &mlx->shot->width, 4);
memcpy(header + 22, &mlx->shot->height, 4);
memcpy(header + 26, &biplanes, 2);
memcpy(header + 28, &mlx->shot->bitcount, 2);
memcpy(header + 34, &mlx->shot->imagesize, 4);
return (header);
}
void screen_shot(t_mlx *mlx)
{
ft_move(mlx);
ft_update(mlx, YES);
mlx->shot = ft_init_shot(mlx);
mlx->shot->header = ft_bitheader(mlx);
screno(mlx);
}
void screno(t_mlx *mlx)
{
int x ;
int y ;
int row;
int col;
x = 0;
y = 0;
row = mlx->shot->height - 1;
col = 0;
unsigned char* buf = malloc(mlx->shot->imagesize);
while (row >= 0)
{
y = 0;
col = 0;
while (col < mlx->shot->width)
{
int red = (mlx->tex.img_data[x * w + y] >> 16) & 0xFF;
int green = (mlx->tex.img_data[x * w + y] >> 8) & 0xFF;
int blue = mlx->tex.img_data[x * w + y] & 0xFF;
buf[row * mlx->shot->width_in_bytes + col * 3 + 0] = blue;
buf[row * mlx->shot->width_in_bytes + col * 3 + 1] = green;
buf[row * mlx->shot->width_in_bytes + col * 3 + 2] = red;
col++;
y++;
}
row--;
x++;
}
ft_printf("Taking ScreenShoot....\n");
FILE *image = fopen("screenshot.bmp", "wb");
ft_printf("ScreenShot Has been saved under The name 'screenshot.bmp']\n");
fwrite(mlx->shot->header, 1, 54, image);
fwrite((char*)buf, 1, mlx->shot->imagesize, image);
fclose(image);
free(buf);
}
The problem is when I compiling This code the image appear some time and some time give me this error:
Thank You for Your help.

Related

my MD5 implementation is giving the wrong result

Ive been trying to solve this issue for hours and hours on end im not completely sure whats making the wrong output obviously its hard to find out because its a hashing algorithm i know my chunking code is incomplete its still a work in progress and ive been programming this for a week
/*
* MD5 Implementation in C
* Created by Caelan Ireland 2023
*/
//#include "MD5.h"
#include <stdint.h> // uint32_t
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <endian.h>
#include <stdint.h> // needed?
// make sure to use -lm tag when compiling with gcc
#include <math.h>
// To Do: Essential Items for Understanding MD5
// 5. Divide up
// 6. Finish ABCD funct
// 4. Padding (Incomplete) incl error checks
// 4 32 bit words called A, B, C and D
#define A 0x67452301
#define B 0xEFCDAB89
#define C 0x98BADCFE
#define D 0x10325476
// remember Let [abcd k s i] ------------------------------------------->>>>>>>
const uint32_t S[64] = {
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
};
//const uint32_t MD[4] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476};
// unsigned int T[64];
// for(int i = 0; i < 64; i++) {
// T[i] = floor(pow(2, 32) * fabs(sin(i + 1))); // fabs fixed wrap or abs? floorf for floats
// printf("0x%08x\n", T[i]); // %u
// };
// precomputed hashes
const uint32_t K[64] = { // T
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define FF(a, b, c, d, k, s, i) \
{ (a) += F((b), (c), (d)) + (k) + (i); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, k, s, i) \
{ (a) += G((b), (c), (d)) + (k) + (i); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, k, s, i) \
{ (a) += H((b), (c), (d)) + (k) + (i); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, k, s, i) \
{ (a) += I((b), (c), (d)) + (k) + (i); \
(a) = ROTATE_LEFT((a), (s)); \
(a) += (b); \
}
// void ToLittleEndian(uint32_t* input) {
// uint32_t tmp = *input;
// *input = ((tmp & 0xff000000) >> 24) | ((tmp & 0x00ff0000) >> 8) |
// ((tmp & 0xff) << 24) | ((tmp & 0x0000ff00) << 8);
// }
uint8_t* ProcessChunk(uint8_t* input)
{
uint32_t AA = A;
uint32_t BB = B;
uint32_t CC = C;
uint32_t DD = D;
uint32_t M[16] = {0};
for(int i = 0; i < 16; i++) {
for(int j = 0; j < 4; j++) {
//word[i] |= (uint32_t)input[(i * 4) + j] << (24 - (j * 8));
M[i] |= (uint32_t)input[(i * 4) + j] << (32 - ((j + 1) * 8));
}
M[i] = htole32(M[i]); // is this necessary?
}
for(int i = 0; i < 16; i++) {
printf("\n word %d = 0x%08x\n", i, M[i]);
}
/* shifting rounds */
for(int i = 0; i < 64; i++) {
// error here
if (i < 16) {
FF(AA, BB, CC, DD, M[i], S[i], K[i]);
//printf("%d, %d, %u\n", M[i], S[i], K[i]);
} else if (i < 32) {
GG(AA, BB, CC, DD, M[(5 * i + 1) % 16], S[i], K[i]);
//printf("%d, %d, %u\n", M[(5 * i + 1) % 16], S[i], K[i]);
} else if (i < 48) {
HH(AA, BB, CC, DD, M[(3 * i + 5) % 16], S[i], K[i]);
//printf("%d, %d, %u\n", M[(3 * i + 5) % 16], S[i], K[i]);
} else {
II(AA, BB, CC, DD, M[(7 * i) % 16], S[i], K[i]);
//printf("%d, %d, %u\n", M[(7 * i) % 16], S[i], K[i]);
}
int Temp = DD;
DD = CC;
CC = BB;
BB = AA;
AA = Temp;
// printf("A = 0x%x\n", A);
// printf("B = 0x%x\n", B);
// printf("C = 0x%x\n", C);
// printf("D = 0x%x\n", D);
// printf("\n");
// printf("AA = 0x%x\n", AA);
// printf("BB = 0x%x\n", BB);
// printf("CC = 0x%x\n", CC);
// printf("DD = 0x%x\n", DD);
// printf("\n");
}
AA += A;
BB += B;
CC += C;
DD += D;
// uint64_t result = ((uint64_t)AA << 96) | ((uint64_t)BB << 64) |
// ((uint64_t)CC << 32) | (uint64_t)D;
uint8_t* digest = malloc(16);
for (int i = 0; i < 16; i++) {
if (i < 4) {
digest[i] = (AA >> (i*8)) & 0xff;
} else if (i < 8) {
digest[i] = (BB >> (i*8)) & 0xff;
} else if (i < 12) {
digest[i] = (CC >> (i*8)) & 0xff;
} else {
digest[i] = (DD >> (i*8)) & 0xff;
}
}
// for (int i = 0; i < 16; i++) {
// printf("%x ", result[i]);
// }
return (uint8_t*)digest;
// print out chunk
// printf("\n\n");
// for(int i = 0; i < 16; i++) {
// printf("0x%x ", M[i]);
// }
}
// abbrivation for print error
int printerr(char* errordesc)
{
printf("Error: %s\n", errordesc);
exit(1);
}
uint8_t* AddPadding(uint8_t* input, size_t input_len)
{
// compute padding length
size_t pad_len = (56 - (input_len) % 64) % 64;
// allocate required space to output buffer
uint8_t* padded = malloc(input_len + pad_len + 8);
if (padded == NULL) {
printerr("padding process cant allocate req memory");
}
// add cmd line string bytes into output
for(int i = 0; i < input_len; i++) { padded[i] = input[i]; }
// add padding bytes
for(int i = 0; i < (pad_len + 8); i++) {
if(i == 0) {
padded[input_len] = 0x80;
} else {
padded[input_len + 1 + i] = 0x00;
}
}
// changing size byte position to 0x80 when utilizing last byte
// add usigned 64 bit input length to end of the string
// if 2^64 only low order of bits are utilised
for(int i = 0; i < (64 / 8); i++) {
padded[input_len + pad_len + i] = (uint8_t)(input_len >> (64 - (i + 1) * 8) & 0xFF);
//padded[input_len + pad_len + i] = (uint8_t)(input_len >> (i * 8) & 0xFF);
}
return padded;
}
int main (int argc, char* argv[])
{
// initalise input var
uint8_t* inputstr = NULL;
if (argc !=3 || strcmp(argv[1], "--inputstr") != 0) {
printerr("usage - MD5 --inputstr (input_string)");
} else {
// point to argv[2] (3rd argument) for buffer
inputstr = (uint8_t*)argv[2];
}
// get str length
const size_t inputstr_len = strlen((char*)inputstr);
// improve later
if (inputstr_len == 0) {
printerr("inputstr < 1 char");
}
// add padding to last chunk
uint8_t* outputstr = AddPadding(inputstr, inputstr_len);
// print padding (probably will delete later)
for (int i = 0; i < inputstr_len + 1 + (64 - ((inputstr_len + 8 + 1) % 64 ) + 8); i++) {
printf("0x%02x ", outputstr[i]);
}
// break message into chunks + 1 compensation for padding
//size_t chunks = (inputstr_len / 64) + ((inputstr_len % 64 > 0) && (inputstr_len % 64 > 56));
uint8_t* chunk_result = NULL;
size_t chunks = (inputstr_len / 64) + 1 + (inputstr_len % 64 > 56);
for(int i = 0; i < chunks; i++) {
// only give req bytes
uint8_t* chunk_input = malloc(64 * sizeof(uint8_t));
for(int j = 0; j < 64; j++) {
chunk_input[j] = outputstr[i * 64 + j];
}
chunk_result = ProcessChunk(chunk_input);
// > 2 chunks??
}
// print chunk data
for (int i = 0; i < 16; i++) {
printf("%02x ", chunk_result[i]);
}
// make sure chunks cant be 0
printf("chunks: %ld\n", chunks);
// deallocate memory
free(outputstr);
free(chunk_result);
// executed sucessfully
exit(0);
}
so i was trying the MD5 hashing result for 'h' and it was
2510c39011c5be704182423e3a695e91
my result was
e0 64 f6 8c 9d de 68 df 1f 4b 11 d8 41 13 6b 77
i apologize i havent made a sorting method yet but by comparing the 0x25 you can tell its not equal
i have found a couple errors hopefully this helps on line 150 i defined them all as B in the macros #define statements i forgot the brackets around the letters

smoothening image boundaries for NxN kernel size

In my open source project ( https://github.com/mmj-the-fighter/GraphicsLabFramework ) i am trying to add a image smoothening box filter for NxN kernel size. I have already implemented the algorithm for 3x3 kernel size. As you can see from the source code below I am not processing the image for edges. Using this logic, for a 5x5 kernel size I have to skip two rows or columns from top, right, bottom and left of the image. So the edges will not be blurred. Is there any other solution.
Here is the code:
/*applying a box filter of size 3x3*/
void blur_image(unsigned char *img, int width, int height)
{
int n = width * height;
int i, j;
int r, g, b;
int x, y;
float v = 1.0 / 9.0;
float kernel[3][3] =
{
{ v, v, v },
{ v, v, v },
{ v, v, v }
};
unsigned char* resimage = (unsigned char *)malloc(width * height * 4 * sizeof(unsigned char));
memcpy(resimage, img, width*height * 4);
for (x = 1; x < width - 1; ++x) {
for (y = 1; y < height - 1; ++y) {
float bs = 0.0;
float gs = 0.0;
float rs = 0.0;
for (i = -1; i <= 1; ++i) {
for (j = -1; j <= 1; ++j){
float weight = (float)kernel[i + 1][j + 1];
unsigned char* buffer = img + width * 4 * (y + j) + (x + i) * 4;
bs += weight * *buffer;
gs += weight * *(buffer + 1);
rs += weight * *(buffer + 2);
}
}
unsigned char* outbuffer = resimage + width * 4 * y + x * 4;
*outbuffer = bs;
*(outbuffer + 1) = gs;
*(outbuffer + 2) = rs;
*(outbuffer + 3) = 255;
}
}
memcpy(img, resimage, width*height * 4);
free(resimage);
}

how can I switch form for loop to while loop in c?

I'm trying to replace my 'for' loop with a 'while' loop but I get a different output.
The for loop:
for(int row = mlx->shot->height - 1; row >= 0; row--)
{
y = 0;
for(int col = 0; col < mlx->shot->width; col++)
{
int red = (mlx->tex.img_data[x * w + y] >> 16) & 0xFF;
int green = (mlx->tex.img_data[x * w + y] >> 8) & 0xFF;
int blue = mlx->tex.img_data[x * w + y] & 0xFF;
buf[row * mlx->shot->width_in_bytes + col * 3 + 0] = blue;
buf[row * mlx->shot->width_in_bytes + col * 3 + 1] = green;
buf[row * mlx->shot->width_in_bytes + col * 3 + 2] = red;
y++;
}
x++;
}
here The output is perfect
My while loop:
int row;
row = mlx->shot->height - 1;
while (row >= 0)
{
y = 0;
col = 0;
while (col < mlx->shot->width)
{
int red = (mlx->tex.img_data[x * w + y] >> 16) & 0xFF;
int green = (mlx->tex.img_data[x * w + y] >> 8) & 0xFF;
int blue = mlx->tex.img_data[x * w + y] & 0xFF;
buf[row * mlx->shot->width_in_bytes + col * 3 + 0] = blue;
buf[row * mlx->shot->width_in_bytes + col * 3 + 1] = green;
buf[row * mlx->shot->width_in_bytes + col * 3 + 2] = red;
col++;
y++;
}
row--;
x++;
}
But here I get an: 1163 segmentation fault
EDIT: The rest of The variables is already declared.
This is The hole Function:
void screno(t_mlx *mlx)
{
int x ;
int y ;
int row;
int col;
x = 0;
y = 0;
row = mlx->shot->height - 1;
col = 0;
unsigned char* buf = malloc(mlx->shot->imagesize);
while (row >= 0)
{
y = 0;
col = 0;
while (col < mlx->shot->width)
{
int red = (mlx->tex.img_data[x * w + y] >> 16) & 0xFF;
int green = (mlx->tex.img_data[x * w + y] >> 8) & 0xFF;
int blue = mlx->tex.img_data[x * w + y] & 0xFF;
buf[row * mlx->shot->width_in_bytes + col * 3 + 0] = blue;
buf[row * mlx->shot->width_in_bytes + col * 3 + 1] = green;
buf[row * mlx->shot->width_in_bytes + col * 3 + 2] = red;
col++;
y++;
}
row--;
x++;
}
/*for(int row = mlx->shot->height - 1; row >= 0; row--)
{
y = 0;
for(int col = 0; col < mlx->shot->width; col++)
{
int red = (mlx->tex.img_data[x * w + y] >> 16) & 0xFF;
int green = (mlx->tex.img_data[x * w + y] >> 8) & 0xFF;
int blue = mlx->tex.img_data[x * w + y] & 0xFF;
buf[row * mlx->shot->width_in_bytes + col * 3 + 0] = blue;
buf[row * mlx->shot->width_in_bytes + col * 3 + 1] = green;
buf[row * mlx->shot->width_in_bytes + col * 3 + 2] = red;
y++;
}
x++;
}*/
ft_printf("Taking ScreenShoot....\n");
FILE *fout = fopen("screenshot.bmp", "wb");
ft_printf("ScreenShot Has been saved under The name 'screenshot.bmp']\n");
fwrite(mlx->shot->header, 1, 54, fout);
fwrite((char*)buf, 1, mlx->shot->imagesize, fout);
fclose(fout);
free(buf);
}
when I use the for loop The code work perfectly fine.
but with the while loop, I get an error or The image saved empty.
Simply add the following line at the beginning:
int row = mlx->shot->height - 1;
you should check for zero values before looping
In this code you don't initialize row. Just declaring a variable leaves the variable with an indetermined content, possibly a very big number and when you use it as an array index like in buf[row * mlx->shot->width_in_bytes + col * 3 + 0], you're accessing the array out of bounds which is undefined behaviour and often results in a segmentation fault.
int row;
while (row >= 0) // row contains an indetermined value here
You need this:
int row = mlx->shot->height - 1;
while (row >= 0)
Generally spoken a for loop is just more or less syntactic sugar for a while loop:
for (x;y;z)
{
...
}
is more or less equivalent to:
x;
while (y)
{
...
z;
}
The variable you want to use in while loop is to be initialized first and then you can use it in the while loop and write the body of your loop then decrement/increment the variable accordingly.
While loop format
initialization;
while(condition)
{
body
decrement/increment variable
}
The variable you want to use in the for loop can be initialized in the loop itself.
For loop format
for(initialization;condition;decrement/increment)
{
body
}
You have just declared the variable you haven't initialized it.
Just change int row; to
int row = mlx->shot->height - 1;

Trying to convert YUV420p to RGBA with C language

I have a video data which is YUV420p(I420). And I'm trying to convert to RGBA with C language, but I don't know which part of my code is wrong, I can't get the right RGBA data.
const void *data = [frameData bytes];
NSInteger numOfPixel = width * height;
NSInteger positionOfV = numOfPixel;
NSInteger positionOfU = numOfPixel * 5 / 4;
uint8_t *rgba = malloc(numOfPixel * 4);
for (uint32_t i = 0; i < height; i ++) {
NSInteger startY = i * width;
NSInteger step = (i/2)*(width/2);
NSInteger startU = positionOfU + step;
NSInteger startV = positionOfV + step;
for (uint32_t j = 0; j < width; j ++) {
NSInteger indexY = startY + j;
NSInteger indexU = startU + j/2;
NSInteger indexV = startV + j/2;
NSInteger index = indexY * 4;
uint8_t Y = *(uint8_t *)(&data[indexY]);
uint8_t U = *(uint8_t *)(&data[indexU]);
uint8_t V = *(uint8_t *)(&data[indexV]);
int r = (int)((Y&0xff) + 1.4075 * ((V&0xff) - 128));
int g = (int)((Y&0xff) - 0.3455 * ((U&0xff)-128) - 0.7169*((V&0xff)-128));
int b = (int)((Y&0xff) + 1.779 * ((U&0xff)-128));
int a = 0xff;
if (r<0) r=0; if (r>255) r=255;
if (g<0) g=0; if (g>255) g=255;
if (b<0) b=0; if (b>255) b=255;
rgba[index] = (uint8_t)r;
rgba[index + 1] = (uint8_t)g;
rgba[index + 2] = (uint8_t)b;
rgba[index + 3] = (uint8_t)a;
}
}

speeding up md5 program

This is a example of md5 in C, but the program is very slow it takes a little over a second to encode a simple string, What is slowing the program down?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
// Constants are the integer part of the sines of integers (in radians) * 2^32.
const uint32_t k[64] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
// r specifies the per-round shift amounts
const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
// leftrotate function definition
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
void to_bytes(uint32_t val, uint8_t *bytes)
{
bytes[0] = (uint8_t) val;
bytes[1] = (uint8_t) (val >> 8);
bytes[2] = (uint8_t) (val >> 16);
bytes[3] = (uint8_t) (val >> 24);
}
uint32_t to_int32(const uint8_t *bytes)
{
return (uint32_t) bytes[0]
| ((uint32_t) bytes[1] << 8)
| ((uint32_t) bytes[2] << 16)
| ((uint32_t) bytes[3] << 24);
}
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {
// These vars will contain the hash
uint32_t h0, h1, h2, h3;
// Message (to prepare)
uint8_t *msg = NULL;
size_t new_len, offset;
uint32_t w[16];
uint32_t a, b, c, d, i, f, g, temp;
// Initialize variables - simple count in nibbles:
h0 = 0x67452301;
h1 = 0xefcdab89;
h2 = 0x98badcfe;
h3 = 0x10325476;
//Pre-processing:
//append "1" bit to message
//append "0" bits until message length in bits ≡ 448 (mod 512)
//append length mod (2^64) to message
for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++)
;
msg = (uint8_t*)malloc(new_len + 8);
memcpy(msg, initial_msg, initial_len);
msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"
for (offset = initial_len + 1; offset < new_len; offset++)
msg[offset] = 0; // append "0" bits
// append the len in bits at the end of the buffer.
to_bytes(initial_len*8, msg + new_len);
// initial_len>>29 == initial_len*8>>32, but avoids overflow.
to_bytes(initial_len>>29, msg + new_len + 4);
// Process the message in successive 512-bit chunks:
//for each 512-bit chunk of message:
for(offset=0; offset<new_len; offset += (512/8)) {
// break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
for (i = 0; i < 16; i++)
w[i] = to_int32(msg + offset + i*4);
// Initialize hash value for this chunk:
a = h0;
b = h1;
c = h2;
d = h3;
// Main loop:
for(i = 0; i<64; i++) {
if (i < 16) {
f = (b & c) | ((~b) & d);
g = i;
} else if (i < 32) {
f = (d & b) | ((~d) & c);
g = (5*i + 1) % 16;
} else if (i < 48) {
f = b ^ c ^ d;
g = (3*i + 5) % 16;
} else {
f = c ^ (b | (~d));
g = (7*i) % 16;
}
temp = d;
d = c;
c = b;
b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);
a = temp;
}
// Add this chunk's hash to result so far:
h0 += a;
h1 += b;
h2 += c;
h3 += d;
}
// cleanup
free(msg);
//var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
to_bytes(h0, digest);
to_bytes(h1, digest + 4);
to_bytes(h2, digest + 8);
to_bytes(h3, digest + 12);
}
int main(int argc, char **argv) {
char *msg = argv[1];
size_t len;
int i;
uint8_t result[16];
if (argc < 2) {
printf("usage: %s 'string'\n", argv[0]);
return 1;
}
len = strlen(msg);
// benchmark
for (i = 0; i < 1000000; i++) {
md5((uint8_t*)msg, len, result);
}
// display result
for (i = 0; i < 16; i++)
printf("%2.2x", result[i]);
puts("");
return 0;
}
I might be missing something, but:
// benchmark
for (i = 0; i < 1000000; i++) {
md5((uint8_t*)msg, len, result);
}
performs the same code one million times? A good idea to get an idea of how efficient it is, but not to actually do any work, efficiently.

Resources