Cairo load image from data - c

I have a doubt with cairo library.
I downloaded an image and I put it into a buffer memory. Is there any solution in cairo to load an image from data that there is in memory?
Thanks

Give a look to cairo_image_surface_create_for_data.

You can load image data from memory, but you need to lay out that memory in the correct format that Cairo expects.
For what you describe, it's probably easier to save the data in a tmpfile and let Cairo load it using FILE operations. Cairo recognizes more formats as filetypes than it does as in-memory structures.
When I used cairo_image_surface_create_for_data for bitmaps, I had to convert my byte-oriented Big-endian bitmap data into 32bit-word-oriented Little-endian rows.
You can tell from the littering of comments, that at times my efforts were reduced to hunt-and-peck, trial-and-error methods. But I got the desired output with this code. Steal from it what you can.
One more thing: The documentation for the in-memory formats (A8, RGB24, ARGB32) is in the .header files, not the reference manual.
enum { BIG, LITTLE } endian = LITTLE;
inline unsigned char reverse(unsigned char b) {
return (b&1 ? 0x80: 0)
| (b&2 ? 0x40: 0)
| (b&4 ? 0x20: 0)
| (b&8 ? 0x10: 0)
| (b&0x10 ? 8: 0)
| (b&0x20 ? 4: 0)
| (b&0x40 ? 2: 0)
| (b&0x80 ? 1: 0);
}
inline unsigned long wreverse(unsigned long w) {
return ( ( w &0xFF) << 24)
| ( ((w>>8) &0xFF) << 16)
| ( ((w>>16)&0xFF) << 8)
| ( ((w>>24)&0xFF) );
}
unsigned char abit[2] = { 0, 0xFF };
unsigned char aspeck[4] = { 0, 0x55, 0xAA, 0xFF };
unsigned char anibble[16] = { 0, 36, 72, 108, 144, 180, 216, 255 };
unsigned char *amap[] = { abit, aspeck, anibble };
void drawimage(state *st, int wid, int hgt, int bits, unsigned char *samp, unsigned char *tmap) {
int stride;
//stride = cairo_format_stride_for_width(CAIRO_FORMAT_A8, wid);
stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wid);
//stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, wid);
int n;
//unsigned char data[n=stride*hgt];
unsigned char data[n=stride*hgt*4];
memset(data, 0, n);
//unsigned char *data; data = calloc(n=stride*hgt, 1);
unsigned long *ldata = (void *)data;
int spo = 8/bits; /* samples per octet */
int span = wid/spo + (wid%spo?1:0); /* byte width */
int i,j;
for (i=0; i < hgt; i++) {
for (j=0; j < wid; j++) {
unsigned char t;
/*if (bits==8) t = samp[i*span + j/spo];
else*/ t = ( ( samp[i*span + j/spo] >> (/*7 -*/ (j%spo)/* *bits */) )
& (0xFF >> (8-bits)) ) /*<< (8-bits)*/;
if (bits < 8) t = amap[bits==1?0:bits==2?1:2][t];
t = tmap[t]; /* map value through the transfer map */
//printf("%2X ", t);
//data[i*stride + j] = t;
ldata[i*stride/4 + j] = /*0x80<<24 |*/ t<<16 | t<<8 | t;
}
//puts("");
}
/*
for (i=0; i < hgt; i++) {
//for (j=0; j < stride; j++)
//printf("%2X ", data[i*stride + j]);
for (j=0; j < stride/4; j++)
printf("%2lX ", ldata[i*stride/4 + j] & 0xFF);
puts("");
}
*/
cairo_surface_t *surf;
//surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A8, wid, hgt, stride);
surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_RGB24, wid, hgt, stride);
//surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, wid, hgt, stride);
//cairo_mask_surface(st->cr, surf, 0, 0);
cairo_set_source_surface(st->cr, surf, 0, 0);
cairo_paint(st->cr);
cairo_surface_flush(st->surface);
if (st->dis) XFlush(st->dis);
cairo_surface_destroy(surf);
//free(data);
}
OPFN_ void image(state *st, object w, object h, object bits, object mat, object proc) {
unsigned char tmap[256];
switch (bits.u.i) {
case 1: case 2: case 4: case 8: break;
default: error(st, rangecheck);
}
int n;
int i;
unsigned char data[n=w.u.i*h.u.i/(8/bits.u.i)];
/* map gray scale through the transfer function */
for (i = 0; i < 256; i++) {
object v;
v = consreal((double)i/255);
push(v);
pushe(consoper(st, "quit", NULL,0,0));
pushe(consoper(st, "exec", NULL,0,0));
pushe(consoper(st, "currenttransfer", NULL,0,0));
run(st);
v = pop();
if (v.tag==integertype) promote(v);
if (v.tag!=realtype) error(st, typecheck);
tmap[i] = v.u.r * 255;
}
for (i = 0; i < n; ) {
object s;
pushe(consoper(st, "quit", NULL,0,0));
pushe(proc);
run(st);
if (tos-os < 1) error(st, stackunderflow);
s = pop();
if (s.tag != stringtype) error(st, typecheck);
memcpy(&data[i], STR(s), s.u.c.n);
i += s.u.c.n;
}
if (DEBUG) { for (i=0; i<n; i++) { printf("%02x ", data[i]); } puts(""); }
if (st->cr) {
gsave(st);
cairo_new_path(st->cr);
cairo_rectangle(st->cr, 0, 0, 1, 1);
cairo_clip(st->cr);
{ cairo_matrix_t cm, icm;
psm2cm(st, mat, &cm);
cminvert(&cm, &icm);
cairo_transform(st->cr, &icm);
}
cairo_set_source_rgb(st->cr, 0.0, 0.0, 0.0);
drawimage(st, w.u.i, h.u.i, bits.u.i, data, tmap);
grestore(st);
}
}

Maybe you want something like gdk_pixbuf_new_from_data
http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-data

Related

Hough transform implementation using C using 2D raw image

I'm trying to implement Hough algorithm using C programming language and 2D raw image.
I have written the code in order to get separate output image for edge detection and Hough transform. When I do edge detection only I'm getting the proper edge detected output image. But here I'm getting the output raw image of size 0KB.I'm not getting where I made mistake.
Can anybody please help me to rectify this problem and give idea for further development such as draw line based on Hough space for the below code.
Thank you in advance.
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
void
hough_transform(unsigned char out[256][256], unsigned char h_out[][256],
int w, int h)
{
int i, j;
int thetaDeg;
float thetaRad;
int rho;
int distMax;
int thetamax;
distMax = sqrt((h * h) + (w * w));
thetamax = 360;
int Acc[180][180];
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
if (out[i][j] > 0) {
for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) {
thetaRad = thetaDeg * (PI / 180);
rho = i * cos(thetaRad) + j * sin(thetaRad);
// find rho value that is closest to this
if (distMax < rho) {
int min = abs(rho - distMax);
}
if (distMax <= 1) {
// Increment a value in an accumulator array
Acc[rho][thetaDeg] += 1;
}
}
}
}
}
for (rho = 0; rho < distMax; rho++) {
for (thetaDeg = 0; thetaDeg < thetamax; thetaDeg++) {
h_out[rho][thetaDeg] = Acc[rho][thetaDeg];
}
}
}
void
edge_detect(unsigned char input[256][256], unsigned char out[][256],
int width, int height)
{
int in[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} };
int pixel;
int i;
int j;
int x;
int y;
for (y = 1; y < height - 1; y++) {
for (x = 1; x < width - 1; x++) {
pixel = 0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel += in[j + 1][i + 1] * input[y + j][x + i];
}
}
out[y][x] = (unsigned char) abs(pixel);
}
}
}
int
main()
{
FILE *fp;
FILE *fp1;
FILE *fp2;
unsigned char input[256][256];
unsigned char out[256][256];
unsigned char h_out[256][256];
int width = 256;
int height = 256;
fp = fopen("Image.raw", "rb");
fp1 = fopen("output.raw", "wb");
fp2 = fopen("h_output.raw", "wb");
fread(input, 256 * 256, 1, fp);
edge_detect(input, out, width, height);
hough_transform(out, h_out, width, height);
fwrite(out, 256 * 256, 1, fp1);
fwrite(h_out, 256 * 256, 1, fp2);
fclose(fp);
fclose(fp1);
fclose(fp2);
return (0);
}

Bytes of png become corrupted in C

I want to write my own png reader using little help from other libraries. So far, I can read back images with only one IDAT chunk perfectly well. However, when I need to concatenate multiple chunks, the file ends up corrupted. Here is an example of one:
I have a lot of code, so I'm going to try and get it to as 'minimum reproducable example' as I can get, but this along with the fact I do not know specifically what part is causing it, is going to make it a bit longer than I'm sure some of you might like, and I'm sorry.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
unsigned char IEND_CHUNK[4] = {'I', 'E', 'N', 'D'}; //Indicates End Of File
unsigned char IDAT_CHUNK[4] = {'I', 'D', 'A', 'T'}; //Holds Pixel Information
typedef struct Chunk Chunk;
typedef struct IHDR IHDR;
struct Chunk {
int length;
unsigned char type[4];
unsigned char *data;
unsigned char crc[4];
};
struct IHDR {
int width;
int height;
int bitd;
int colort;
int compm;
int filterm;
int interlacem;
int channels;
int bytesPerPixel;
};
int bytesToInt(unsigned char a, unsigned char b, unsigned char c, unsigned char d)
{
return (int) a << 24 | b << 16 | c << 8 | d;
}
int compType(unsigned char *a, unsigned char b[], int len)
{
int equal = 1;
for(int i = 0; i < len; i++) equal = a[i] == b[i] ? equal : 0;
return equal;
}
Chunk* getChunksFromBytes(unsigned char* bytes)
{
int next_seg = 7;
int chunks = 0;
long int size = 1;
Chunk* temp = (Chunk*) malloc(sizeof(Chunk));
while(1){
size += sizeof(Chunk);
temp = realloc(temp, size);
temp[chunks].length = bytesToInt(bytes[next_seg+1], bytes[next_seg+2],
bytes[next_seg+3], bytes[next_seg+4]);
temp[chunks].type[0] = bytes[next_seg+5];
temp[chunks].type[1] = bytes[next_seg+6];
temp[chunks].type[2] = bytes[next_seg+7];
temp[chunks].type[3] = bytes[next_seg+8];
temp[chunks].data = malloc(temp[chunks].length);
if(temp[chunks].length > 0){
memcpy(temp[chunks].data, bytes+next_seg+9, temp[chunks].length);
}
else temp[chunks].data = NULL;
temp[chunks].crc[0] = bytes[next_seg+temp[chunks].length+9];
temp[chunks].crc[1] = bytes[next_seg+temp[chunks].length+10];
temp[chunks].crc[2] = bytes[next_seg+temp[chunks].length+11];
temp[chunks].crc[3] = bytes[next_seg+temp[chunks].length+12];
if(compType(temp[chunks].type, IEND_CHUNK, 4)) break;
next_seg+=temp[chunks].length+12;
chunks++;
}
return temp;
}
IHDR getIHDRFromChunks(Chunk* chunks)
{
IHDR img_info;
int channels[7] = {1, 0, 3, 1, 2, 0, 4};
img_info.width = bytesToInt(chunks[0].data[0], chunks[0].data[1],
chunks[0].data[2], chunks[0].data[3]);
img_info.height = bytesToInt(chunks[0].data[4], chunks[0].data[5],
chunks[0].data[6], chunks[0].data[7]);
img_info.bitd = (int) chunks[0].data[8];
img_info.colort = (int) chunks[0].data[9];
img_info.compm = (int) chunks[0].data[10];
img_info.filterm = (int) chunks[0].data[11];
img_info.interlacem = (int) chunks[0].data[12];
img_info.channels = channels[img_info.colort];
img_info.bytesPerPixel = (int) img_info.channels * (img_info.bitd / 8);
return img_info;
}
unsigned char* getImgFromChunks(Chunk* chunks)
{
int count = 0;
IHDR ihdr_data = getIHDRFromChunks(chunks);
uLongf compressed_size = 0;
uLongf uncompressed_size = (ihdr_data.width*ihdr_data.height*ihdr_data.bytesPerPixel) + ihdr_data.height + 1;
unsigned char* compressed_idat = (unsigned char*) malloc(sizeof(unsigned char)*4);
unsigned char* uncompressed_idat = (unsigned char*) malloc(sizeof(unsigned char)*uncompressed_size);
while(1){
if(compType(chunks[count].type, IEND_CHUNK, 4)) break;
else if (compType(chunks[count].type, IDAT_CHUNK, 4)){
compressed_size += sizeof(unsigned char)*chunks[count].length;
compressed_idat = realloc(compressed_idat, compressed_size);
memcpy(compressed_idat + compressed_size - chunks[count].length, chunks[count].data, chunks[count].length);
}
count++;
}
int ret = uncompress(uncompressed_idat, &uncompressed_size, compressed_idat, compressed_size);
free(compressed_idat);
return ret == 0 ? uncompressed_idat : '\0';
}
int PaethPredictor(int a, int b, int c)
{
int pa = abs(b - c);
int pb = abs(a - c);
int pc = abs(a + b - (2*c));
if(pa <= pb && pa <= pc) return a;
else if(pb <= pc) return b;
return c;
}
int* getPixelsFromImg(unsigned char* img, IHDR ihdr_info)
{
int* pixels = (int*) malloc(sizeof(int)*ihdr_info.width*ihdr_info.height*ihdr_info.bytesPerPixel);
int filter_type;
int i = 0;
int current_pixel = 0;
int stride = ihdr_info.width * ihdr_info.bytesPerPixel;
int filt_a;
int filt_b;
int filt_c;
for(int r = 0; r < ihdr_info.height; r++){
filter_type = img[i];
i++;
for(int c = 0; c < stride; c++){
filt_a = c >= ihdr_info.bytesPerPixel ? pixels[r * stride + c - ihdr_info.bytesPerPixel] : 0;
filt_b = r > 0 ? pixels[(r - 1) * stride + c] : 0;
filt_c = r > 0 && c >= ihdr_info.bytesPerPixel ? pixels[(r - 1) * stride + c - ihdr_info.bytesPerPixel] : 0;
switch(filter_type){
case 0:
pixels[current_pixel] = img[i] & 0xff;
break;
case 1:
pixels[current_pixel] = (img[i] + filt_a) & 0xff;
break;
case 2:
pixels[current_pixel] = (img[i] + filt_b) & 0xff;
break;
case 3:
pixels[current_pixel] = (img[i] + filt_a + filt_c) & 0xff;
break;
case 4:
pixels[current_pixel] = (img[i] + PaethPredictor(filt_a, filt_b, filt_c)) & 0xff;
break;
}
current_pixel++;
i++;
}
}
return pixels;
}
These are the combinations of funtcions i use to achieve this. I first use a separate function which I know is not the problem and have therefore left out to get the bytes of the png file. I then call getChunksFromBytes() to gather the chunks of the png file, and I separate the IHDR from these chunks into a separate struct. Finally, I call getImgFromChunks() to uncompress the IDAT data, and getPixelsFromImg() to unfilter the uncompressed values.
First off, bytes per pixel is not a thing since pixels can be bits packed into bytes. So your calculation of uncompressed_size in getImgFromChunks() is wrong. It should be:
uLongf uncompressed_size = ihdr_data.height *
(1 + ((ihdr_data.bitd * ihdr_data.channels * (uLongf)ihdr_data.width + 7) >> 3));
Given that bits per pixel is not a thing, you need to rethink how you are doing getPixelsFromImg(). So there's no point in digging further here until you do that.
There is nothing wrong with your processing of multiple IDAT chunks. You may have misidentified the salient difference of the png file that is giving you issues.

Font asset loading/displaying bitmap issue

I am trying to load a font (arial) from a .ttf file and using the STB TrueType library: https://github.com/nothings/stb/blob/master/stb_truetype.h and display it on the screen.
It is working when displaying the 1st letter in the characters array 'a', but every character after that it looks all distorted and weird, see example below
Comes out as 'a' (correct):
Should be 'b':
I think maybe I am misunderstanding/misapplying how the memory ends up being laid out, or how the file is being read?
Here is the relevant code:
(In win32 platform layer file)
struct character_bitmap
{
unsigned char* memory;
int width;
int height;
};
struct font_buffer
{
character_bitmap* memory;
float size;
};
static font_buffer font_bitmaps;
void test_load_arial(float size)
{
if (font_bitmaps.memory)
{
// VirtualFree(font_bitmaps.memory, 0, MEM_RELEASE);
free(font_bitmaps.memory);
}
unsigned char* ttf_buffer = (unsigned char*)malloc(1 << 25);
stbtt_fontinfo font;
fread(ttf_buffer, 1, 1 << 25, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
stbtt_InitFont(&font, (unsigned char*)ttf_buffer, stbtt_GetFontOffsetForIndex((unsigned char*)ttf_buffer, 0));
// int char_bitmap_width = (int)size;
// int char_bitmap_height = (int)size;
// unsigned int character_memory_size = ((int)size * (int)size) * 4 /*+ 8*/;
// int font_memory_size = character_memory_size * 52;
unsigned int font_memory_size = sizeof(character_bitmap) * 52;
// font_bitmaps.memory = (character_bitmap*)VirtualAlloc(0, font_memory_size, MEM_COMMIT, PAGE_READWRITE);
font_bitmaps.memory = (character_bitmap*)malloc(font_memory_size);
char alphabet[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
character_bitmap* current_character = font_bitmaps.memory;
for (int i = 0; i < 52; i++)
{
// current_character->width = char_bitmap_width;
// current_character->height = char_bitmap_height;
current_character->memory = stbtt_GetCodepointBitmap(&font, 0, stbtt_ScaleForPixelHeight(&font, size), alphabet[i],
&current_character->width, &current_character->height, 0, 0);
current_character++;
}
}
(In different file, inside main update and render function which gets called every frame I call this function)
void test_render_text(offscreen_buffer* buffer, font_buffer* font_bitmaps)
{
int width = font_bitmaps->memory[0].width;
int height = font_bitmaps->memory[0].height;
unsigned char* dest_row = (unsigned char*)buffer->memory
unsigned char* source = font_bitmaps->memory[42].memory;
for (int y = 0; y < height; y++)
{
unsigned int* dest_pixel = (unsigned int*)dest_row;
for (int x = 0; x < width; x++)
{
unsigned char alpha = *source;
*dest_pixel = ((alpha << 24)
| (alpha << 16)
| (alpha << 8)
| (alpha << 0));
dest_pixel++;
source++;
}
dest_row += buffer->pitch;
}
}
Also posted on github if you want the full source to review/compile:
https://github.com/jackson-lenhart/loji

c; converting 2 bytes to short and vice versa

I want to convert array of bytes bytes1 (little endian), 2 by 2, into an array of short integers, and vice versa . I expect to get final array bytes2, equal to initial array bytes1. I have code like this:
int i = 0;
int j = 0;
char *bytes1;
char *bytes2;
short *short_ints;
bytes1 = (char *) malloc( 2048 );
bytes2 = (char *) malloc( 2048 );
short_ints = (short *) malloc( 2048 );
for ( i=0; i<2048; i+=2)
{
short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
j++;
}
j = 0;
for ( i=0; i<2048; i+=2)
{
bytes2[i+1] = (short_ints[j] >> 8) & 0xff;
bytes2[i] = (short_ints[j]) ;
j++;
}
j = 0;
Now, can someone tell me why I haven't got bytes2 array, completely the same as bytes1 ? And how to do this properly?
Suggest 2 functions. Do all combining and extraction as unsigned to remove issues with the sign bit in short and maybe char.
The sign bit is OP's code biggest problem. short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ; likely does a sign extend with bytes1[i] conversion to int.
Also (short_ints[j] >> 8) does a sign extend.
// Combine every 2 char (little endian) into 1 short
void charpair_short(short *dest, const char *src, size_t n) {
const unsigned char *usrc = (const unsigned char *) src;
unsigned short *udest = (unsigned short *) dest;
if (n % 2) Handle_OddError();
n /= 2;
while (n-- > 0) {
*udest = *usrc++;
*udest += *usrc++ * 256u;
udest++;
}
}
// Break every short into 2 char (little endian)
void short_charpair(char *dest, const short *src, size_t n) {
const unsigned short *usrc = (const unsigned short *) src;
unsigned char *udest = (unsigned char *) dest;
if (n % 2) Handle_OddError();
n /= 2;
while (n-- > 0) {
*udest++ = (unsigned char) (*usrc);
*udest++ = (unsigned char) (*usrc / 256u);
usrc++;
}
}
int main(void) {
size_t n = 2048; // size_t rather than int has advantages for array index
// Suggest code style: type *var = malloc(sizeof(*var) * N);
// No casting of return
// Use sizeof() with target pointer name rather than target type.
char *bytes1 = malloc(sizeof * bytes1 * n);
Initialize(bytes, n); //TBD code for OP-best to not work w/uninitialized data
// short_ints = (short *) malloc( 2048 );
// This is weak as `sizeof(short)!=2` is possible
short *short_ints = malloc(sizeof * short_ints * n/2);
charpair_short(short_ints, bytes1, n);
char *bytes2 = malloc(sizeof * bytes2 * n);
short_charpair(bytes2, short_ints, n);
compare(bytes1, bytes2, n); // TBD code for OP
// epilogue
free(bytes1);
free(short_ints);
free(bytes2);
return 0;
}
Avoided the union approach as that is platform endian dependent.
Here's a program that demonstrates that you are experiencing the problem associated with bit-shifting signed integral values.
#include <stdio.h>
#include <stdlib.h>
void testCore(char bytes1[],
char bytes2[],
short short_ints[],
int size)
{
int i = 0;
int j = 0;
for ( i=0; i<size; i+=2)
{
short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
j++;
}
j = 0;
for ( i=0; i<size; i+=2)
{
bytes2[i+1] = (short_ints[j] >> 8) & 0xff;
bytes2[i] = (short_ints[j]) ;
j++;
}
for ( i=0; i<size; ++i)
{
if ( bytes1[i] != bytes2[i] )
{
printf("%d-th element is not equal\n", i);
}
}
}
void test1()
{
char bytes1[4] = {-10, 0, 0, 0};
char bytes2[4];
short short_ints[2];
testCore(bytes1, bytes2, short_ints, 4);
}
void test2()
{
char bytes1[4] = {10, 0, 0, 0};
char bytes2[4];
short short_ints[2];
testCore(bytes1, bytes2, short_ints, 4);
}
int main()
{
printf("Calling test1 ...\n");
test1();
printf("Done\n");
printf("Calling test2 ...\n");
test2();
printf("Done\n");
return 0;
}
Output of the program:
Calling test1 ...
1-th element is not equal
Done
Calling test2 ...
Done
Udate
Here's a version of testCore that works for me:
void testCore(char bytes1[],
char bytes2[],
short short_ints[],
int size)
{
int i = 0;
int j = 0;
unsigned char c1;
unsigned char c2;
unsigned short s;
for ( i=0; i<size; i+=2)
{
c1 = bytes1[i];
c2 = bytes1[i+1];
short_ints[j] = (c2 << 8) | c1;
j++;
}
j = 0;
for ( i=0; i<size; i+=2)
{
s = short_ints[j];
s = s >> 8;
bytes2[i+1] = s;
bytes2[i] = short_ints[j] & 0xff;
j++;
}
for ( i=0; i<size; ++i)
{
if ( bytes1[i] != bytes2[i] )
{
printf("%d-th element is not equal\n", i);
}
}
}
It is tested with:
char bytes1[4] = {-10, 0, 25, -4};
and
char bytes1[4] = {10, -2, 25, 4};
Well, what you need is a UNION:
#include <stdio.h>
#include <string.h>
union MyShort {
short short_value;
struct {
char byte1;
char byte2;
};
};
int main(int argc, const char * argv[])
{
char a[4]="abcd";
char b[4]="1234";
short c[5]; c[4]=0;
union MyShort d;
for (int i = 0; i<4; i++) {
d.byte1 = a[i];
d.byte2 = b[i];
c[i] = d.short_value;
}//next i
printf("%s\n", (char*)c);
return 0;
}
the result should be a1b2c3d4.

Decompression stops inbetween and output file filled with zeros(BLACK PIXELS)?

I am trying to apply DCT(discrete cosine transformation) compression on a bmp(bitmap) file. I have a c file which i am running in Turbo C++. This is not actually compressing but i was trying to implement the DCT and IDCT. The code is as follows:
/*
the image to be compressed is a bmp with 24 bpp and
with name "college4.bmp" of dimensions 200*160 ie 25*20- 8*8 blocks
o/p is college2.dat
format: 8 bit signed integers starting rowwise from 0,0 to 8,8
the coefficients order is blue,green,red
for the block no 1 then 2 and soon
*/
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define WIDTH 25
#define HEIGHT 20
typedef struct {
unsigned int type;
unsigned long int filesize;
unsigned int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
BMPHEAD bmphead;
INFOHEAD infohead;
FILE *bmp_fp1,*bmp_fp2;
int buf[WIDTH][8][8][3],buf1[WIDTH][8][8][3];
float pi=3.14159265,DCTcoeff[8][8][8][8];
void generatedctcoeff() {
int y, i, j, x;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
DCTcoeff[i][j][x][y] = cos(((2 * y + 1) * pi * j) / 16)
* cos(((2 * x + 1) * i * pi) / 16);
}
}
}
}
}
void outputtofile1() { // Write into college2.dat
int i, j, x, y, blockno; // One block at a time, buf contains pixel
int redcoef, greencoef, bluecoef; // data of one row of blocks
float gijred, gijgreen, gijblue, c, ci, cj;
c = 1 / (sqrt(2));
for (blockno = 0; blockno < WIDTH; blockno++) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
gijred = 0;
gijgreen = 0;
gijblue = 0;
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
gijblue = gijblue + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][0];
gijgreen = gijgreen + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][1];
gijred = gijred + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][2];
}
}
ci = cj = 1.0;
if (i == 0)
ci = c;
if (j == 0)
cj = c;
gijblue = ci * cj * gijblue / 4;
gijgreen = ci * cj * gijgreen / 4;
gijred = ci * cj * gijred / 4;
bluecoef = (int) gijblue;
greencoef = (int) gijgreen;
redcoef = (int) gijred;
fprintf(bmp_fp2, "%d %d %d ", bluecoef, greencoef, redcoef);
}
}
} /* end of one block processing */
}
void compressimage() {
int rowcount,x,y;
bmp_fp1=fopen("college4.bmp","r");
bmp_fp2=fopen("college2.dat","w");
printf("generating coefficients...\n");
generatedctcoeff();
if(bmp_fp1==NULL) {
printf("can't open");
return;
}
printf("compressing....\n");
fread(&bmphead,1,sizeof(bmphead),bmp_fp1);
fread(&infohead,1,sizeof(infohead),bmp_fp1);
fseek(bmp_fp1,bmphead.offset,SEEK_SET);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(y=0;y<8;y++) {
for(x=0;x<infohead.width;x++) {
buf[x/8][x%8][y][0]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][1]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][2]=(int)fgetc(bmp_fp1);
}
}
outputtofile1(); //output contents of buf after dct to file
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
void outputtofile2() { //output buf to college3.bmp
int i, j, x, y, blockno; // buf now contains coefficients
float pxyred, pxygreen, pxyblue, c, ci, cj; // a temp buffer buf1 used to
c = 1 / (sqrt(2)); // store one row of block of
for (blockno = 0; blockno < WIDTH; blockno++) { // decoded pixel values
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++) {
pxyred = 0;
pxygreen = 0;
pxyblue = 0;
for (j = 0; j < 8; j++) {
cj = 1.0;
if (j == 0)
cj = c;
for (i = 0; i < 8; i++) {
ci = 1.0;
if (i == 0)
ci = c;
pxyblue = pxyblue + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][0];
pxygreen = pxygreen + ci * cj
* DCTcoeff[i][j][y][x] * buf[blockno][i][j][1];
pxyred = pxyred + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][2];
}
}
pxyblue /= 4;
pxygreen /= 4;
pxyred /= 4;
buf1[blockno][y][x][0] = pxyblue;
buf1[blockno][y][x][1] = pxygreen;
buf1[blockno][y][x][2] = pxyred;
}
}
for (y = 0; y < 8; y++) {
for (blockno = 0; blockno < WIDTH; blockno++)
for (x = 0; x < 8; x++) {
fprintf(bmp_fp2, "%c%c%c", (char) buf1[blockno][x][y][0],
(char) buf1[blockno][x][y][1],
(char) buf1[blockno][x][y][2]);
}
}
}
void uncompressimage() {
int blue,green,red,rowcount,colcount,i,j;
bmp_fp1=fopen("college2.dat","r");
bmp_fp2=fopen("college3.bmp","w");
printf("generating coefficients...\n");
generatedctcoeff();
if (bmp_fp1==NULL) {
printf("open failed");
return;
}
printf("uncompressing....\n");
bmphead.type=0x4d42;
bmphead.filesize=30518;
bmphead.reserved1=0;
bmphead.reserved2=0;
bmphead.offset=sizeof(bmphead)+sizeof(infohead);
infohead.infosize=sizeof(infohead);
infohead.width=200;
infohead.height=160;
infohead.planes=1;
infohead.bitsperpixel=24;
infohead.compression=0;
infohead.sizeimage=0;
infohead.xpelspermeter=3780;
infohead.ypelspermeter=3780;
infohead.colorused=0;
infohead.colorimportant=0;
fwrite(&bmphead,sizeof(BMPHEAD),1,bmp_fp2);
fwrite(&infohead,sizeof(INFOHEAD),1,bmp_fp2);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(colcount=0;colcount<WIDTH;colcount++) {
for(i=0;i<8;i++) {
for(j=0;j<8;j++) {
fscanf(bmp_fp1,"%d",&blue);
fscanf(bmp_fp1,"%d",&green);
fscanf(bmp_fp1,"%d",&red);
buf[colcount][i][j][0]=blue;
buf[colcount][i][j][1]=green;
buf[colcount][i][j][2]=red;
}
}
}
outputtofile2();
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
int main() {
printf("opening files...\n");
compressimage();
printf("opening files...again\n");
uncompressimage();
printf("successful decompression\nenter any key\n");
return 0;
}
Here is the image i am using as input
(im srry the site converted the bmp into png. You may convert it back to bmp to use it)
Here is the image that is generated:
The file college3.bmp that gets created is of size 200x160 and of 93.8 kB but till quarter of the image it has decoded the coefficients correctly but later the file is filled with black pixels. I have taken a screenshot of the o/p as it was saying not a valid bmp while uploading. I am sitting on this problem since feb,2004. If anyone can say me where there is a bug i would be very thankful. I have analysed the output file and found an EOF right at the place where the pixels are starting to be black. I read some other questions on the topic and found that the conversion factors ci,cj have been used improperly. While coding i had also got confused with the indices x,y,i and j. So i hope this problem i will solve in a few days.
Apparently, the problem in the above code is in how you open your files.
This is what should be in your code (note the explicitly specified open modes, binary and text):
void compressimage() {
...
bmp_fp1=fopen("college4.bmp","rb");
bmp_fp2=fopen("college2.dat","wt");
...
}
void uncompressimage() {
...
bmp_fp1=fopen("college2.dat","rt");
bmp_fp2=fopen("college3.bmp","wb");
...
}
With that and slightly altered structure definitions:
#pragma pack(push,1)
typedef struct {
unsigned short int type;
unsigned long int filesize;
unsigned short int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned short int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
#pragma pack(pop)
I'm able to compile your program successfully using 3 different compilers (Turbo C++, Open Watcom, gcc) and get the desired output picture.

Resources