Created
October 8, 2019 08:12
-
-
Save tspspi/b8df658389fe66e3ea6ed03c561cb90c to your computer and use it in GitHub Desktop.
Simple JPEG image I/O example with libjpeg (nearly no proper error handling)
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 <stddef.h> | |
#include <stdlib.h> | |
#include "./simple_imageio.h" | |
enum imageLibraryError filterGrayscale( | |
struct imgRawImage* lpInput, | |
struct imgRawImage** lpOutput | |
) { | |
unsigned long int i; | |
if(lpOutput == NULL) { | |
(*lpOutput) = lpInput; /* We will replace our input structure ... */ | |
} else { | |
(*lpOutput) = malloc(sizeof(struct imgRawImage)); | |
(*lpOutput)->width = lpInput->width; | |
(*lpOutput)->height = lpInput->height; | |
(*lpOutput)->numComponents = lpInput->numComponents; | |
(*lpOutput)->lpData = malloc(sizeof(unsigned char) * lpInput->width*lpInput->height*3); | |
} | |
for(i = 0; i < lpInput->width*lpInput->height; i=i+1) { | |
/* Do a grayscale transformation */ | |
unsigned char luma = (unsigned char)(0.299f * (float)lpInput->lpData[i * 3 + 0] + 0.587f * (float)lpInput->lpData[i * 3 + 1] + 0.114f * (float)lpInput->lpData[i * 3 + 2]); | |
(*lpOutput)->lpData[i * 3 + 0] = luma; | |
(*lpOutput)->lpData[i * 3 + 1] = luma; | |
(*lpOutput)->lpData[i * 3 + 2] = luma; | |
} | |
return imageLibE_Ok; | |
} |
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 <stdio.h> | |
#include <stdlib.h> | |
#include <jpeglib.h> | |
#include <jerror.h> | |
#include "./simple_imageio.h" | |
int storeJpegImageFile(struct imgRawImage* lpImage, char* lpFilename) { | |
struct jpeg_compress_struct info; | |
struct jpeg_error_mgr err; | |
unsigned char* lpRowBuffer[1]; | |
FILE* fHandle; | |
fHandle = fopen(lpFilename, "wb"); | |
if(fHandle == NULL) { | |
#ifdef DEBUG | |
fprintf(stderr, "%s:%u Failed to open output file %s\n", __FILE__, __LINE__, lpFilename); | |
#endif | |
return 1; | |
} | |
info.err = jpeg_std_error(&err); | |
jpeg_create_compress(&info); | |
jpeg_stdio_dest(&info, fHandle); | |
info.image_width = lpImage->width; | |
info.image_height = lpImage->height; | |
info.input_components = 3; | |
info.in_color_space = JCS_RGB; | |
jpeg_set_defaults(&info); | |
jpeg_set_quality(&info, 100, TRUE); | |
jpeg_start_compress(&info, TRUE); | |
/* Write every scanline ... */ | |
while(info.next_scanline < info.image_height) { | |
lpRowBuffer[0] = &(lpImage->lpData[info.next_scanline * (lpImage->width * 3)]); | |
jpeg_write_scanlines(&info, lpRowBuffer, 1); | |
} | |
jpeg_finish_compress(&info); | |
fclose(fHandle); | |
jpeg_destroy_compress(&info); | |
return 0; | |
} | |
struct imgRawImage* loadJpegImageFile(char* lpFilename) { | |
struct jpeg_decompress_struct info; | |
struct jpeg_error_mgr err; | |
struct imgRawImage* lpNewImage; | |
unsigned long int imgWidth, imgHeight; | |
int numComponents; | |
unsigned long int dwBufferBytes; | |
unsigned char* lpData; | |
unsigned char* lpRowBuffer[1]; | |
FILE* fHandle; | |
fHandle = fopen(lpFilename, "rb"); | |
if(fHandle == NULL) { | |
#ifdef DEBUG | |
fprintf(stderr, "%s:%u: Failed to read file %s\n", __FILE__, __LINE__, lpFilename); | |
#endif | |
return NULL; /* ToDo */ | |
} | |
info.err = jpeg_std_error(&err); | |
jpeg_create_decompress(&info); | |
jpeg_stdio_src(&info, fHandle); | |
jpeg_read_header(&info, TRUE); | |
jpeg_start_decompress(&info); | |
imgWidth = info.output_width; | |
imgHeight = info.output_height; | |
numComponents = info.num_components; | |
#ifdef DEBUG | |
fprintf(stderr, "%s:%u: Reading JPEG with dimensions %lu x %lu and %u components\n", __FILE__, __LINE__, imgWidth, imgHeight, numComponents); | |
#endif | |
dwBufferBytes = imgWidth * imgHeight * 3; /* We only read RGB, not A */ | |
lpData = (unsigned char*)malloc(sizeof(unsigned char)*dwBufferBytes); | |
lpNewImage = (struct imgRawImage*)malloc(sizeof(struct imgRawImage)); | |
lpNewImage->numComponents = numComponents; | |
lpNewImage->width = imgWidth; | |
lpNewImage->height = imgHeight; | |
lpNewImage->lpData = lpData; | |
/* Read scanline by scanline */ | |
while(info.output_scanline < info.output_height) { | |
lpRowBuffer[0] = (unsigned char *)(&lpData[3*info.output_width*info.output_scanline]); | |
jpeg_read_scanlines(&info, lpRowBuffer, 1); | |
} | |
jpeg_finish_decompress(&info); | |
jpeg_destroy_decompress(&info); | |
fclose(fHandle); | |
return lpNewImage; | |
} |
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 <stdio.h> | |
#include <stdlib.h> | |
#include "./simple_imageio.h" | |
int main(int argc, char* argv[]) { | |
struct imgRawImage* lpImage; | |
struct imgRawImage* lpIntegral; | |
if(argc >= 2) { | |
lpImage = loadJpegImageFile(argv[1]); | |
if(lpImage == NULL) { | |
return 1; | |
} | |
if(filterGrayscale(lpImage, &lpImage) != imageLibE_Ok) { | |
fprintf(stderr, "%s:%u Failed to do grayscale conversion\n", __FILE__, __LINE__); | |
return 1; | |
} | |
if(argc >= 3) { | |
storeJpegImageFile(lpImage, argv[2]); | |
} | |
} | |
return 0; | |
} |
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
main: main.c filter_greyscale.c imagefile.c simple_imageio.h | |
clang -DDEBUG -o main -Wall -ansi -std=c99 -pedantic -Werror main.c filter_greyscale.c imagefile.c -ljpeg |
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
enum imageLibraryError { | |
imageLibE_Ok, | |
imageLibE_OutOfMemory, | |
imageLibE_InvalidParam | |
}; | |
struct imgRawImage { | |
unsigned int numComponents; | |
unsigned long int width, height; | |
unsigned char* lpData; | |
}; | |
int storeJpegImageFile(struct imgRawImage* lpImage, char* lpFilename); | |
struct imgRawImage* loadJpegImageFile(char* lpFilename); | |
enum imageLibraryError filterGrayscale( | |
struct imgRawImage* lpInput, | |
struct imgRawImage** lpOutput | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment