Skip to content

Instantly share code, notes, and snippets.

@alaingalvan
Created December 14, 2017 04:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alaingalvan/848e62386f5ae438d9eb9a4501e3d88c to your computer and use it in GitHub Desktop.
Save alaingalvan/848e62386f5ae438d9eb9a4501e3d88c to your computer and use it in GitHub Desktop.
//-----------------------------------------------------------------------------
// Photoshop Trick
// Author: Kiran Sudhakara
//
// Produces an image that most image editors cannot downsize Inspired
// by http://www.4p8.com/eric.brasseur/gamma.html
//-----------------------------------------------------------------------------
#include "windows.h"
#include <stdio.h>
//-----------------------------------------------------------------------------
typedef enum FileDialogType {
DIALOG_OPEN,
DIALOG_SAVE
} FileDialogType;
int GetBitmapPath(char *sz_path, int len, FileDialogType dialog_type)
{
OPENFILENAME desc;
memset(&desc,0,sizeof(desc));
sz_path[0] = '\0';
desc.lStructSize = sizeof(desc);
desc.lpstrFile = sz_path;
desc.nMaxFile = len;
desc.lpstrFilter = "Windows Bitmap File\0*.bmp\0";
if (dialog_type == DIALOG_OPEN)
desc.Flags = OFN_FILEMUSTEXIST;
else
desc.Flags = OFN_OVERWRITEPROMPT;
if (dialog_type == DIALOG_OPEN) {
if (!GetOpenFileName(&desc))
return 1;
} else {
if (!GetSaveFileName(&desc)) {
return 1;
}
}
return 0;
}
//-----------------------------------------------------------------------------
//this only supports 24 bit bitmaps!
typedef struct rgb_t {
unsigned char b;
unsigned char g;
unsigned char r;
} rgb_t;
typedef struct image_t {
int w,h;
rgb_t *rgb;
} image_t;
int Image_Init(image_t *img, int w, int h)
{
img->w = w;
img->h = h;
img->rgb = (rgb_t*)malloc(w*h*sizeof(rgb_t));
return 0;
}
int Image_InitFromBitmap(image_t *img)
{
FILE *fp;
BITMAPFILEHEADER file_header;
BITMAPINFOHEADER info_header;
int buf_size;
char sz_path[260];
if (GetBitmapPath(sz_path, sizeof(sz_path),DIALOG_OPEN))
return 1;
//read file into image
fp = fopen(sz_path, "rb");
fread(&file_header, sizeof(file_header), 1, fp);
fread(&info_header, sizeof(info_header), 1, fp);
fseek(fp, file_header.bfOffBits, SEEK_SET);
img->h = info_header.biHeight;
img->w = info_header.biWidth;
buf_size = img->h * img->w * sizeof(rgb_t);
if (info_header.biBitCount != 24)
return 1;
img->rgb = (rgb_t*)malloc(buf_size);
fread(img->rgb, 1, buf_size, fp);
fclose(fp);
return 0;
}
void Image_Destroy(image_t *img)
{
free(img->rgb);
memset(img, 0, sizeof(image_t));
}
int Image_WriteToBitmap(image_t *img)
{
FILE *fp;
BITMAPFILEHEADER file_header;
BITMAPINFOHEADER info_header;
char sz_path[260];
int img_size;
union {
unsigned short type;
char id[2];
} magic;
memset(&file_header, 0, sizeof(file_header));
memset(&info_header, 0, sizeof(info_header));
magic.id[0] = 'B';
magic.id[1] = 'M';
img_size = img->w * img->h * sizeof(rgb_t);
file_header.bfType = magic.type;
file_header.bfSize = sizeof(file_header) + sizeof(info_header) + img_size;
file_header.bfOffBits = sizeof(file_header) + sizeof(info_header);
info_header.biSize = sizeof(info_header);
info_header.biWidth = img->w;
info_header.biHeight = img->h;
info_header.biPlanes = 1;
info_header.biBitCount = 24;
info_header.biCompression = 0;
info_header.biSizeImage = img_size;
//write to file
if (GetBitmapPath(sz_path, sizeof(sz_path), DIALOG_SAVE))
return 1;
fp = fopen(sz_path, "wb");
fwrite(&file_header, sizeof(file_header), 1, fp);
fwrite(&info_header, sizeof(info_header), 1, fp);
fwrite(img->rgb, img_size, 1, fp);
fclose(fp);
return 0;
}
void Image_PhotoshopTrick(image_t *out, image_t *in)
{
int i,j;
int w,h;
rgb_t px,px_out;
w = in->w;
h = in->h;
for (j=0; j<h; j+=2) {
for (i=0; i<w; i++) {
px = in->rgb[j*w + i];
px_out.r = 127 - px.r /2;
px_out.g = 127 - px.g /2;
px_out.b = 127 - px.b /2;
out->rgb[j*w + i] = px_out;
px_out.r = 127 + px.r /2;
px_out.g = 127 + px.g /2;
px_out.b = 127 + px.b /2;
out->rgb[(j+1)*w + i] = px_out;
}
}
}
//-----------------------------------------------------------------------------
int main(int argc, char *argv[])
{
image_t in, out;
if (Image_InitFromBitmap(&in))
return 1;
Image_Init(&out, in.w, in.h);
Image_PhotoshopTrick(&out, &in);
Image_WriteToBitmap(&out);
Image_Destroy(&in);
Image_Destroy(&out);
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment