Create image from unsigned char buffer - c

I'm capturing fingerprints using a device called Secugen Pro 20, it has its own SDK for Linux, and i want to capture the fingerprint image and save it as any image format.
They have this typedef unsigned char BYTE;
I declared my imageBuffer
BYTE *CurrentImageBuffer;
Then i allocate memory to it using the devices specs
CurrentImageBuffer = malloc(device_info.ImageWidth*device_info.ImageHeight);
And at some point at my code i capture image and pass CurrentImageBuffer as argument to the capture function:
SGFPM_GetImageEx(m_hFPM, CurrentImageBuffer, GET_IMAGE_TIMEOUT, NULL, GET_IMAGE_DESIRED_QUALITY)
Thats what the variable looks right after this line of code ( i can confirm that it captured a finger):
I just don't understand how to proceed creating an image from this buffer, as it doesn't look like a ByteArray
I don't even know if thats the right place to get my image from, but that looks like the right place because its a buffer, right?.
OBS: I'm new to C

This is a small sample program to write an 8-bit graylevel image into a Windows BMP file:
#include <stdio.h>
typedef unsigned char Byte;
int writeBMPGray8(FILE *f, int w, int h, const Byte *data)
{
unsigned bytesPerRow = (w + 3) & ~3; // align to 4 bytes (requirement)
unsigned size
= 14 // Bitmap file header size
+ 12 // DIB header size
+ 256 * 3; // palette size
unsigned gap = size;
size = (size + 3) & ~3; // align to 4 bytes (requirement)
gap = size - gap; // get size of gap between end of headers and raw data
unsigned offs = size; // store offset of raw data
size += h * bytesPerRow; // bitmap data size in file
/* write Bitmap file header (14 bytes) */
{ const Byte buffer[14] = {
'B', 'M', // magic code
size & 0xff, size >> 8 & 0xff, size >> 16 & 0xff, size >> 24 & 0xff, // size of BMP file in bytes
0, 0, // reserved
0, 0, // reserved
offs & 0xff, offs >> 8 & 0xff, offs >> 16 & 0xff, offs >> 24 & 0xff // starting offset of pixel data
};
if (fwrite(buffer, sizeof buffer, 1, f) != 1) return -1; // ERROR!
}
/* write DIB header (12 bytes) */
{ const Byte buffer[12] = {
12, 0, 0, 0, // size of this header
w & 0xff, w >> 8 & 0xff, // bitmap width in pixels
h & 0xff, h >> 8 & 0xff, // bitmap height in pixels
1, 0, // number of color planes, must be 1
8, 0 // number of bits per pixel
};
if (fwrite(buffer, sizeof buffer, 1, f) != 1) return -1; // ERROR!
}
/* write color palette (3 * 256 bytes) */
for (int i = 0; i < 256; ++i) { // make a gray level palette
Byte buffer[3] = { i, i, i };
if (fwrite(buffer, sizeof buffer, 1, f) != 1) return -1; // ERROR!
}
/* write gap (to align start address of raw data with 4 */
for (int i = 0; i < gap; ++i) {
if (fputc(0, f) < 0) return -1; // ERROR!
}
/* write raw data */
for (int y = 0; y < h; ++y) { // for all rows
int x = 0;
for (; x < w; ++x) { // for all columns
if (fputc(*data++, f) < 0) return -1; // ERROR!
}
// write row padding
for (; x < bytesPerRow; ++x) {
if (fputc(0, f) < 0) return -1; // ERROR!
}
}
/* done */
return 0;
}
int main()
{
/* a sample image 6 x 8, gray level */
enum { w = 6, h = 8 };
const Byte imgRaw[w * h] = {
0x00, 0x30, 0x60, 0x90, 0xc0, 0xf0,
0x02, 0x32, 0x62, 0x92, 0xc2, 0xf2,
0x04, 0x34, 0x64, 0x94, 0xc4, 0xf4,
0x06, 0x36, 0x66, 0x96, 0xc6, 0xf6,
0x08, 0x38, 0x68, 0x98, 0xc8, 0xf8,
0x0a, 0x3a, 0x6a, 0x9a, 0xca, 0xfa,
0x0c, 0x3c, 0x6c, 0x9c, 0xcc, 0xfc,
0x0e, 0x3e, 0x6e, 0x9e, 0xce, 0xfe
};
FILE *f = fopen("test.bmp", "wb");
if (!f) return 1; // ERROR!
if (writeBMPGray8(f, w, h, imgRaw)) return 1; // ERROR!
if (fclose(f)) return 1; // ERROR!
return 0; // success
}
The sample image provides some kind of gradients horizontally and vertically. I've chosen a width of 6 intentionally to check/show that row alignment is done properly.
The implementation is based on the description in Wikipedia BMP file format.
To keep it short, I encoded the simplest format – the ancient BITMAPCOREHEADER of Windows 2.0 and OS/2 1.x. (MS Paint can load this as well as the Windows 10 preview. I tested with GIMP which loaded as well without any complaints.)
This is how it looks in GIMP:

The easiest way to get an image is to make a NetPBM PGM image - see Wikipedia NetPBM page.
So, if your image is say 640 px wide by 480 px tall, you would get a buffer from your SDK with 307,200 bytes and you would write that to a file and check it has the correct length. Call that image.raw.
Now you just need a PGM header, and as your image is greyscale and binary, you need a P5 header.
So, in Terminal you can put a header on:
{ printf "P5\n640 480\n255\n" ; cat image.raw ; } > image.pgm
If you are unfamiliar with that syntax, you can get the same with:
printf "P5\n640 480\n255\n" > image.pgm
cat image.raw >> image.pgm
And you can view that image with feh, gimp, Photoshop etc.
If you want to make it into a BMP, or JPEG, or PNG, use ImageMagick which is installed on most Linux distros and is available for macOS and Windows:
magick image.pgm image.png
or
magick image.pgm image.jpg
If your version of ImageMagick is v6 or older, use convert in place of magick:
convert image.pgm image.png

If you have correctly captured the image in CurrentImageBuffer, you can write this as raw file using the code fragment below:
fp = fopen(rawFileName,"wb");
fwrite (CurrentImageBuffer, sizeof (BYTE) , device_info.ImageHeight*device_info.ImageWidth , fp);
fclose(fp);
As I have used the same environment, I am sending the above fragment from my working codebase. Actually, raw file is later converted to template which is later used for matching / identification and not directly used for viewing etc. Variable rawFileName stores the name of the file as char array (string) where this buffer is stored.

Related

c only first 8 bytes passed to function

I am working on a C module in micropython... if I pass a byte array to a function, only the first 8 bytes make it (according to sizeof). I have to also send in the length, then copy it to access everything in a function.
static void printSomeBytes(char *description, byte *bytes)
{
printf("\r\n%s: ", description);
for (int i = 0; i < sizeof(bytes); ++i )
{
printf("%02X", bytes[i]);
}
}
static void printAllBytes(char *description, byte *bytes, int length)
{
byte copy[length];
memcpy(copy, bytes, length);
printf("\r\n%s: ", description);
for (int i = 0; i < sizeof(copy); ++i )
{
printf("%02X", copy[i]);
}
// this also works without making a copy
//for (int i = 0; i < length; ++i )
//{
// printf("%02X", bytes[i]);
//}
}
byte Kifd[] = { 0x0B, 0x79, 0x52, 0x40, 0xCB, 0x70, 0x49, 0xB0, 0x1C, 0x19, 0xB3, 0x3E, 0x32, 0x80, 0x4F, 0x0B};
printSomeBytes("Kifd", kifd); // prints "Kifd: 0B795240CB7049B0"
printAllBytes("Kifd", kifd, sizeof(kifd)); // prints "Kifd: 0B795240CB7049B01C19B33E32804F0B"
What am I doing wrong / is there a better way to send a pointer to a byte array to a function?
sizeof(bytes) returns you the number of bytes that a pointer to byte will need to be stored in memory. It doesn't return you the number of bytes that the array pointed to by bytes contains.
For that you need to pass that size to the function:
static void printSomeBytes(char *description, byte *bytes, size_t size)
{
printf("\r\n%s: ", description);
for (size_t i = 0; i < size; ++i )
{
printf("%02X", bytes[i]);
}
puts("");
}
edit
I also added puts("") there so that the bytes are printed right away. Note
that printf is buffered and it won't show the output on the screen unless you flush it
(fflush(stdout);) by hand or add a '\n' newline at the end of printf.
puts(string) is equivalent to printf("%s\n", string); but without the
overhead of having to parse the format argument.
end edit
And then call it:
byte Kifd[] = { 0x0B, 0x79, 0x52, 0x40, 0xCB, 0x70, 0x49, 0xB0, 0x1C, 0x19, 0xB3, 0x3E, 0x32, 0x80, 0x4F, 0x0B};
printSomeBytes("Kifd", Kifd, sizeof Kifd / sizeof *Kifd);
Also the correct way of getting the number of elements of an array is:
sizeof array / sizeof *array
I encourage you to use that formula even when you know that the type is 8bit
long. It makes the code more portable.
You've done a poor job of explaining the issue. Are you saying that sizeof(bytes) returns 8?
bytes is a pointer, and sizeof(bytes) is returning the size of that pointer. And pointers may be 8 bytes on your system. That has nothing to do with the number of bytes at the address it points to.
In C, when you get a pointer, there is no way to know how many bytes it points to unless you provide that information as another argument or have a special terminating value in the data.

