Created
August 11, 2011 21:59
-
-
Save corruptmem/1140906 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string.h> | |
#include <iostream> | |
#include "jpeg.h" | |
#define FORC(cnt) for (c=0; c < cnt; c++) | |
#define FORC3 FORC(3) | |
#define FORC4 FORC(4) | |
#define FORCC FORC(colors) | |
ljpeg::ljpeg(const unsigned char* data, int size) : SeekCur(1) { | |
jh = &jhactual; | |
_data = data; | |
_size = size; | |
_pos = 0; | |
} | |
void ljpeg::fread(unsigned char* data, int m, int n) { | |
//std::cout<<"read"<<std::endl; | |
int dst = 0; | |
for(int i = 0; i<n; i++) { | |
int cp = m; | |
if(_pos + cp >= _size) { | |
cp = _size - _pos; | |
} | |
memcpy(data+dst, _data+_pos, cp); | |
_pos += cp; | |
dst += cp; | |
if(_pos > _size) return; | |
} | |
} | |
unsigned int ljpeg::fgetc() { | |
//std::cout<<"getc"<<std::endl; | |
if(_pos >= _size) { | |
return EOF; | |
} | |
return _data[_pos++]; | |
} | |
unsigned int ljpeg::getc() { | |
return fgetc(); | |
} | |
void ljpeg::fseek(int amount, int seektype) { | |
_pos = _pos + amount; | |
} | |
unsigned ljpeg::getbithuff (int nbits, ushort *huff) | |
{ | |
static unsigned bitbuf=0; | |
static int vbits=0, reset=0; | |
unsigned c; | |
if (nbits == -1) | |
return bitbuf = vbits = reset = 0; | |
if (nbits == 0 || vbits < 0) return 0; | |
while (!reset && vbits < nbits && (c = fgetc()) != EOF && | |
!(reset = zero_after_ff && c == 0xff && fgetc())) { | |
bitbuf = (bitbuf << 8) + (uchar) c; | |
vbits += 8; | |
} | |
c = bitbuf << (32-vbits) >> (32-nbits); | |
if (huff) { | |
vbits -= huff[c] >> 8; | |
c = (uchar) huff[c]; | |
} else | |
vbits -= nbits; | |
if (vbits < 0) throw "Vbits was 0"; | |
return c; | |
} | |
unsigned ljpeg::getbits(int nbits) { | |
return getbithuff(nbits, 0); | |
} | |
ushort * ljpeg::make_decoder_ref (const uchar **source) | |
{ | |
int max, len, h, i, j; | |
const uchar *count; | |
ushort *huff; | |
count = (*source += 16) - 17; | |
for (max=16; max && !count[max]; max--); | |
huff = (ushort *) calloc (1 + (1 << max), sizeof *huff); | |
merror (huff, "make_decoder()"); | |
huff[0] = max; | |
for (h=len=1; len <= max; len++) | |
for (i=0; i < count[len]; i++, ++*source) | |
for (j=0; j < 1 << (max-len); j++) | |
if (h <= 1 << max) | |
huff[h++] = len << 8 | **source; | |
return huff; | |
} | |
int ljpeg::start (int info_only) | |
{ | |
int c, tag, len; | |
uchar data[0x10000]; | |
const uchar *dp; | |
memset (jh, 0, sizeof *jh); | |
jh->restart = INT_MAX; | |
fread (data, 2, 1); | |
if (data[1] != 0xd8) return 0; | |
do { | |
fread (data, 2, 2); | |
tag = data[0] << 8 | data[1]; | |
len = (data[2] << 8 | data[3]) - 2; | |
if (tag <= 0xff00) return 0; | |
fread (data, 1, len); | |
switch (tag) { | |
case 0xffc3: | |
jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; | |
case 0xffc0: | |
jh->bits = data[0]; | |
jh->high = data[1] << 8 | data[2]; | |
jh->wide = data[3] << 8 | data[4]; | |
jh->clrs = data[5] + jh->sraw; | |
if (len == 9 && !dng_version) getc(); | |
break; | |
case 0xffc4: | |
if (info_only) break; | |
for (dp = data; dp < data+len && (c = *dp++) < 4; ) | |
jh->free[c] = jh->huff[c] = make_decoder_ref (&dp); | |
break; | |
case 0xffda: | |
jh->psv = data[1+data[0]*2]; | |
jh->bits -= data[3+data[0]*2] & 15; | |
break; | |
case 0xffdd: | |
jh->restart = data[0] << 8 | data[1]; | |
} | |
} while (tag != 0xffda); | |
if (info_only) return 1; | |
FORC(5) if (!jh->huff[c+1]) jh->huff[c+1] = jh->huff[c]; | |
if (jh->sraw) { | |
FORC(4) jh->huff[2+c] = jh->huff[1]; | |
FORC(jh->sraw) jh->huff[1+c] = jh->huff[0]; | |
} | |
jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4); | |
merror (jh->row, "ljpeg_start()"); | |
return zero_after_ff = 1; | |
} | |
void ljpeg::merror (void *ptr, const char *where) | |
{ | |
if (ptr) return; | |
throw "Out of memory"; | |
} | |
void ljpeg::end () | |
{ | |
int c; | |
FORC4 if (jh->free[c]) free (jh->free[c]); | |
free (jh->row); | |
} | |
int ljpeg::diff (ushort *huff) | |
{ | |
int len, diff; | |
len = gethuff(huff); | |
if (len == 16 && (!dng_version || dng_version >= 0x1010000)) | |
return -32768; | |
diff = getbits(len); | |
if ((diff & (1 << (len-1))) == 0) | |
diff -= (1 << len) - 1; | |
return diff; | |
} | |
ushort * ljpeg::row (int jrow) | |
{ | |
int col, c, diff, pred, spred=0; | |
ushort mark=0, *row[3]; | |
if (jrow * jh->wide % jh->restart == 0) { | |
FORC(6) jh->vpred[c] = 1 << (jh->bits-1); | |
if (jrow) { | |
fseek (-2, SEEK_CUR); | |
do mark = (mark << 8) + (c = fgetc()); | |
while (c != EOF && mark >> 4 != 0xffd); | |
} | |
getbits(-1); | |
} | |
FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1); | |
for (col=0; col < jh->wide; col++) | |
FORC(jh->clrs) { | |
diff = this->diff (jh->huff[c]); | |
if (jh->sraw && c <= jh->sraw && (col | c)) | |
pred = spred; | |
else if (col) pred = row[0][-jh->clrs]; | |
else pred = (jh->vpred[c] += diff) - diff; | |
if (jrow && col) switch (jh->psv) { | |
case 1: break; | |
case 2: pred = row[1][0]; break; | |
case 3: pred = row[1][-jh->clrs]; break; | |
case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break; | |
case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break; | |
case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break; | |
case 7: pred = (pred + row[1][0]) >> 1; break; | |
default: pred = 0; | |
} | |
if ((**row = pred + diff) >> jh->bits) throw "Data error"; | |
if (c <= jh->sraw) spred = **row; | |
row[0]++; row[1]++; | |
} | |
return row[2]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// jpeg.h | |
// rawproc | |
// | |
// Created by Cameron Harris on 02/08/2011. | |
// Copyright 2011 lolwtf. All rights reserved. | |
// | |
#ifndef rawproc_jpeg_h | |
#define rawproc_jpeg_h | |
typedef unsigned short ushort; | |
typedef unsigned char uchar; | |
typedef long long INT64; | |
typedef unsigned long long UINT64; | |
struct jhead { | |
int bits, high, wide, clrs, sraw, psv, restart, vpred[6]; | |
ushort *huff[6], *free[4], *row; | |
}; | |
class ljpeg { | |
private: | |
unsigned data_error; | |
const char* ifname; | |
unsigned zero_after_ff; | |
unsigned dng_version; | |
struct jhead* jh; | |
const unsigned char* _data; | |
int _size; | |
int _pos; | |
const int SeekCur; | |
public: | |
struct jhead jhactual; | |
ljpeg(const unsigned char* data, int size); | |
void fread(unsigned char* data, int m, int n); | |
unsigned int fgetc(); | |
unsigned int getc(); | |
void fseek(int amount, int seektype); | |
unsigned getbithuff (int nbits, ushort *huff); | |
unsigned getbits(int nbits); | |
template<typename T> unsigned gethuff(T& h) { | |
return getbithuff(*h, h+1); | |
} | |
ushort * make_decoder_ref (const uchar **source); | |
int start (int info_only); | |
void merror (void *ptr, const char *where); | |
void end (); | |
int diff (ushort *huff); | |
ushort * row (int jrow); | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment