def getCameraObject(exif): """ Given image exif data, either creates a new camera object or returns an existing one. """ cameraName = getExifValue(exif, "Model") if cameraName: serial = getExifValue(exif, "BodySerialNumber") cameras = CAMERA_MODEL.get().objects.filter(name=cameraName, serial=serial) if cameras.exists(): return cameras[0] else: return CAMERA_MODEL.get().objects.create(name=cameraName, serial=serial) return None
def getCameraObject(exif): ''' Given image exif data, either creates a new camera object or returns an existing one. ''' cameraName = getExifValue(exif, 'Model') if cameraName: serial = getExifValue(exif, 'BodySerialNumber') cameras = CAMERA_MODEL.get().objects.filter(name=cameraName, serial=serial) if cameras.exists(): return cameras[0] else: return CAMERA_MODEL.get().objects.create(name=cameraName, serial=serial) return None
def getExifTimeString(request, uploadedFile): exifData = getExifData(uploadedFile) if 'exifData' in request.POST: # update the parsed exif dictionary with the incoming exif json exifData.update(json.loads(request.POST['exifData'])) # get metadata for image set, create the image set # get exif time for image set exifTime = None exifTimeString = getExifValue(exifData, 'DateTimeOriginal') if not exifTimeString: exifTimeString = getExifValue(exifData, 'DateTime') elif exifTimeString is None: return HttpResponse(json.dumps( {'error': 'Could not determine image date'}), content_type='application/json', status=406) return exifData, exifTimeString
def create_image_set(file, filename, author, vehicle, camera, width_height=None, form_tz=None, form_tz_name=None, exif_data=None, exif_time=None, object_id=None, time_mark=None, latlon=None): """ Create image set from one image, and save image set to database :param file: :param filename: :param width_height: :param author: :param vehicle: :param camera: :param form_tz: :param form_tz_name: :param exif_data: :param exif_time: :param object_id: :param time_mark: :param latlon: :return: """ if not exif_time: exif_time = datetime.now(pytz.utc) # create a new image set instance if object_id: new_image_set = IMAGE_SET_MODEL.get()(pk=int(object_id)) else: new_image_set = IMAGE_SET_MODEL.get()() new_image_set.acquisition_time = exif_time new_image_set.name = filename if isinstance(camera, CAMERA_MODEL.get()): new_image_set.camera = camera new_image_set.flight = getFlight(new_image_set.acquisition_time, vehicle) track = None if new_image_set.flight: if not form_tz_name: form_tz_name = new_image_set.flight.timezone if not form_tz and form_tz_name: form_tz = pytz.timezone(form_tz_name) try: track = new_image_set.flight.track except: # the flight may not have a track pass new_image_set.acquisition_timezone = form_tz_name if track: new_image_set.track_position = getClosestPosition(track=track, timestamp=exif_time, vehicle=vehicle) if exif_data: new_image_set.exif_position = buildExifPosition( exif_data, new_image_set.camera, vehicle, exif_time, form_tz) elif latlon: new_image_set.exif_position = buildExifPositionFromLatLon( latlon, exif_time) new_image_set.author = author # timing stats if time_mark: now_time = time.time() upload_and_save_time = now_time - time_mark new_image_set.uploadAndSaveTime = upload_and_save_time overall_start_time = cache.get("imageAutoloadGlobalTimeMark", None) if overall_start_time: total_time_since_notify = now_time - float(overall_start_time) new_image_set.totalTimeSinceNotify = total_time_since_notify # end timing stats new_image_set.save() # build the metadata for the single image single_image_metadata = {'imageSet': new_image_set} try: if exif_data: single_image_metadata['width'] = int( getExifValue(exif_data, 'ExifImageWidth')) single_image_metadata['height'] = int( getExifValue(exif_data, 'ExifImageHeight')) else: if not width_height: dt = Image.open(file) width_height = dt.size single_image_metadata['width'] = width_height[0] single_image_metadata['height'] = width_height[1] except: pass # convert the image if needed converted_file = convert_to_jpg_if_needed(file) if converted_file: # create the single image for the source single_image_metadata['fileSizeBytes'] = get_file_size(file) single_image_metadata['file'] = file single_image_metadata['imageType'] = ImageType.source.value single_image_metadata['raw'] = False single_image_metadata['thumbnail'] = False source_single_image = SINGLE_IMAGE_MODEL.get().objects.create( **single_image_metadata) file = converted_file # create the single image for the raw / full / renderable try: single_image_metadata['fileSizeBytes'] = get_file_size(file) single_image_metadata['file'] = file single_image_metadata['imageType'] = ImageType.full.value single_image_metadata['raw'] = True single_image_metadata['thumbnail'] = False except: pass new_single_image = SINGLE_IMAGE_MODEL.get().objects.create( **single_image_metadata) # relay was here createThumbnail(new_single_image, new_image_set) # TODO: replace this with a BoundedSemaphore # TODO: we are pretty sure this was causing the fail in tiling and in importing images because many deepzoom # threads are kicked off at the same time yet this code uses just one flag. #FIX # TODO: suggest putting a single flag for each image we are tiling into REDIS # dbServer = couchdb.Server(settings.COUCHDB_URL) # db = dbServer[settings.COUCHDB_FILESTORE_NAME] # if 'create_deepzoom_thread' in db: # myFlag = db['create_deepzoom_thread'] # myFlag['active'] = True # db['create_deepzoom_thread'] = myFlag # else: # db['create_deepzoom_thread'] = {'active': True} createDeepzoomTiles(new_image_set) return new_image_set
def saveImage(request): """ Image drag and drop, saves the files and to the database. """ if request.method == "POST": timeMark = time.time() form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): # create and save a single image obj uploadedFile = request.FILES["file"] newImage = SINGLE_IMAGE_MODEL.get()(file=uploadedFile) form_tz = form.getTimezone() resource = form.getResource() exifData = getExifData(newImage) # save image dimensions and file size try: newImage.width = int(getExifValue(exifData, "ExifImageWidth")) newImage.height = int(getExifValue(exifData, "ExifImageHeight")) except: pass newImage.fileSizeBytes = uploadedFile.size # get exif time exifTime = None exifTimeString = getExifValue(exifData, "DateTimeOriginal") if not exifTimeString: exifTimeString = getExifValue(exifData, "DateTime") if exifTimeString: exifTime = datetime.strptime(str(exifTimeString), "%Y:%m:%d %H:%M:%S") if (form_tz != pytz.utc) and exifTime: localized_time = form_tz.localize(exifTime) exifTime = TimeUtil.timeZoneToUtc(localized_time) else: exifTime = exifTime.replace(tzinfo=pytz.utc) else: # read the time from the last modified time that we pushed in from imageUpload.js if "HTTP_LASTMOD" in request.META: modtimesString = request.META["HTTP_LASTMOD"] if modtimesString: modtime = None theImages = modtimesString.split(",") for i in theImages: k, v = i.split("||") if k == str(uploadedFile.name): modtime = datetime.fromtimestamp(int(v) / 1000) break if modtime: localized_time = form_tz.localize(modtime) exifTime = TimeUtil.timeZoneToUtc(localized_time) if not exifTime: exifTime = datetime.now(pytz.utc) # create a new image set instance author = None if request.user.is_authenticated(): author = request.user # set user as image author elif "username" in request.POST: try: username = str(request.POST["username"]) author = User.objects.get(username=username) except: author = User.objects.get(username="******") newImageSet = IMAGE_SET_MODEL.get()() newImageSet.acquisition_time = exifTime newImageSet.acquisition_timezone = form.getTimezoneName() fileName = uploadedFile.name newImageSet.name = fileName newImageSet.camera = getCameraObject(exifData) newImageSet.track_position = getTrackPosition(exifTime, resource) newImageSet.exif_position = buildExifPosition(exifData, newImageSet.camera, resource, exifTime, form_tz) newImageSet.author = author newImageSet.resource = resource newImageSet.finish_initialization(request) nowTime = time.time() uploadAndSaveTime = nowTime - timeMark newImageSet.uploadAndSaveTime = uploadAndSaveTime overallStartTime = cache.get("imageAutoloadGlobalTimeMark", None) if overallStartTime: totalTimeSinceNotify = nowTime - float(overallStartTime) newImageSet.totalTimeSinceNotify = totalTimeSinceNotify newImageSet.save() # link the "image set" to "image". newImage.imageSet = newImageSet newImage.save() # create a thumbnail thumbnailStream = createThumbnailFile(newImage.file) SINGLE_IMAGE_MODEL.get().objects.create( file=thumbnailStream, raw=False, thumbnail=True, imageSet=newImageSet ) # create deep zoom tiles for viewing in openseadragon. if newImageSet.create_deepzoom: deepzoomTilingThread = Thread(target=newImageSet.create_deepzoom_image) deepzoomTilingThread.start() # newImageSet.create_deepzoom_image() imageSetDict = newImageSet.toMapDict() # pass the image set to the client as json. return HttpResponse( json.dumps({"success": "true", "json": imageSetDict}, cls=DatetimeJsonEncoder), content_type="application/json", ) else: return HttpResponse( json.dumps({"error": "Imported image is not valid", "details": form.errors}), content_type="application/json", )
def saveImage(request): """ Image drag and drop, saves the files and to the database. """ if request.method == 'POST': timeMark = time.time() form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): # create and save a single image obj uploadedFile = request.FILES['file'] newSingleImage = SINGLE_IMAGE_MODEL.get()(file=uploadedFile) form_tz = form.getTimezone() resource = form.getResource() exifData = getExifData(newSingleImage) # save image dimensions and file size try: newSingleImage.width = int( getExifValue(exifData, 'ExifImageWidth')) newSingleImage.height = int( getExifValue(exifData, 'ExifImageHeight')) except: pass newSingleImage.fileSizeBytes = uploadedFile.size # get exif time exifTime = None exifTimeString = getExifValue(exifData, 'DateTimeOriginal') if not exifTimeString: exifTimeString = getExifValue(exifData, 'DateTime') if exifTimeString: exifTime = datetime.strptime(str(exifTimeString), '%Y:%m:%d %H:%M:%S') if (form_tz != pytz.utc) and exifTime: localized_time = form_tz.localize(exifTime) exifTime = TimeUtil.timeZoneToUtc(localized_time) else: exifTime = exifTime.replace(tzinfo=pytz.utc) else: # read the time from the last modified time that we pushed in from imageUpload.js if 'HTTP_LASTMOD' in request.META: modtimesString = request.META['HTTP_LASTMOD'] if modtimesString: modtime = None theImages = modtimesString.split(',') for i in theImages: k, v = i.split('||') if k == str(uploadedFile.name): modtime = datetime.fromtimestamp(int(v) / 1000) break if modtime: localized_time = form_tz.localize(modtime) exifTime = TimeUtil.timeZoneToUtc(localized_time) if not exifTime: exifTime = datetime.now(pytz.utc) # create a new image set instance author = None if request.user.is_authenticated(): author = request.user # set user as image author elif 'username' in request.POST: try: username = str(request.POST['username']) author = User.objects.get(username=username) except: author = User.objects.get(username='******') if 'object_id' in request.POST: newImageSet = IMAGE_SET_MODEL.get()( pk=int(request.POST['object_id'])) else: newImageSet = IMAGE_SET_MODEL.get()() newImageSet.acquisition_time = exifTime newImageSet.acquisition_timezone = form.getTimezoneName() fileName = uploadedFile.name newImageSet.name = fileName newImageSet.camera = getCameraObject(exifData) newImageSet.track_position = getTrackPosition(exifTime, resource) newImageSet.exif_position = buildExifPosition( exifData, newImageSet.camera, resource, exifTime, form_tz) newImageSet.author = author newImageSet.resource = resource newImageSet.finish_initialization(request) nowTime = time.time() uploadAndSaveTime = nowTime - timeMark newImageSet.uploadAndSaveTime = uploadAndSaveTime overallStartTime = cache.get("imageAutoloadGlobalTimeMark", None) if overallStartTime: totalTimeSinceNotify = nowTime - float(overallStartTime) newImageSet.totalTimeSinceNotify = totalTimeSinceNotify newImageSet.save() # link the "image set" to "image". newSingleImage.imageSet = newImageSet newSingleImage.save() # relay if needed if 'relay' in request.POST: # create the record for the datum # fire a message for new data deletePostKey(request.POST, 'relay') addRelay(newImageSet, request.FILES, json.dumps(request.POST), reverse('xgds_save_image')) # create a thumbnail thumbnailStream = createThumbnailFile(newSingleImage.file) SINGLE_IMAGE_MODEL.get().objects.create(file=thumbnailStream, raw=False, thumbnail=True, imageSet=newImageSet) # create deep zoom tiles for viewing in openseadragon. if (newImageSet.create_deepzoom): deepzoomTilingThread = Thread( target=newImageSet.create_deepzoom_image) deepzoomTilingThread.start() # newImageSet.create_deepzoom_image() imageSetDict = newImageSet.toMapDict() # pass the image set to the client as json. return HttpResponse(json.dumps( { 'success': 'true', 'json': imageSetDict }, cls=DatetimeJsonEncoder), content_type='application/json') else: return HttpResponse(json.dumps({ 'error': 'Imported image is not valid', 'details': form.errors }), content_type='application/json')