Print Unicode characters by code

I have an array of uint32_t. Each is value representing a Unicode characters. I want to print the array like a string but I'm not able to get that working.
I tried a lot of different things
typedef struct String {
uint32_t *characters;
unsigned long length;
} WRString;
char* WRStringToString(WRString *wstr){
char *string = malloc(sizeof(char) * wstr->length * 4);
int i = 0;
int j = 0;
for (; i < wstr->length; i++) {
string[j++] = wstr->characters[i];
char byte2 = (char)wstr->characters[i] >> 8;
if (byte2) {
string[j++] = byte2;
char byte3 = (char)wstr->characters[i] >> 16;
if (byte3) {
string[j++] = byte3;
char byte4 = (char)wstr->characters[i] >> 24;
if (byte4) {
string[j++] = byte4;
}
}
}
}
return string;
}
Always with
WRString *string; //Characters are 0xD6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68
I tried:
setlocale(LC_CTYPE,"de_DE.UTF-8");
puts(WRStringToString(string));
Gives \326\377\377\377sterreich.
wprintf(L"%s",WRStringToString(string));
Gives the same as long as no local is set.
Printing UTF-8 strings with printf - wide vs. multibyte string literals and Printing Unicode Character (stored in variables) in C do not really help me.
Any suggestions?
Theses just seem to be unicode code points. Store them in a wchar_t string, one by one, and then print this with
printf("%ls\n", wstring);
You'd have to set the locale right at the start of your program to the default of the system:
set_locale(LC_ALL, "");
Jens Gustedt's answer was a point into the right direction but I keep using uint32_t, because I need to support Unicode's Emojis and wchar_t can be too small for those. (as said above by Remy Lebeau)
This seems to be working perfectly fine:
setlocale(LC_CTYPE,"de_DE.UTF-8");
printf("%ls\n", string->characters);

Initialize C array with struct

Is it possible to initialise an array of uint8_t with a struct?
What I want to achieve is something similar to:
#define BIGGER_THAN_STRUCT 1024
struct Device {
uint32_t address;
uint32_t id;
};
const uint8_t bytes[BIGGER_THAN_STRUCT] = (struct Device) {
.address = 123,
.id = 456,
};
The reason I want to do this it to get an easy overlay view of the content I write to the byte array. I simply want an easy interface to whatever first bytes I need for the information that is displayed by the structure.
If thats not possible, what's the closest thing to it?
The standard way in C to overlay data types is by using unions:
#include <stdio.h>
#include <stdint.h>
#define BIGGER_THAN_STRUCT 1024
struct Device {
uint32_t address;
uint32_t id;
};
union Memory {
uint8_t bytes[BIGGER_THAN_STRUCT];
struct Device devices[BIGGER_THAN_STRUCT/sizeof(struct Device)];
};
const union Memory memory = {
.devices = {
{ .address = 123, .id = 30 },
{ .address = 111, .id = 89 }
}
};
int main(void)
{
unsigned i;
for (i = 0; i < 16; i++)
printf("%d ", memory.bytes[i]);
putchar('\n');
return 0;
}
,
$ ./a
123 0 0 0 30 0 0 0 111 0 0 0 89 0 0 0
Beside approaching this via a union (as proposed by hdante here https://stackoverflow.com/a/27462808/694576) instead of trying:
const uint8_t bytes[BIGGER_THAN_STRUCT] = (struct Device) {
.address = 123,
.id = 456,
};
do quick and dirty:
uint8_t bytes[BIGGER_THAN_STRUCT] = {0};
*((struct Device *) bytes) = ((struct Device) {
.address = 123,
.id = 456,
});
or better do:
struct Device dev = {
.address = 123,
.id = 456,
};
uint8_t bytes[BIGGER_THAN_STRUCT] = {0};
...
size_t size_dev = sizeof dev;
memcpy(bytes, &dev, size_dev);
Then inspect array bytes up to the size_dev - 1th element.
This will do it then
static const uint8_t buffer[BIGGER_THAN_STRUCT] = {
0x7b, 0x00, 0x00, 0x00,
0xc8, 0x01, 0x00, 0x00
};
I think you maybe want to do something like that, even if the copy is not that necessary as b_sample is exactly what you need.
#include <stdio.h>
#include <stdint.h>
typedef struct Device dev;
struct Device {
uint32_t address;
uint32_t id;
};
int main(void) {
//create an instance `sample.address=123` and `sample.id=456`
dev sample = (dev) { 123, 456 };
//convert dev pointer to byte pointer, so you loop through bytes
uint8_t* b_sample = (uint8_t *)(&sample);
//buffer for copy
uint8_t* bytes[1024];
int size = (int)(sizeof(dev)/sizeof(uint8_t)), i;
for(i = 0; i < size; i++) {
bytes[i] = b_sample[i];
//see what values you copy
printf("%x ", bytes[i]);
}
return 0;
}
Demo: http://codepad.org/wE8dbBV1
If you want to divide the struct into uint16_t segments you can safely replace all uint8_t with uint16_t
Usually, when I have to work with bag of structured bytes, I create a "view" struct/class that gives me some higher-level interface to a block of memory. Manual pointer arithmetic is usually too error prone to be repeated. Create a "memory view" structure and unit-test it properly.
struct memory_view {
uint32_t *addr;
uint32_t *id;
};
void view_init(struct memory_view *view, void *buf, size_t bufsz) {
// TODO: validate buffer size using bufsz here
view->addr = (uint32_t*)buf;
view->id = (uint32_t*)(buf + sizeof(uint32_t));
}
struct memory_view view;
uint8_t buffer[LARGE_NUMBER];
view_init(&view, buffer, LARGE_NUMBER);
*view->addr = 0xDEADBEEF;
*view->id = 0xCAFEBABE;
You can see a similar technique in device drivers, when structures are initialized to access different hardware registers located in some memory region.
You could also get a buffer pointer, cast it to structure and try using this memory block as it were a structure. Doable, but memory alignment can bite you hard. Such code may or may not work, depending on compiler and system architecture.
Does this:
#define BIGGER_THAN_STRUCT 1024
struct Device {
uint32_t address;
uint32_t id;
};
struct DeviceAndData {
struct Device d;
char filler[BIGGER_THAN_STRUCT - sizeof(Device)];
};
const struct DeviceAndData bytes_pre = { .d = { .address = 123, .id = 456 } };
const uint8_t* bytes = (uint8_t*)&bytes_pre;
do the trick? :)
There is an alternative to using a uint8_t byte[] array. You can also make use of a struct utilizing a bitfield for each addr and id. You (may/may not) find it more convenient, but it does provide an easy way to keep the offset information associated with any give addr/id pair.
I don't believe there is a way to directly make use of struct type Designated Initializers to fill the uint8_t byte array. I think the closest full initialization would be with memcpy. I've included that in the example below. Note, there is nothing that prevents you from filling the uint8_t byte array with memcpy, but then you have to track the offset within the uint8_t byte array to accurately point to any given byte in either addr or id for any given element. This is where the bitfield makes things a little easier. You get a one-to-one correlation between the struct Device index and the uibitfield index with a1..4 and b1..4 being the bytes within each addr and id, respectively.
A version using the uint8_t array is shown below this version.
Here is a short example with test data in an array of struct Device:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct /* bitfield corresponding to struct Device */
{
unsigned int a1 : 8,
a2 : 8,
a3 : 8,
a4 : 8;
unsigned int b1 : 8,
b2 : 8,
b3 : 8,
b4 : 8;
} uibitfield;
struct Device { /* original struct Device */
uint32_t addr;
uint32_t id;
};
int main () {
/* test data in an array of struct Device */
struct Device dev[] = { {0x4009f0, 0}, {0x4009f1, 1}, {0x4009f2, 2}, {0x4009f3, 3},
{0x4009f4, 4}, {0x4009f5, 5}, {0x4009f6, 6}, {0x4009f7, 7},
{0x4009f8, 8}, {0x4009f9, 9}, {0x4009fa, 10}, {0x4009fb, 11},
{0x4009fc, 12}, {0x4009fd, 13}, {0x4009fe, 14}, {0x4009ff, 15},
{0x400a00, 16}, {0x400a01, 17}, {0x400a02, 18}, {0x400a03, 19} };
int it = 0; /* general iterator */
size_t sz = sizeof (dev)/sizeof (*dev); /* size of array */
/* create validate and fill bitfield array */
uibitfield *bytes = calloc (sz, sizeof (*bytes));
if (!bytes) {
fprintf (stderr, "error: allocation failed.\n");
return 1;
}
memcpy (bytes, dev, sz * sizeof (dev));
/* print bytes in each addr & id in dev */
for (it = 0; it < sz; it++)
printf ("\n addr[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n id[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
it, (bytes + it)->a1, (bytes + it)->a2, (bytes + it)->a3, (bytes + it)->a4,
it, (bytes + it)->b1, (bytes + it)->b2, (bytes + it)->b3, (bytes + it)->b4);
printf ("\n");
return 0;
}
output:
$ ./bin/memview
addr[ 0]: 0xf0, 0x09, 0x40, 0x00
id[ 0]: 0x00, 0x00, 0x00, 0x00
addr[ 1]: 0xf1, 0x09, 0x40, 0x00
id[ 1]: 0x01, 0x00, 0x00, 0x00
addr[ 2]: 0xf2, 0x09, 0x40, 0x00
id[ 2]: 0x02, 0x00, 0x00, 0x00
addr[ 3]: 0xf3, 0x09, 0x40, 0x00
id[ 3]: 0x03, 0x00, 0x00, 0x00
addr[ 4]: 0xf4, 0x09, 0x40, 0x00
id[ 4]: 0x04, 0x00, 0x00, 0x00
(snip)
Note: it was a unclear how you would be using/filling struct Device and how much of an initial peek you wanted at the data in stuct Device, so this is just intended as an example of viewing the data.
using a uint8_t byte array:
If you do want to use the `uint8_t array, the changes needed are minimal:
/* using a uint8_t byte array */
uint8_t *bytearr = calloc (sz * 4, sizeof (*bytearr));
if (!bytearr) {
fprintf (stderr, "error: allocation failed.\n");
return 1;
}
memcpy (bytearr, dev, sz * sizeof (dev));
/* print bytes in each addr & id in dev using uint8_t array */
for (it = 0; it < sz * 4; it+=8)
printf ("\n addr[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n id[%2d]: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
it, bytearr[it], bytearr[it+1], bytearr[it+2], bytearr[it+3],
it, bytearr[it+4], bytearr[it+5], bytearr[it+6], bytearr[it+7]);
output is the same

In a "C" program how can I store a hexadecimal value in a string variable?

I have a program which takes the input data as a plaintext and then decrypts the message using 3DES method in CBC mode. But the values are hardcoded in the program I want to provide the encrypted value myself which should be decryted. How can I do this in the following program?
int main(void)
{
unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE];
unsigned char *e = out;
int len;
DES_cblock key;
DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_key_schedule keysched;
DES_cblock ivec;
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(back, 0, sizeof(back));
RAND_seed(seed, sizeof(DES_cblock));
DES_random_key(&key);
DES_set_odd_parity(&key);
if (DES_set_key_checked((C_Block *)key, &keysched))
{
fprintf(stderr, "ERROR: Unable to set key schedule\n");
exit(1);
}
/* 64 bytes of plaintext */
/* From here, encryption starts for the plaintext below. */
strcpy(in, "Now is the time for all men to stand up and be counted");
printf("Plaintext: [%s]\n", in);
len = strlen(in);
memcpy(ivec, ivsetup, sizeof(ivsetup));
DES_ncbc_encrypt(in, out, len, &keysched, &ivec, DES_ENCRYPT);
printf("Ciphertext:");
while (*e) printf(" [%02x]", *e++);
printf("\n");
/* Till here, encryption is over. After this we have to decrypt
* the value which has been encoded, but I want to remove all this
* part and to provide my own encrypted message, and get the
* proper output.
*/
memcpy(ivec, ivsetup, sizeof(ivsetup));
/* The problem I am facing is how to provide the value properly
* to the parameter "out" and "keysched", which should be of my
* choice. For "out" I want to provide THIS value:
* "2DC39619B4450A8C27A3976C50DE5799".
*/
DES_ncbc_encrypt(out, back, len, &keysched, &ivec, DES_DECRYPT);
printf("Decrypted Text: [%s]\n", back);
exit(0);
}
Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz1uqOp1Yhv
Read C FAQ 20.10. Hexadecimal is a representation. All numbers are stored in binary internally. Your DES_cblock is probably a typedef for an (unsigned, perhaps!) integral type. So, what you have in effect is an array of integers. You can put numbers in decimal, hexadecimal or binary -- but they will all work. Hexadecimal is typically used in cryptography because it has some notational advantages.
I got it done.
I did it in a childish way for the time being but it is working now. I did it like this.
out[0]=0xA0; out[1]=0x69; out[2]=0x57; out[3]=0x3B;
out[4]=0x70; out[5]=0x26; out[6]=0x1C; out[7]=0xE8;
out[8]=0xEF; out[9]=0xF2; out[10]=0x9F;out[11]=0x60;
out[12]=0x80;out[13]=0x60;out[14]=0xB2;out[15]=0xE5;
Later I will do this thing in a for loop.
Create a dump function like this:
hexdump(char *buff, int len) {
int i,tmp;
for(i=0; i < len; i++) {
tmp = buff[i] & 0xff; /** to avoid sign extension */
printf("%02x",tmp);
}
}
And use it.
hexdump(back,len);
If you have to write it in memory, you can use sprintf, but you may have to write your own binary to hex function.
Using the nonstandard itoa function that stores the value it as a string, you can do the following:
char* hexstr = itoa(back,16);
// print out a string
printf("Decrypted Text: [%X]\n", back);

How to generate a file from C-hexvalues?

I have a C-array that looks like this:
char hexc[] = {
0x41, 0x80, 0x7a, 0x39, 0xea, 0x7e, 0x27, 0xfc,
0xe6, 0x45, 0x9c, 0x8b, 0xb5, 0xce, 0xa7, 0x35,
0x5f, 0xf2, 0x43, 0xcf, 0x89, 0xd8, 0x61, 0xec,
0xe7, 0xed, 0x2e, 0x34, 0x45, 0x0c, 0x32, 0xae,
0x71, 0x4f, 0x1c, 0xd8, 0xb5, 0x8c, 0x1e, 0xdd,
0x5d, 0x90, 0xf3, 0xf2, 0xe7, 0xa6, 0x4f, 0xef,
0xec, 0x96, 0xe3, 0xca, 0x8e, 0xeb, 0x64, 0x1d,
0x18, 0xa9, 0x95, 0xec, 0x64, 0x02, 0xf8, 0x26,
};
I knew that behind this hex-representations is a .GIF-file, what is the best way to generate from this hex-values a viewable file again? And how to add the missing GIF-header?
You would just open the file and write to it:
FILE *f = fopen("filename.gif", "wb");
if (!f) return; // or do something else
fwrite(hexc, 1, sizeof(hexc), f);
fclose(f);
Make sure to #include <stdio.h>.
open the file as binary
ofstream outfile ("new.gif",ofstream::binary);
and then write your buffer
outfile.write (hexc, sizeof hexc);
Turbo C DOS code
/****************************************************************************
** This support Compuserve 256 colour GIF87a and GIF89a image up to **
** 320x200 in size. **
****************************************************************************/
//This program requires a stack of at least 19.5K!!
#include "stdio.h"
typedef
struct GIFHeader {
char Signature [7];
unsigned int ScreenWidth, ScreenHeight;
unsigned char Depth, Background, Zero;
};
struct GIFDescriptor {
char Separator;
unsigned int ImageLeft, ImageTop, ImageWidth, ImageHeight;
unsigned char Depth;
};
char far *Screen = (char far *)0xA0000000L;
//For loading from the file
FILE *GIFFile;
unsigned int BPointer;
unsigned char Buffer [257];
//GIF data is stored in blocks of a certain size
unsigned char BlockSize;
//For loading the code
unsigned char CodeSize;
char BitsIn;
unsigned char Temp;
//Coordinates
unsigned int X, Y, tlX, tlY, brX, brY;
//The string table
unsigned int Prefix [4096];
unsigned char Suffix [4096];
//This sets the display to VGA 320x200 in 256 colours
void VGAScreen ()
{
asm {
mov ax, 0x13
int 0x10
}
}
//This resets the display to text mode
void TextScreen ()
{
asm {
mov ax, 0x3
int 0x10
}
}
//This sets a DAC register to a specific Red Green Blue-value
void SetDAC(unsigned char DAC, unsigned char R, unsigned char G, unsigned char B)
{
outportb (0x3C8, DAC);
outportb (0x3C9, R);
outportb (0x3C9, G);
outportb (0x3C9, B);
}
//This sets one pixel on the screen
void PutPixel (unsigned int x, unsigned int y, unsigned char c)
{
Screen [(y << 8) + (y << 6) + x] = c;
}
//Function to read from the buffer
unsigned char LoadByte ()
{
//Read next block}
if (BPointer == BlockSize) {
fread (Buffer, BlockSize + 1, 1, GIFFile);
BPointer = 0;
}
//Return byte
return Buffer [BPointer++];
}
//Procedure to read the next code from the file
unsigned int ReadCode ()
{
int Counter;
unsigned int Code;
Code = 0;
//Read the code, bit by bit
for (Counter = 0; Counter < CodeSize; Counter++) {
//Maybe, a new byte needs to be loaded with a further 8 bits
if (++BitsIn == 9) {
Temp = LoadByte ();
BitsIn = 1;
}
//Add the current bit to the code
if (Temp & 1) Code += 1 << Counter;
Temp >>= 1;
}
return Code;
}
//Procedure to draw a pixel
void NextPixel (unsigned int c)
{
//Actually draw the pixel on screen
PutPixel (X, Y, c & 255);
//Move to next row, if necessary
if (++X == brX) {
X = tlX;
Y++;
}
}
//Local function to output a string. Returns the first character.
unsigned char OutString (unsigned int CurCode)
{
unsigned int OutCount;
unsigned char OutCode [1024];
//If it's a single character, output that
if (CurCode < 256) {
NextPixel (CurCode);
} else {
OutCount = 0;
//Store the string, which ends up in reverse order
do {
OutCode [OutCount++] = Suffix [CurCode];
CurCode = Prefix [CurCode];
} while (CurCode > 255);
//Add the last character
OutCode [OutCount++] = CurCode;
//Output all the string, in the correct order
do {
NextPixel (OutCode [--OutCount]);
} while (OutCount);
}
//Return 1st character
return CurCode;
}
//This actually loads the GIF
void LoadGIF (char *Filename)
{
//For loading from the GIF file
struct GIFHeader Header;
struct GIFDescriptor Descriptor;
//Colour information
unsigned char BitsPerPixel,
NumOfColours;
unsigned int DAC;
unsigned char Palette [256][3];
//For indexing the string table
unsigned int FirstFree, FreeCode;
//All the code information
unsigned char InitCodeSize;
unsigned int Code, OldCode, MaxCode;
//Special codes
unsigned int ClearCode, EOICode;
//Check whether the GIF file exists, and open it
GIFFile = fopen (Filename, "rb");
if (GIFFile == 0) {
TextScreen ();
printf ("Could not open file %s", Filename);
return;
}
//Read header
fread (&Header, 6, 1, GIFFile);
Header.Signature [6] = 0;
fread (&Header.ScreenWidth, sizeof (Header) - 7, 1, GIFFile);
//Check signature and terminator
if ((strcmp (Header.Signature, "GIF87a")
&& strcmp (Header.Signature, "GIF89a"))
|| Header.Zero) {
TextScreen ();
printf ("Not a valid GIF file\n");
return;
}
//Get amount of colours in image
BitsPerPixel = 1 + (Header.Depth & 7);
NumOfColours = (1 << BitsPerPixel) - 1;
//Load global colour map
fread (Palette, 3, (NumOfColours + 1), GIFFile);
for (DAC = 0; DAC <= NumOfColours; DAC++)
SetDAC (DAC, Palette [DAC][0] >> 2,
Palette [DAC][1] >> 2,
Palette [DAC][2] >> 2);
//Load the image descriptor
fread (&Descriptor, sizeof (Descriptor), 1, GIFFile);
if (Descriptor.Separator != ',') {
TextScreen ();
printf ("Incorrect image descriptor.\n");
return;
}
//Get image corner coordinates
tlX = Descriptor.ImageLeft;
tlY = Descriptor.ImageTop;
brX = tlX + Descriptor.ImageWidth;
brY = tlY + Descriptor.ImageHeight;
//Some restrictions apply
if (Descriptor.Depth & 128) {
TextScreen ();
printf ("Local colour maps not supported\n");
return;
}
if (Descriptor.Depth & 64) {
TextScreen ();
printf ("Interlaced images not supported\n");
return;
}
//Get initial code size
fread (&CodeSize, 1, 1, GIFFile);
//GIF data is stored in blocks, so it's necessary to know the size
fread (&BlockSize, 1, 1, GIFFile);
//Start loader
BPointer = BlockSize;
//Special codes used in the GIF spec
ClearCode = 1 << CodeSize; //Code to reset
EOICode = ClearCode + 1; //End of file
//Initialize the string table
FirstFree = ClearCode + 2; //Strings start here
FreeCode = FirstFree; //Strings can be added here
//Initial size of the code and its maximum value
InitCodeSize = ++CodeSize;
MaxCode = 1 << CodeSize;
BitsIn = 8;
//Start at top left of image
X = Descriptor.ImageLeft;
Y = Descriptor.ImageTop;
do {
//Read next code
Code = ReadCode ();
//If it's an End-Of-Information code, stop processing
if (Code == EOICode) break;
//If it's a clear code...
else if (Code == ClearCode) {
//Clear the string table
FreeCode = FirstFree;
//Set the code size to initial values
CodeSize = InitCodeSize;
MaxCode = 1 << CodeSize;
//The next code may be read
Code = ReadCode ();
OldCode = Code;
//Set pixel
NextPixel (Code);
//Other codes
} else {
/*If the code is already in the string table, it's string is displayed,
and the old string followed by the new string's first character is
added to the string table.*/
if (Code < FreeCode)
Suffix [FreeCode] = OutString (Code);
else {
/*If it is not already in the string table, the old string followed by
the old string's first character is added to the string table and
displayed.*/
Suffix [FreeCode] = OutString (OldCode);
NextPixel (Suffix [FreeCode]);
}
//Finish adding to string table
Prefix [FreeCode++] = OldCode;
//If the code size needs to be adjusted, do so
if (FreeCode >= MaxCode && CodeSize < 12) {
CodeSize++;
MaxCode <<= 1;
}
//The current code is now old
OldCode = Code;
}
} while (Code != EOICode);
//Close the GIF file
fclose (GIFFile);
}
void main (int argcount, char *argvalue[])
{
char FileName [80];
//Check if a filename was passed as a parameter, otherwise ask for one
if (argcount > 1) {
strcpy (FileName, argvalue [1]);
} else {
printf ("Enter filename:");
gets (FileName);
}
//Switch to graphics screen
VGAScreen ();
//Load GIF file
LoadGIF (FileName);
//Wait for keypress
getch ();
//Switch back to text mode
TextScreen ();
}

Resources